From dca11e6c41b727ffc8adbecdcab8bb63cc544108 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 2 Oct 2024 09:40:54 +0200 Subject: [PATCH] loop: remove extra allocation We don't actually need the extra allocation for the tss. We can just mark the queue as being in the tss. When a queue is destroyed, mark it as destroyed but when it is still in the tss, don't free the structure yet. We free the structure when we destroy the tss. We can also free the overflow queues of a queue when it is destroyed immediately. --- spa/plugins/support/loop.c | 58 ++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/spa/plugins/support/loop.c b/spa/plugins/support/loop.c index 6d1c0cb5f..b2677635a 100644 --- a/spa/plugins/support/loop.c +++ b/spa/plugins/support/loop.c @@ -91,7 +91,8 @@ struct queue { int ack_fd; struct spa_ratelimit rate_limit; - struct queue **tss_queue; + bool destroyed; + bool in_tss; struct spa_ringbuffer buffer; uint8_t *buffer_data; @@ -412,48 +413,45 @@ static void loop_queue_destroy(void *data) struct queue *queue = data; struct impl *impl = queue->impl; - pthread_mutex_lock(&impl->queue_lock); - spa_list_remove(&queue->link); - pthread_mutex_unlock(&impl->queue_lock); + if (!queue->destroyed) { + queue->destroyed = true; - if (queue->flags & QUEUE_FLAG_ACK_FD) - spa_system_close(impl->system, queue->ack_fd); - if (queue->tss_queue) - *queue->tss_queue = NULL; - free(queue); + pthread_mutex_lock(&impl->queue_lock); + spa_list_remove(&queue->link); + pthread_mutex_unlock(&impl->queue_lock); + + if (queue->overflow) + loop_queue_destroy(queue->overflow); + + if (queue->flags & QUEUE_FLAG_ACK_FD) + spa_system_close(impl->system, queue->ack_fd); + } + if (!queue->in_tss) + free(queue); } static void loop_queue_destroy_tss(void *data) { - struct queue **qp = data; - if (*qp) - loop_queue_destroy(*qp); - free(qp); + struct queue *queue = data; + if (queue) { + queue->in_tss = false; + loop_queue_destroy(queue); + } } static int loop_invoke(void *object, spa_invoke_func_t func, uint32_t seq, const void *data, size_t size, bool block, void *user_data) { struct impl *impl = object; - struct queue *local_queue, **qp; - - qp = tss_get(impl->queue_tss_id); - if (qp == NULL) { - qp = malloc(sizeof(struct queue **)); - if (qp == NULL) - return -errno; + struct queue *local_queue; + local_queue = tss_get(impl->queue_tss_id); + if (local_queue == NULL) { local_queue = loop_create_queue(impl, QUEUE_FLAG_ACK_FD); - if (local_queue == NULL) { - free(qp); + if (local_queue == NULL) return -errno; - } - *qp = local_queue; - local_queue->tss_queue = qp; - tss_set(impl->queue_tss_id, qp); - } else { - if ((local_queue = *qp) == NULL) - return -ESTALE; + local_queue->in_tss = true; + tss_set(impl->queue_tss_id, local_queue); } return loop_queue_invoke(local_queue, func, seq, data, size, block, user_data); } @@ -1102,7 +1100,7 @@ static int impl_clear(struct spa_handle *handle) loop_queue_destroy(queue); /* free the tss from this thread if any */ - free(tss_get(impl->queue_tss_id)); + loop_queue_destroy_tss(tss_get(impl->queue_tss_id)); spa_system_close(impl->system, impl->poll_fd); pthread_mutex_destroy(&impl->queue_lock);