ck_fifo_spsc: Fix implementation.

Do not be overly pedantic. Fix misplaced store
barrier and make sure to atomically load stub
pointer on reader side.
ck_pring
Samy Al Bahra 12 years ago
parent 80c56d115b
commit 78f00eeeb6

@ -105,11 +105,9 @@ ck_fifo_spsc_init(struct ck_fifo_spsc *fifo, struct ck_fifo_spsc_entry *stub)
ck_spinlock_init(&fifo->m_head); ck_spinlock_init(&fifo->m_head);
ck_spinlock_init(&fifo->m_tail); ck_spinlock_init(&fifo->m_tail);
ck_pr_store_ptr(&stub->next, NULL);
ck_pr_store_ptr(&fifo->head, stub); stub->next = NULL;
ck_pr_store_ptr(&fifo->tail, stub); fifo->head = fifo->tail = fifo->head_snapshot = fifo->garbage = stub;
ck_pr_store_ptr(&fifo->head_snapshot, stub);
ck_pr_store_ptr(&fifo->garbage, stub);
return; return;
} }
@ -119,11 +117,13 @@ ck_fifo_spsc_enqueue(struct ck_fifo_spsc *fifo,
void *value) void *value)
{ {
ck_pr_store_ptr(&entry->value, value); entry->value = value;
ck_pr_store_ptr(&entry->next, NULL); entry->next = NULL;
ck_pr_store_ptr(&fifo->tail->next, entry);
/* If stub->next is visible, guarantee that entry is consistent. */
ck_pr_fence_store(); ck_pr_fence_store();
ck_pr_store_ptr(&fifo->tail, entry); ck_pr_store_ptr(&fifo->tail->next, entry);
fifo->tail = entry;
return; return;
} }
@ -138,15 +138,14 @@ ck_fifo_spsc_dequeue(struct ck_fifo_spsc *fifo, void *value)
* If the stub entry does not point to an entry, then the queue is * If the stub entry does not point to an entry, then the queue is
* empty. * empty.
*/ */
stub = ck_pr_load_ptr(&fifo->head); entry = ck_pr_load_ptr(&fifo->head->next);
ck_pr_fence_load();
entry = stub->next;
if (entry == NULL) if (entry == NULL)
return (false); return (false);
store = ck_pr_load_ptr(&entry->value); /* If entry is visible, guarantee store to value is visible. */
ck_pr_store_ptr(value, store); ck_pr_fence_load();
ck_pr_store_ptr(&fifo->head, entry); ck_pr_store_ptr(value, entry->value);
fifo->head = entry;
return (true); return (true);
} }
@ -157,21 +156,17 @@ ck_fifo_spsc_dequeue(struct ck_fifo_spsc *fifo, void *value)
CK_CC_INLINE static struct ck_fifo_spsc_entry * CK_CC_INLINE static struct ck_fifo_spsc_entry *
ck_fifo_spsc_recycle(struct ck_fifo_spsc *fifo) ck_fifo_spsc_recycle(struct ck_fifo_spsc *fifo)
{ {
struct ck_fifo_spsc_entry *p, *garbage; struct ck_fifo_spsc_entry *garbage;
garbage = ck_pr_load_ptr(&fifo->garbage);
p = ck_pr_load_ptr(&fifo->head_snapshot);
if (garbage == p) { if (fifo->head_snapshot == fifo->garbage) {
p = ck_pr_load_ptr(&fifo->head); fifo->head_snapshot = ck_pr_load_ptr(&fifo->head);
ck_pr_store_ptr(&fifo->head_snapshot, p); if (fifo->head_snapshot == fifo->garbage)
if (garbage == p) return NULL;
return (NULL);
} }
p = garbage; garbage = fifo->garbage;
ck_pr_store_ptr(&fifo->garbage, garbage->next); fifo->garbage = garbage->next;
return (p); return (garbage);
} }
CK_CC_INLINE static bool CK_CC_INLINE static bool

Loading…
Cancel
Save