mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
atomicqueue: fix subtle race
Fix a race where the reader would see the updated the tail pointer before the write could write the data into the queue. Fix this by having a separate reader tail pointer that is only incremented after the writer wrote the data.
This commit is contained in:
parent
beea57dca7
commit
61e8fa0dc5
1 changed files with 8 additions and 3 deletions
|
@ -57,6 +57,7 @@ struct _GstAQueueMem
|
|||
gpointer *array;
|
||||
volatile gint head;
|
||||
volatile gint tail;
|
||||
volatile gint tail_read;
|
||||
GstAQueueMem *next;
|
||||
GstAQueueMem *free;
|
||||
};
|
||||
|
@ -84,6 +85,7 @@ new_queue_mem (guint size, gint pos)
|
|||
mem->array = g_new0 (gpointer, mem->size + 1);
|
||||
mem->head = pos;
|
||||
mem->tail = pos;
|
||||
mem->tail_read = pos;
|
||||
mem->next = NULL;
|
||||
mem->free = NULL;
|
||||
|
||||
|
@ -234,7 +236,7 @@ gst_atomic_queue_peek (GstAtomicQueue * queue)
|
|||
head_mem = g_atomic_pointer_get (&queue->head_mem);
|
||||
|
||||
head = g_atomic_int_get (&head_mem->head);
|
||||
tail = g_atomic_int_get (&head_mem->tail);
|
||||
tail = g_atomic_int_get (&head_mem->tail_read);
|
||||
size = head_mem->size;
|
||||
|
||||
/* when we are not empty, we can continue */
|
||||
|
@ -291,7 +293,7 @@ gst_atomic_queue_pop (GstAtomicQueue * queue)
|
|||
head_mem = g_atomic_pointer_get (&queue->head_mem);
|
||||
|
||||
head = g_atomic_int_get (&head_mem->head);
|
||||
tail = g_atomic_int_get (&head_mem->tail);
|
||||
tail = g_atomic_int_get (&head_mem->tail_read);
|
||||
size = head_mem->size;
|
||||
|
||||
/* when we are not empty, we can continue */
|
||||
|
@ -380,6 +382,9 @@ gst_atomic_queue_push (GstAtomicQueue * queue, gpointer data)
|
|||
tail + 1));
|
||||
|
||||
tail_mem->array[tail & size] = data;
|
||||
|
||||
/* and now the readers can read */
|
||||
g_atomic_int_inc (&tail_mem->tail_read);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,7 +413,7 @@ gst_atomic_queue_length (GstAtomicQueue * queue)
|
|||
head = g_atomic_int_get (&head_mem->head);
|
||||
|
||||
tail_mem = g_atomic_pointer_get (&queue->tail_mem);
|
||||
tail = g_atomic_int_get (&tail_mem->tail);
|
||||
tail = g_atomic_int_get (&tail_mem->tail_read);
|
||||
|
||||
#ifdef LOW_MEM
|
||||
if (g_atomic_int_dec_and_test (&queue->num_readers))
|
||||
|
|
Loading…
Reference in a new issue