ck_ring: Various improvements to readability.

No regressions in unit tests, so I'm dropping volatile
semantics for unnecessary volatile load/store on producer/consumer
side.
ck_pring
Samy Al Bahra 12 years ago
parent 290add2e50
commit ad5e143bd5

@ -53,6 +53,7 @@
struct type *buffer, \ struct type *buffer, \
unsigned int size) \ unsigned int size) \
{ \ { \
\
ck_pr_store_uint(&ring->size, size); \ ck_pr_store_uint(&ring->size, size); \
ck_pr_store_uint(&ring->mask, size - 1); \ ck_pr_store_uint(&ring->mask, size - 1); \
ck_pr_store_uint(&ring->p_tail, 0); \ ck_pr_store_uint(&ring->p_tail, 0); \
@ -82,13 +83,13 @@
unsigned int consumer, producer; \ unsigned int consumer, producer; \
\ \
consumer = ck_pr_load_uint(&ring->c_head); \ consumer = ck_pr_load_uint(&ring->c_head); \
producer = ck_pr_load_uint(&ring->p_tail); \ producer = ring->p_tail; \
\ \
if (((producer + 1) & ring->mask) == consumer) \ if (((producer + 1) & ring->mask) == consumer) \
return (false); \ return (false); \
\ \
ring->ring[producer] = *entry; \ ring->ring[producer] = *entry; \
ck_pr_fence_store(); \ ck_pr_fence_memory(); \
ck_pr_store_uint(&ring->p_tail, (producer + 1) & ring->mask); \ ck_pr_store_uint(&ring->p_tail, (producer + 1) & ring->mask); \
\ \
return (true); \ return (true); \
@ -99,7 +100,7 @@
{ \ { \
unsigned int consumer, producer; \ unsigned int consumer, producer; \
\ \
consumer = ck_pr_load_uint(&ring->c_head); \ consumer = ring->c_head; \
producer = ck_pr_load_uint(&ring->p_tail); \ producer = ck_pr_load_uint(&ring->p_tail); \
\ \
if (consumer == producer) \ if (consumer == producer) \
@ -154,7 +155,7 @@ CK_CC_INLINE static unsigned int
ck_ring_capacity(struct ck_ring *ring) ck_ring_capacity(struct ck_ring *ring)
{ {
return ck_pr_load_uint(&ring->size); return ring->size;
} }
CK_CC_INLINE static bool CK_CC_INLINE static bool
@ -163,15 +164,19 @@ ck_ring_enqueue_spsc(struct ck_ring *ring, void *entry)
unsigned int consumer, producer; unsigned int consumer, producer;
consumer = ck_pr_load_uint(&ring->c_head); consumer = ck_pr_load_uint(&ring->c_head);
producer = ck_pr_load_uint(&ring->p_tail); producer = ring->p_tail;
if (((producer + 1) & ring->mask) == consumer) if (((producer + 1) & ring->mask) == consumer)
return (false); return (false);
ck_pr_store_ptr(&ring->ring[producer], entry); ring->ring[producer] = entry;
/*
* Make sure to update slot value before indicating
* that the slot is available for consumption.
*/
ck_pr_fence_store(); ck_pr_fence_store();
ck_pr_store_uint(&ring->p_tail, (producer + 1) & ring->mask); ck_pr_store_uint(&ring->p_tail, (producer + 1) & ring->mask);
return (true); return (true);
} }
@ -182,19 +187,33 @@ CK_CC_INLINE static bool
ck_ring_dequeue_spsc(struct ck_ring *ring, void *data) ck_ring_dequeue_spsc(struct ck_ring *ring, void *data)
{ {
unsigned int consumer, producer; unsigned int consumer, producer;
void *value;
consumer = ck_pr_load_uint(&ring->c_head); consumer = ring->c_head;
producer = ck_pr_load_uint(&ring->p_tail); producer = ck_pr_load_uint(&ring->p_tail);
if (consumer == producer) if (consumer == producer)
return (false); return (false);
/*
* Make sure to serialize with respect to our snapshot
* of the producer counter.
*/
ck_pr_fence_load(); ck_pr_fence_load();
value = ck_pr_load_ptr(ring->ring + consumer);
ck_pr_store_ptr(data, value);
ck_pr_store_uint(&ring->c_head, (consumer + 1) & ring->mask);
/*
* This is used to work-around aliasing issues (C
* lacks a generic pointer to pointer despite it
* being a reality on POSIX). This interface is
* troublesome on platforms where sizeof(void *)
* is not guaranteed to be sizeof(T *).
*
* It is guaranteed that the value of
* ring->ring[consumer] is either in *data or aliased
* to some location whose value is to be stored in data
* before this operation completes.
*/
ck_pr_store_ptr(data, ring->ring[consumer]);
ck_pr_store_uint(&ring->c_head, (consumer + 1) & ring->mask);
return (true); return (true);
} }

Loading…
Cancel
Save