11fb62fb0SOlivier Houchard /*
21fb62fb0SOlivier Houchard * Copyright 2009-2015 Samy Al Bahra.
31fb62fb0SOlivier Houchard * All rights reserved.
41fb62fb0SOlivier Houchard *
51fb62fb0SOlivier Houchard * Redistribution and use in source and binary forms, with or without
61fb62fb0SOlivier Houchard * modification, are permitted provided that the following conditions
71fb62fb0SOlivier Houchard * are met:
81fb62fb0SOlivier Houchard * 1. Redistributions of source code must retain the above copyright
91fb62fb0SOlivier Houchard * notice, this list of conditions and the following disclaimer.
101fb62fb0SOlivier Houchard * 2. Redistributions in binary form must reproduce the above copyright
111fb62fb0SOlivier Houchard * notice, this list of conditions and the following disclaimer in the
121fb62fb0SOlivier Houchard * documentation and/or other materials provided with the distribution.
131fb62fb0SOlivier Houchard *
141fb62fb0SOlivier Houchard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151fb62fb0SOlivier Houchard * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161fb62fb0SOlivier Houchard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171fb62fb0SOlivier Houchard * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181fb62fb0SOlivier Houchard * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191fb62fb0SOlivier Houchard * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201fb62fb0SOlivier Houchard * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211fb62fb0SOlivier Houchard * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221fb62fb0SOlivier Houchard * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231fb62fb0SOlivier Houchard * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241fb62fb0SOlivier Houchard * SUCH DAMAGE.
251fb62fb0SOlivier Houchard */
261fb62fb0SOlivier Houchard
271fb62fb0SOlivier Houchard #ifndef CK_RING_H
281fb62fb0SOlivier Houchard #define CK_RING_H
291fb62fb0SOlivier Houchard
301fb62fb0SOlivier Houchard #include <ck_cc.h>
311fb62fb0SOlivier Houchard #include <ck_md.h>
321fb62fb0SOlivier Houchard #include <ck_pr.h>
331fb62fb0SOlivier Houchard #include <ck_stdbool.h>
341fb62fb0SOlivier Houchard #include <ck_string.h>
351fb62fb0SOlivier Houchard
361fb62fb0SOlivier Houchard /*
371fb62fb0SOlivier Houchard * Concurrent ring buffer.
381fb62fb0SOlivier Houchard */
391fb62fb0SOlivier Houchard
401fb62fb0SOlivier Houchard struct ck_ring {
411fb62fb0SOlivier Houchard unsigned int c_head;
421fb62fb0SOlivier Houchard char pad[CK_MD_CACHELINE - sizeof(unsigned int)];
431fb62fb0SOlivier Houchard unsigned int p_tail;
441fb62fb0SOlivier Houchard unsigned int p_head;
451fb62fb0SOlivier Houchard char _pad[CK_MD_CACHELINE - sizeof(unsigned int) * 2];
461fb62fb0SOlivier Houchard unsigned int size;
471fb62fb0SOlivier Houchard unsigned int mask;
481fb62fb0SOlivier Houchard };
491fb62fb0SOlivier Houchard typedef struct ck_ring ck_ring_t;
501fb62fb0SOlivier Houchard
511fb62fb0SOlivier Houchard struct ck_ring_buffer {
521fb62fb0SOlivier Houchard void *value;
531fb62fb0SOlivier Houchard };
541fb62fb0SOlivier Houchard typedef struct ck_ring_buffer ck_ring_buffer_t;
551fb62fb0SOlivier Houchard
561fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_ring_size(const struct ck_ring * ring)571fb62fb0SOlivier Houchard ck_ring_size(const struct ck_ring *ring)
581fb62fb0SOlivier Houchard {
591fb62fb0SOlivier Houchard unsigned int c, p;
601fb62fb0SOlivier Houchard
611fb62fb0SOlivier Houchard c = ck_pr_load_uint(&ring->c_head);
621fb62fb0SOlivier Houchard p = ck_pr_load_uint(&ring->p_tail);
631fb62fb0SOlivier Houchard return (p - c) & ring->mask;
641fb62fb0SOlivier Houchard }
651fb62fb0SOlivier Houchard
661fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_ring_capacity(const struct ck_ring * ring)671fb62fb0SOlivier Houchard ck_ring_capacity(const struct ck_ring *ring)
681fb62fb0SOlivier Houchard {
69*74e9b5f2SOlivier Houchard
701fb62fb0SOlivier Houchard return ring->size;
711fb62fb0SOlivier Houchard }
721fb62fb0SOlivier Houchard
73*74e9b5f2SOlivier Houchard /*
74*74e9b5f2SOlivier Houchard * This function is only safe to call when there are no concurrent operations
75*74e9b5f2SOlivier Houchard * on the ring. This is primarily meant for persistent ck_ring use-cases. The
76*74e9b5f2SOlivier Houchard * function returns true if any mutations were performed on the ring.
77*74e9b5f2SOlivier Houchard */
78*74e9b5f2SOlivier Houchard CK_CC_INLINE static bool
ck_ring_repair(struct ck_ring * ring)79*74e9b5f2SOlivier Houchard ck_ring_repair(struct ck_ring *ring)
80*74e9b5f2SOlivier Houchard {
81*74e9b5f2SOlivier Houchard bool r = false;
82*74e9b5f2SOlivier Houchard
83*74e9b5f2SOlivier Houchard if (ring->p_tail != ring->p_head) {
84*74e9b5f2SOlivier Houchard ring->p_tail = ring->p_head;
85*74e9b5f2SOlivier Houchard r = true;
86*74e9b5f2SOlivier Houchard }
87*74e9b5f2SOlivier Houchard
88*74e9b5f2SOlivier Houchard return r;
89*74e9b5f2SOlivier Houchard }
90*74e9b5f2SOlivier Houchard
91*74e9b5f2SOlivier Houchard /*
92*74e9b5f2SOlivier Houchard * This can be called when no concurrent updates are occurring on the ring
93*74e9b5f2SOlivier Houchard * structure to check for consistency. This is primarily meant to be used for
94*74e9b5f2SOlivier Houchard * persistent storage of the ring. If this functions returns false, the ring
95*74e9b5f2SOlivier Houchard * is in an inconsistent state.
96*74e9b5f2SOlivier Houchard */
97*74e9b5f2SOlivier Houchard CK_CC_INLINE static bool
ck_ring_valid(const struct ck_ring * ring)98*74e9b5f2SOlivier Houchard ck_ring_valid(const struct ck_ring *ring)
99*74e9b5f2SOlivier Houchard {
100*74e9b5f2SOlivier Houchard unsigned int size = ring->size;
101*74e9b5f2SOlivier Houchard unsigned int c_head = ring->c_head;
102*74e9b5f2SOlivier Houchard unsigned int p_head = ring->p_head;
103*74e9b5f2SOlivier Houchard
104*74e9b5f2SOlivier Houchard /* The ring must be a power of 2. */
105*74e9b5f2SOlivier Houchard if (size & (size - 1))
106*74e9b5f2SOlivier Houchard return false;
107*74e9b5f2SOlivier Houchard
108*74e9b5f2SOlivier Houchard /* The consumer counter must always be smaller than the producer. */
109*74e9b5f2SOlivier Houchard if (c_head > p_head)
110*74e9b5f2SOlivier Houchard return false;
111*74e9b5f2SOlivier Houchard
112*74e9b5f2SOlivier Houchard /* The producer may only be up to size slots ahead of consumer. */
113*74e9b5f2SOlivier Houchard if (p_head - c_head >= size)
114*74e9b5f2SOlivier Houchard return false;
115*74e9b5f2SOlivier Houchard
116*74e9b5f2SOlivier Houchard return true;
117*74e9b5f2SOlivier Houchard }
118*74e9b5f2SOlivier Houchard
1191fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_ring_init(struct ck_ring * ring,unsigned int size)1201fb62fb0SOlivier Houchard ck_ring_init(struct ck_ring *ring, unsigned int size)
1211fb62fb0SOlivier Houchard {
1221fb62fb0SOlivier Houchard
1231fb62fb0SOlivier Houchard ring->size = size;
1241fb62fb0SOlivier Houchard ring->mask = size - 1;
1251fb62fb0SOlivier Houchard ring->p_tail = 0;
1261fb62fb0SOlivier Houchard ring->p_head = 0;
1271fb62fb0SOlivier Houchard ring->c_head = 0;
1281fb62fb0SOlivier Houchard return;
1291fb62fb0SOlivier Houchard }
1301fb62fb0SOlivier Houchard
1311fb62fb0SOlivier Houchard /*
1321fb62fb0SOlivier Houchard * The _ck_ring_* namespace is internal only and must not used externally.
1331fb62fb0SOlivier Houchard */
134*74e9b5f2SOlivier Houchard
135*74e9b5f2SOlivier Houchard /*
136*74e9b5f2SOlivier Houchard * This function will return a region of memory to write for the next value
137*74e9b5f2SOlivier Houchard * for a single producer.
138*74e9b5f2SOlivier Houchard */
139*74e9b5f2SOlivier Houchard CK_CC_FORCE_INLINE static void *
_ck_ring_enqueue_reserve_sp(struct ck_ring * ring,void * CK_CC_RESTRICT buffer,unsigned int ts,unsigned int * size)140*74e9b5f2SOlivier Houchard _ck_ring_enqueue_reserve_sp(struct ck_ring *ring,
141*74e9b5f2SOlivier Houchard void *CK_CC_RESTRICT buffer,
142*74e9b5f2SOlivier Houchard unsigned int ts,
143*74e9b5f2SOlivier Houchard unsigned int *size)
144*74e9b5f2SOlivier Houchard {
145*74e9b5f2SOlivier Houchard const unsigned int mask = ring->mask;
146*74e9b5f2SOlivier Houchard unsigned int consumer, producer, delta;
147*74e9b5f2SOlivier Houchard
148*74e9b5f2SOlivier Houchard consumer = ck_pr_load_uint(&ring->c_head);
149*74e9b5f2SOlivier Houchard producer = ring->p_tail;
150*74e9b5f2SOlivier Houchard delta = producer + 1;
151*74e9b5f2SOlivier Houchard if (size != NULL)
152*74e9b5f2SOlivier Houchard *size = (producer - consumer) & mask;
153*74e9b5f2SOlivier Houchard
154*74e9b5f2SOlivier Houchard if (CK_CC_UNLIKELY((delta & mask) == (consumer & mask)))
155*74e9b5f2SOlivier Houchard return NULL;
156*74e9b5f2SOlivier Houchard
157*74e9b5f2SOlivier Houchard return (char *)buffer + ts * (producer & mask);
158*74e9b5f2SOlivier Houchard }
159*74e9b5f2SOlivier Houchard
160*74e9b5f2SOlivier Houchard /*
161*74e9b5f2SOlivier Houchard * This is to be called to commit and make visible a region of previously
162*74e9b5f2SOlivier Houchard * reserved with reverse_sp.
163*74e9b5f2SOlivier Houchard */
164*74e9b5f2SOlivier Houchard CK_CC_FORCE_INLINE static void
_ck_ring_enqueue_commit_sp(struct ck_ring * ring)165*74e9b5f2SOlivier Houchard _ck_ring_enqueue_commit_sp(struct ck_ring *ring)
166*74e9b5f2SOlivier Houchard {
167*74e9b5f2SOlivier Houchard
168*74e9b5f2SOlivier Houchard ck_pr_fence_store();
169*74e9b5f2SOlivier Houchard ck_pr_store_uint(&ring->p_tail, ring->p_tail + 1);
170*74e9b5f2SOlivier Houchard return;
171*74e9b5f2SOlivier Houchard }
172*74e9b5f2SOlivier Houchard
1731fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_enqueue_sp(struct ck_ring * ring,void * CK_CC_RESTRICT buffer,const void * CK_CC_RESTRICT entry,unsigned int ts,unsigned int * size)1741fb62fb0SOlivier Houchard _ck_ring_enqueue_sp(struct ck_ring *ring,
1751fb62fb0SOlivier Houchard void *CK_CC_RESTRICT buffer,
1761fb62fb0SOlivier Houchard const void *CK_CC_RESTRICT entry,
1771fb62fb0SOlivier Houchard unsigned int ts,
1781fb62fb0SOlivier Houchard unsigned int *size)
1791fb62fb0SOlivier Houchard {
1801fb62fb0SOlivier Houchard const unsigned int mask = ring->mask;
1811fb62fb0SOlivier Houchard unsigned int consumer, producer, delta;
1821fb62fb0SOlivier Houchard
1831fb62fb0SOlivier Houchard consumer = ck_pr_load_uint(&ring->c_head);
1841fb62fb0SOlivier Houchard producer = ring->p_tail;
1851fb62fb0SOlivier Houchard delta = producer + 1;
1861fb62fb0SOlivier Houchard if (size != NULL)
1871fb62fb0SOlivier Houchard *size = (producer - consumer) & mask;
1881fb62fb0SOlivier Houchard
1891fb62fb0SOlivier Houchard if (CK_CC_UNLIKELY((delta & mask) == (consumer & mask)))
1901fb62fb0SOlivier Houchard return false;
1911fb62fb0SOlivier Houchard
1921fb62fb0SOlivier Houchard buffer = (char *)buffer + ts * (producer & mask);
1931fb62fb0SOlivier Houchard memcpy(buffer, entry, ts);
1941fb62fb0SOlivier Houchard
1951fb62fb0SOlivier Houchard /*
1961fb62fb0SOlivier Houchard * Make sure to update slot value before indicating
1971fb62fb0SOlivier Houchard * that the slot is available for consumption.
1981fb62fb0SOlivier Houchard */
1991fb62fb0SOlivier Houchard ck_pr_fence_store();
2001fb62fb0SOlivier Houchard ck_pr_store_uint(&ring->p_tail, delta);
2011fb62fb0SOlivier Houchard return true;
2021fb62fb0SOlivier Houchard }
2031fb62fb0SOlivier Houchard
2041fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_enqueue_sp_size(struct ck_ring * ring,void * CK_CC_RESTRICT buffer,const void * CK_CC_RESTRICT entry,unsigned int ts,unsigned int * size)2051fb62fb0SOlivier Houchard _ck_ring_enqueue_sp_size(struct ck_ring *ring,
2061fb62fb0SOlivier Houchard void *CK_CC_RESTRICT buffer,
2071fb62fb0SOlivier Houchard const void *CK_CC_RESTRICT entry,
2081fb62fb0SOlivier Houchard unsigned int ts,
2091fb62fb0SOlivier Houchard unsigned int *size)
2101fb62fb0SOlivier Houchard {
2111fb62fb0SOlivier Houchard unsigned int sz;
2121fb62fb0SOlivier Houchard bool r;
2131fb62fb0SOlivier Houchard
2141fb62fb0SOlivier Houchard r = _ck_ring_enqueue_sp(ring, buffer, entry, ts, &sz);
2151fb62fb0SOlivier Houchard *size = sz;
2161fb62fb0SOlivier Houchard return r;
2171fb62fb0SOlivier Houchard }
2181fb62fb0SOlivier Houchard
2191fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_dequeue_sc(struct ck_ring * ring,const void * CK_CC_RESTRICT buffer,void * CK_CC_RESTRICT target,unsigned int size)2201fb62fb0SOlivier Houchard _ck_ring_dequeue_sc(struct ck_ring *ring,
2211fb62fb0SOlivier Houchard const void *CK_CC_RESTRICT buffer,
2221fb62fb0SOlivier Houchard void *CK_CC_RESTRICT target,
2231fb62fb0SOlivier Houchard unsigned int size)
2241fb62fb0SOlivier Houchard {
2251fb62fb0SOlivier Houchard const unsigned int mask = ring->mask;
2261fb62fb0SOlivier Houchard unsigned int consumer, producer;
2271fb62fb0SOlivier Houchard
2281fb62fb0SOlivier Houchard consumer = ring->c_head;
2291fb62fb0SOlivier Houchard producer = ck_pr_load_uint(&ring->p_tail);
2301fb62fb0SOlivier Houchard
2311fb62fb0SOlivier Houchard if (CK_CC_UNLIKELY(consumer == producer))
2321fb62fb0SOlivier Houchard return false;
2331fb62fb0SOlivier Houchard
2341fb62fb0SOlivier Houchard /*
2351fb62fb0SOlivier Houchard * Make sure to serialize with respect to our snapshot
2361fb62fb0SOlivier Houchard * of the producer counter.
2371fb62fb0SOlivier Houchard */
2381fb62fb0SOlivier Houchard ck_pr_fence_load();
2391fb62fb0SOlivier Houchard
2401fb62fb0SOlivier Houchard buffer = (const char *)buffer + size * (consumer & mask);
2411fb62fb0SOlivier Houchard memcpy(target, buffer, size);
2421fb62fb0SOlivier Houchard
2431fb62fb0SOlivier Houchard /*
2441fb62fb0SOlivier Houchard * Make sure copy is completed with respect to consumer
2451fb62fb0SOlivier Houchard * update.
2461fb62fb0SOlivier Houchard */
2471fb62fb0SOlivier Houchard ck_pr_fence_store();
2481fb62fb0SOlivier Houchard ck_pr_store_uint(&ring->c_head, consumer + 1);
2491fb62fb0SOlivier Houchard return true;
2501fb62fb0SOlivier Houchard }
2511fb62fb0SOlivier Houchard
252*74e9b5f2SOlivier Houchard CK_CC_FORCE_INLINE static void *
_ck_ring_enqueue_reserve_mp(struct ck_ring * ring,void * buffer,unsigned int ts,unsigned int * ticket,unsigned int * size)253*74e9b5f2SOlivier Houchard _ck_ring_enqueue_reserve_mp(struct ck_ring *ring,
254*74e9b5f2SOlivier Houchard void *buffer,
255*74e9b5f2SOlivier Houchard unsigned int ts,
256*74e9b5f2SOlivier Houchard unsigned int *ticket,
257*74e9b5f2SOlivier Houchard unsigned int *size)
258*74e9b5f2SOlivier Houchard {
259*74e9b5f2SOlivier Houchard const unsigned int mask = ring->mask;
260*74e9b5f2SOlivier Houchard unsigned int producer, consumer, delta;
261*74e9b5f2SOlivier Houchard
262*74e9b5f2SOlivier Houchard producer = ck_pr_load_uint(&ring->p_head);
263*74e9b5f2SOlivier Houchard
264*74e9b5f2SOlivier Houchard for (;;) {
265*74e9b5f2SOlivier Houchard ck_pr_fence_load();
266*74e9b5f2SOlivier Houchard consumer = ck_pr_load_uint(&ring->c_head);
267*74e9b5f2SOlivier Houchard
268*74e9b5f2SOlivier Houchard delta = producer + 1;
269*74e9b5f2SOlivier Houchard
270*74e9b5f2SOlivier Houchard if (CK_CC_LIKELY((producer - consumer) < mask)) {
271*74e9b5f2SOlivier Houchard if (ck_pr_cas_uint_value(&ring->p_head,
272*74e9b5f2SOlivier Houchard producer, delta, &producer) == true) {
273*74e9b5f2SOlivier Houchard break;
274*74e9b5f2SOlivier Houchard }
275*74e9b5f2SOlivier Houchard } else {
276*74e9b5f2SOlivier Houchard unsigned int new_producer;
277*74e9b5f2SOlivier Houchard
278*74e9b5f2SOlivier Houchard ck_pr_fence_load();
279*74e9b5f2SOlivier Houchard new_producer = ck_pr_load_uint(&ring->p_head);
280*74e9b5f2SOlivier Houchard
281*74e9b5f2SOlivier Houchard if (producer == new_producer) {
282*74e9b5f2SOlivier Houchard if (size != NULL)
283*74e9b5f2SOlivier Houchard *size = (producer - consumer) & mask;
284*74e9b5f2SOlivier Houchard
285*74e9b5f2SOlivier Houchard return false;
286*74e9b5f2SOlivier Houchard }
287*74e9b5f2SOlivier Houchard
288*74e9b5f2SOlivier Houchard producer = new_producer;
289*74e9b5f2SOlivier Houchard }
290*74e9b5f2SOlivier Houchard }
291*74e9b5f2SOlivier Houchard
292*74e9b5f2SOlivier Houchard *ticket = producer;
293*74e9b5f2SOlivier Houchard if (size != NULL)
294*74e9b5f2SOlivier Houchard *size = (producer - consumer) & mask;
295*74e9b5f2SOlivier Houchard
296*74e9b5f2SOlivier Houchard return (char *)buffer + ts * (producer & mask);
297*74e9b5f2SOlivier Houchard }
298*74e9b5f2SOlivier Houchard
299*74e9b5f2SOlivier Houchard CK_CC_FORCE_INLINE static void
_ck_ring_enqueue_commit_mp(struct ck_ring * ring,unsigned int producer)300*74e9b5f2SOlivier Houchard _ck_ring_enqueue_commit_mp(struct ck_ring *ring, unsigned int producer)
301*74e9b5f2SOlivier Houchard {
302*74e9b5f2SOlivier Houchard
303*74e9b5f2SOlivier Houchard while (ck_pr_load_uint(&ring->p_tail) != producer)
304*74e9b5f2SOlivier Houchard ck_pr_stall();
305*74e9b5f2SOlivier Houchard
306*74e9b5f2SOlivier Houchard ck_pr_fence_store();
307*74e9b5f2SOlivier Houchard ck_pr_store_uint(&ring->p_tail, producer + 1);
308*74e9b5f2SOlivier Houchard return;
309*74e9b5f2SOlivier Houchard }
310*74e9b5f2SOlivier Houchard
3111fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_enqueue_mp(struct ck_ring * ring,void * buffer,const void * entry,unsigned int ts,unsigned int * size)3121fb62fb0SOlivier Houchard _ck_ring_enqueue_mp(struct ck_ring *ring,
3131fb62fb0SOlivier Houchard void *buffer,
3141fb62fb0SOlivier Houchard const void *entry,
3151fb62fb0SOlivier Houchard unsigned int ts,
3161fb62fb0SOlivier Houchard unsigned int *size)
3171fb62fb0SOlivier Houchard {
3181fb62fb0SOlivier Houchard const unsigned int mask = ring->mask;
3191fb62fb0SOlivier Houchard unsigned int producer, consumer, delta;
3201fb62fb0SOlivier Houchard bool r = true;
3211fb62fb0SOlivier Houchard
3221fb62fb0SOlivier Houchard producer = ck_pr_load_uint(&ring->p_head);
3231fb62fb0SOlivier Houchard
324271ce402SOlivier Houchard for (;;) {
3251fb62fb0SOlivier Houchard /*
326271ce402SOlivier Houchard * The snapshot of producer must be up to date with respect to
327271ce402SOlivier Houchard * consumer.
3281fb62fb0SOlivier Houchard */
3291fb62fb0SOlivier Houchard ck_pr_fence_load();
3301fb62fb0SOlivier Houchard consumer = ck_pr_load_uint(&ring->c_head);
3311fb62fb0SOlivier Houchard
3321fb62fb0SOlivier Houchard delta = producer + 1;
333271ce402SOlivier Houchard
334271ce402SOlivier Houchard /*
335271ce402SOlivier Houchard * Only try to CAS if the producer is not clearly stale (not
336271ce402SOlivier Houchard * less than consumer) and the buffer is definitely not full.
337271ce402SOlivier Houchard */
338271ce402SOlivier Houchard if (CK_CC_LIKELY((producer - consumer) < mask)) {
339271ce402SOlivier Houchard if (ck_pr_cas_uint_value(&ring->p_head,
340271ce402SOlivier Houchard producer, delta, &producer) == true) {
341271ce402SOlivier Houchard break;
342271ce402SOlivier Houchard }
343271ce402SOlivier Houchard } else {
344271ce402SOlivier Houchard unsigned int new_producer;
345271ce402SOlivier Houchard
346271ce402SOlivier Houchard /*
347271ce402SOlivier Houchard * Slow path. Either the buffer is full or we have a
348271ce402SOlivier Houchard * stale snapshot of p_head. Execute a second read of
349271ce402SOlivier Houchard * p_read that must be ordered wrt the snapshot of
350271ce402SOlivier Houchard * c_head.
351271ce402SOlivier Houchard */
352271ce402SOlivier Houchard ck_pr_fence_load();
353271ce402SOlivier Houchard new_producer = ck_pr_load_uint(&ring->p_head);
354271ce402SOlivier Houchard
355271ce402SOlivier Houchard /*
356271ce402SOlivier Houchard * Only fail if we haven't made forward progress in
357271ce402SOlivier Houchard * production: the buffer must have been full when we
358271ce402SOlivier Houchard * read new_producer (or we wrapped around UINT_MAX
359271ce402SOlivier Houchard * during this iteration).
360271ce402SOlivier Houchard */
361271ce402SOlivier Houchard if (producer == new_producer) {
3621fb62fb0SOlivier Houchard r = false;
3631fb62fb0SOlivier Houchard goto leave;
3641fb62fb0SOlivier Houchard }
365271ce402SOlivier Houchard
366271ce402SOlivier Houchard /*
367271ce402SOlivier Houchard * p_head advanced during this iteration. Try again.
368271ce402SOlivier Houchard */
369271ce402SOlivier Houchard producer = new_producer;
370271ce402SOlivier Houchard }
371271ce402SOlivier Houchard }
3721fb62fb0SOlivier Houchard
3731fb62fb0SOlivier Houchard buffer = (char *)buffer + ts * (producer & mask);
3741fb62fb0SOlivier Houchard memcpy(buffer, entry, ts);
3751fb62fb0SOlivier Houchard
3761fb62fb0SOlivier Houchard /*
3771fb62fb0SOlivier Houchard * Wait until all concurrent producers have completed writing
3781fb62fb0SOlivier Houchard * their data into the ring buffer.
3791fb62fb0SOlivier Houchard */
3801fb62fb0SOlivier Houchard while (ck_pr_load_uint(&ring->p_tail) != producer)
3811fb62fb0SOlivier Houchard ck_pr_stall();
3821fb62fb0SOlivier Houchard
3831fb62fb0SOlivier Houchard /*
3841fb62fb0SOlivier Houchard * Ensure that copy is completed before updating shared producer
3851fb62fb0SOlivier Houchard * counter.
3861fb62fb0SOlivier Houchard */
3871fb62fb0SOlivier Houchard ck_pr_fence_store();
3881fb62fb0SOlivier Houchard ck_pr_store_uint(&ring->p_tail, delta);
3891fb62fb0SOlivier Houchard
3901fb62fb0SOlivier Houchard leave:
3911fb62fb0SOlivier Houchard if (size != NULL)
3921fb62fb0SOlivier Houchard *size = (producer - consumer) & mask;
3931fb62fb0SOlivier Houchard
3941fb62fb0SOlivier Houchard return r;
3951fb62fb0SOlivier Houchard }
3961fb62fb0SOlivier Houchard
3971fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_enqueue_mp_size(struct ck_ring * ring,void * buffer,const void * entry,unsigned int ts,unsigned int * size)3981fb62fb0SOlivier Houchard _ck_ring_enqueue_mp_size(struct ck_ring *ring,
3991fb62fb0SOlivier Houchard void *buffer,
4001fb62fb0SOlivier Houchard const void *entry,
4011fb62fb0SOlivier Houchard unsigned int ts,
4021fb62fb0SOlivier Houchard unsigned int *size)
4031fb62fb0SOlivier Houchard {
4041fb62fb0SOlivier Houchard unsigned int sz;
4051fb62fb0SOlivier Houchard bool r;
4061fb62fb0SOlivier Houchard
4071fb62fb0SOlivier Houchard r = _ck_ring_enqueue_mp(ring, buffer, entry, ts, &sz);
4081fb62fb0SOlivier Houchard *size = sz;
4091fb62fb0SOlivier Houchard return r;
4101fb62fb0SOlivier Houchard }
4111fb62fb0SOlivier Houchard
4121fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_trydequeue_mc(struct ck_ring * ring,const void * buffer,void * data,unsigned int size)4131fb62fb0SOlivier Houchard _ck_ring_trydequeue_mc(struct ck_ring *ring,
4141fb62fb0SOlivier Houchard const void *buffer,
4151fb62fb0SOlivier Houchard void *data,
4161fb62fb0SOlivier Houchard unsigned int size)
4171fb62fb0SOlivier Houchard {
4181fb62fb0SOlivier Houchard const unsigned int mask = ring->mask;
4191fb62fb0SOlivier Houchard unsigned int consumer, producer;
4201fb62fb0SOlivier Houchard
4211fb62fb0SOlivier Houchard consumer = ck_pr_load_uint(&ring->c_head);
4221fb62fb0SOlivier Houchard ck_pr_fence_load();
4231fb62fb0SOlivier Houchard producer = ck_pr_load_uint(&ring->p_tail);
4241fb62fb0SOlivier Houchard
4251fb62fb0SOlivier Houchard if (CK_CC_UNLIKELY(consumer == producer))
4261fb62fb0SOlivier Houchard return false;
4271fb62fb0SOlivier Houchard
4281fb62fb0SOlivier Houchard ck_pr_fence_load();
4291fb62fb0SOlivier Houchard
4301fb62fb0SOlivier Houchard buffer = (const char *)buffer + size * (consumer & mask);
4311fb62fb0SOlivier Houchard memcpy(data, buffer, size);
4321fb62fb0SOlivier Houchard
4331fb62fb0SOlivier Houchard ck_pr_fence_store_atomic();
4341fb62fb0SOlivier Houchard return ck_pr_cas_uint(&ring->c_head, consumer, consumer + 1);
4351fb62fb0SOlivier Houchard }
4361fb62fb0SOlivier Houchard
4371fb62fb0SOlivier Houchard CK_CC_FORCE_INLINE static bool
_ck_ring_dequeue_mc(struct ck_ring * ring,const void * buffer,void * data,unsigned int ts)4381fb62fb0SOlivier Houchard _ck_ring_dequeue_mc(struct ck_ring *ring,
4391fb62fb0SOlivier Houchard const void *buffer,
4401fb62fb0SOlivier Houchard void *data,
4411fb62fb0SOlivier Houchard unsigned int ts)
4421fb62fb0SOlivier Houchard {
4431fb62fb0SOlivier Houchard const unsigned int mask = ring->mask;
4441fb62fb0SOlivier Houchard unsigned int consumer, producer;
4451fb62fb0SOlivier Houchard
4461fb62fb0SOlivier Houchard consumer = ck_pr_load_uint(&ring->c_head);
4471fb62fb0SOlivier Houchard
4481fb62fb0SOlivier Houchard do {
4491fb62fb0SOlivier Houchard const char *target;
4501fb62fb0SOlivier Houchard
4511fb62fb0SOlivier Houchard /*
4521fb62fb0SOlivier Houchard * Producer counter must represent state relative to
4531fb62fb0SOlivier Houchard * our latest consumer snapshot.
4541fb62fb0SOlivier Houchard */
4551fb62fb0SOlivier Houchard ck_pr_fence_load();
4561fb62fb0SOlivier Houchard producer = ck_pr_load_uint(&ring->p_tail);
4571fb62fb0SOlivier Houchard
4581fb62fb0SOlivier Houchard if (CK_CC_UNLIKELY(consumer == producer))
4591fb62fb0SOlivier Houchard return false;
4601fb62fb0SOlivier Houchard
4611fb62fb0SOlivier Houchard ck_pr_fence_load();
4621fb62fb0SOlivier Houchard
4631fb62fb0SOlivier Houchard target = (const char *)buffer + ts * (consumer & mask);
4641fb62fb0SOlivier Houchard memcpy(data, target, ts);
4651fb62fb0SOlivier Houchard
4661fb62fb0SOlivier Houchard /* Serialize load with respect to head update. */
4671fb62fb0SOlivier Houchard ck_pr_fence_store_atomic();
4681fb62fb0SOlivier Houchard } while (ck_pr_cas_uint_value(&ring->c_head,
4691fb62fb0SOlivier Houchard consumer,
4701fb62fb0SOlivier Houchard consumer + 1,
4711fb62fb0SOlivier Houchard &consumer) == false);
4721fb62fb0SOlivier Houchard
4731fb62fb0SOlivier Houchard return true;
4741fb62fb0SOlivier Houchard }
4751fb62fb0SOlivier Houchard
4761fb62fb0SOlivier Houchard /*
4771fb62fb0SOlivier Houchard * The ck_ring_*_spsc namespace is the public interface for interacting with a
4781fb62fb0SOlivier Houchard * ring buffer containing pointers. Correctness is only provided if there is up
4791fb62fb0SOlivier Houchard * to one concurrent consumer and up to one concurrent producer.
4801fb62fb0SOlivier Houchard */
4811fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_spsc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry,unsigned int * size)4821fb62fb0SOlivier Houchard ck_ring_enqueue_spsc_size(struct ck_ring *ring,
4831fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
4841fb62fb0SOlivier Houchard const void *entry,
4851fb62fb0SOlivier Houchard unsigned int *size)
4861fb62fb0SOlivier Houchard {
4871fb62fb0SOlivier Houchard
4881fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp_size(ring, buffer, &entry,
4891fb62fb0SOlivier Houchard sizeof(entry), size);
4901fb62fb0SOlivier Houchard }
4911fb62fb0SOlivier Houchard
4921fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_spsc(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry)4931fb62fb0SOlivier Houchard ck_ring_enqueue_spsc(struct ck_ring *ring,
4941fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
4951fb62fb0SOlivier Houchard const void *entry)
4961fb62fb0SOlivier Houchard {
4971fb62fb0SOlivier Houchard
4981fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp(ring, buffer,
4991fb62fb0SOlivier Houchard &entry, sizeof(entry), NULL);
5001fb62fb0SOlivier Houchard }
5011fb62fb0SOlivier Houchard
502*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_spsc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,unsigned int * size)503*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spsc_size(struct ck_ring *ring,
504*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer,
505*74e9b5f2SOlivier Houchard unsigned int *size)
506*74e9b5f2SOlivier Houchard {
507*74e9b5f2SOlivier Houchard
508*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(ring, buffer, sizeof(void *),
509*74e9b5f2SOlivier Houchard size);
510*74e9b5f2SOlivier Houchard }
511*74e9b5f2SOlivier Houchard
512*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_spsc(struct ck_ring * ring,struct ck_ring_buffer * buffer)513*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spsc(struct ck_ring *ring,
514*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer)
515*74e9b5f2SOlivier Houchard {
516*74e9b5f2SOlivier Houchard
517*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(ring, buffer, sizeof(void *),
518*74e9b5f2SOlivier Houchard NULL);
519*74e9b5f2SOlivier Houchard }
520*74e9b5f2SOlivier Houchard
521*74e9b5f2SOlivier Houchard CK_CC_INLINE static void
ck_ring_enqueue_commit_spsc(struct ck_ring * ring)522*74e9b5f2SOlivier Houchard ck_ring_enqueue_commit_spsc(struct ck_ring *ring)
523*74e9b5f2SOlivier Houchard {
524*74e9b5f2SOlivier Houchard
525*74e9b5f2SOlivier Houchard _ck_ring_enqueue_commit_sp(ring);
526*74e9b5f2SOlivier Houchard return;
527*74e9b5f2SOlivier Houchard }
528*74e9b5f2SOlivier Houchard
5291fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_dequeue_spsc(struct ck_ring * ring,const struct ck_ring_buffer * buffer,void * data)5301fb62fb0SOlivier Houchard ck_ring_dequeue_spsc(struct ck_ring *ring,
5311fb62fb0SOlivier Houchard const struct ck_ring_buffer *buffer,
5321fb62fb0SOlivier Houchard void *data)
5331fb62fb0SOlivier Houchard {
5341fb62fb0SOlivier Houchard
5351fb62fb0SOlivier Houchard return _ck_ring_dequeue_sc(ring, buffer,
5361fb62fb0SOlivier Houchard (void **)data, sizeof(void *));
5371fb62fb0SOlivier Houchard }
5381fb62fb0SOlivier Houchard
5391fb62fb0SOlivier Houchard /*
5401fb62fb0SOlivier Houchard * The ck_ring_*_mpmc namespace is the public interface for interacting with a
5411fb62fb0SOlivier Houchard * ring buffer containing pointers. Correctness is provided for any number of
5421fb62fb0SOlivier Houchard * producers and consumers.
5431fb62fb0SOlivier Houchard */
5441fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_mpmc(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry)5451fb62fb0SOlivier Houchard ck_ring_enqueue_mpmc(struct ck_ring *ring,
5461fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
5471fb62fb0SOlivier Houchard const void *entry)
5481fb62fb0SOlivier Houchard {
5491fb62fb0SOlivier Houchard
550*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_mp(ring, buffer, &entry, sizeof(entry), NULL);
5511fb62fb0SOlivier Houchard }
5521fb62fb0SOlivier Houchard
5531fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_mpmc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry,unsigned int * size)5541fb62fb0SOlivier Houchard ck_ring_enqueue_mpmc_size(struct ck_ring *ring,
5551fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
5561fb62fb0SOlivier Houchard const void *entry,
5571fb62fb0SOlivier Houchard unsigned int *size)
5581fb62fb0SOlivier Houchard {
5591fb62fb0SOlivier Houchard
560*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_mp_size(ring, buffer, &entry, sizeof(entry),
561*74e9b5f2SOlivier Houchard size);
562*74e9b5f2SOlivier Houchard }
563*74e9b5f2SOlivier Houchard
564*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_mpmc(struct ck_ring * ring,struct ck_ring_buffer * buffer,unsigned int * ticket)565*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpmc(struct ck_ring *ring,
566*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer,
567*74e9b5f2SOlivier Houchard unsigned int *ticket)
568*74e9b5f2SOlivier Houchard {
569*74e9b5f2SOlivier Houchard
570*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(ring, buffer, sizeof(void *),
571*74e9b5f2SOlivier Houchard ticket, NULL);
572*74e9b5f2SOlivier Houchard }
573*74e9b5f2SOlivier Houchard
574*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_mpmc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,unsigned int * ticket,unsigned int * size)575*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpmc_size(struct ck_ring *ring,
576*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer,
577*74e9b5f2SOlivier Houchard unsigned int *ticket,
578*74e9b5f2SOlivier Houchard unsigned int *size)
579*74e9b5f2SOlivier Houchard {
580*74e9b5f2SOlivier Houchard
581*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(ring, buffer, sizeof(void *),
582*74e9b5f2SOlivier Houchard ticket, size);
583*74e9b5f2SOlivier Houchard }
584*74e9b5f2SOlivier Houchard
585*74e9b5f2SOlivier Houchard CK_CC_INLINE static void
ck_ring_enqueue_commit_mpmc(struct ck_ring * ring,unsigned int ticket)586*74e9b5f2SOlivier Houchard ck_ring_enqueue_commit_mpmc(struct ck_ring *ring, unsigned int ticket)
587*74e9b5f2SOlivier Houchard {
588*74e9b5f2SOlivier Houchard
589*74e9b5f2SOlivier Houchard _ck_ring_enqueue_commit_mp(ring, ticket);
590*74e9b5f2SOlivier Houchard return;
5911fb62fb0SOlivier Houchard }
5921fb62fb0SOlivier Houchard
5931fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_trydequeue_mpmc(struct ck_ring * ring,const struct ck_ring_buffer * buffer,void * data)5941fb62fb0SOlivier Houchard ck_ring_trydequeue_mpmc(struct ck_ring *ring,
5951fb62fb0SOlivier Houchard const struct ck_ring_buffer *buffer,
5961fb62fb0SOlivier Houchard void *data)
5971fb62fb0SOlivier Houchard {
5981fb62fb0SOlivier Houchard
5991fb62fb0SOlivier Houchard return _ck_ring_trydequeue_mc(ring,
6001fb62fb0SOlivier Houchard buffer, (void **)data, sizeof(void *));
6011fb62fb0SOlivier Houchard }
6021fb62fb0SOlivier Houchard
6031fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_dequeue_mpmc(struct ck_ring * ring,const struct ck_ring_buffer * buffer,void * data)6041fb62fb0SOlivier Houchard ck_ring_dequeue_mpmc(struct ck_ring *ring,
6051fb62fb0SOlivier Houchard const struct ck_ring_buffer *buffer,
6061fb62fb0SOlivier Houchard void *data)
6071fb62fb0SOlivier Houchard {
6081fb62fb0SOlivier Houchard
6091fb62fb0SOlivier Houchard return _ck_ring_dequeue_mc(ring, buffer, (void **)data,
6101fb62fb0SOlivier Houchard sizeof(void *));
6111fb62fb0SOlivier Houchard }
6121fb62fb0SOlivier Houchard
6131fb62fb0SOlivier Houchard /*
6141fb62fb0SOlivier Houchard * The ck_ring_*_spmc namespace is the public interface for interacting with a
6151fb62fb0SOlivier Houchard * ring buffer containing pointers. Correctness is provided for any number of
6161fb62fb0SOlivier Houchard * consumers with up to one concurrent producer.
6171fb62fb0SOlivier Houchard */
618*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_spmc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,unsigned int * size)619*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spmc_size(struct ck_ring *ring,
620*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer,
621*74e9b5f2SOlivier Houchard unsigned int *size)
622*74e9b5f2SOlivier Houchard {
623*74e9b5f2SOlivier Houchard
624*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(ring, buffer, sizeof(void *), size);
625*74e9b5f2SOlivier Houchard }
626*74e9b5f2SOlivier Houchard
627*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_spmc(struct ck_ring * ring,struct ck_ring_buffer * buffer)628*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spmc(struct ck_ring *ring,
629*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer)
630*74e9b5f2SOlivier Houchard {
631*74e9b5f2SOlivier Houchard
632*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(ring, buffer, sizeof(void *), NULL);
633*74e9b5f2SOlivier Houchard }
634*74e9b5f2SOlivier Houchard
635*74e9b5f2SOlivier Houchard CK_CC_INLINE static void
ck_ring_enqueue_commit_spmc(struct ck_ring * ring)636*74e9b5f2SOlivier Houchard ck_ring_enqueue_commit_spmc(struct ck_ring *ring)
637*74e9b5f2SOlivier Houchard {
638*74e9b5f2SOlivier Houchard
639*74e9b5f2SOlivier Houchard _ck_ring_enqueue_commit_sp(ring);
640*74e9b5f2SOlivier Houchard return;
641*74e9b5f2SOlivier Houchard }
642*74e9b5f2SOlivier Houchard
6431fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_spmc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry,unsigned int * size)6441fb62fb0SOlivier Houchard ck_ring_enqueue_spmc_size(struct ck_ring *ring,
6451fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
6461fb62fb0SOlivier Houchard const void *entry,
6471fb62fb0SOlivier Houchard unsigned int *size)
6481fb62fb0SOlivier Houchard {
6491fb62fb0SOlivier Houchard
6501fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp_size(ring, buffer, &entry,
6511fb62fb0SOlivier Houchard sizeof(entry), size);
6521fb62fb0SOlivier Houchard }
6531fb62fb0SOlivier Houchard
6541fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_spmc(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry)6551fb62fb0SOlivier Houchard ck_ring_enqueue_spmc(struct ck_ring *ring,
6561fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
6571fb62fb0SOlivier Houchard const void *entry)
6581fb62fb0SOlivier Houchard {
6591fb62fb0SOlivier Houchard
6601fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp(ring, buffer, &entry,
6611fb62fb0SOlivier Houchard sizeof(entry), NULL);
6621fb62fb0SOlivier Houchard }
6631fb62fb0SOlivier Houchard
6641fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_trydequeue_spmc(struct ck_ring * ring,const struct ck_ring_buffer * buffer,void * data)6651fb62fb0SOlivier Houchard ck_ring_trydequeue_spmc(struct ck_ring *ring,
6661fb62fb0SOlivier Houchard const struct ck_ring_buffer *buffer,
6671fb62fb0SOlivier Houchard void *data)
6681fb62fb0SOlivier Houchard {
6691fb62fb0SOlivier Houchard
6701fb62fb0SOlivier Houchard return _ck_ring_trydequeue_mc(ring, buffer, (void **)data, sizeof(void *));
6711fb62fb0SOlivier Houchard }
6721fb62fb0SOlivier Houchard
6731fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_dequeue_spmc(struct ck_ring * ring,const struct ck_ring_buffer * buffer,void * data)6741fb62fb0SOlivier Houchard ck_ring_dequeue_spmc(struct ck_ring *ring,
6751fb62fb0SOlivier Houchard const struct ck_ring_buffer *buffer,
6761fb62fb0SOlivier Houchard void *data)
6771fb62fb0SOlivier Houchard {
6781fb62fb0SOlivier Houchard
6791fb62fb0SOlivier Houchard return _ck_ring_dequeue_mc(ring, buffer, (void **)data, sizeof(void *));
6801fb62fb0SOlivier Houchard }
6811fb62fb0SOlivier Houchard
6821fb62fb0SOlivier Houchard /*
6831fb62fb0SOlivier Houchard * The ck_ring_*_mpsc namespace is the public interface for interacting with a
6841fb62fb0SOlivier Houchard * ring buffer containing pointers. Correctness is provided for any number of
6851fb62fb0SOlivier Houchard * producers with up to one concurrent consumers.
6861fb62fb0SOlivier Houchard */
687*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_mpsc(struct ck_ring * ring,struct ck_ring_buffer * buffer,unsigned int * ticket)688*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpsc(struct ck_ring *ring,
689*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer,
690*74e9b5f2SOlivier Houchard unsigned int *ticket)
691*74e9b5f2SOlivier Houchard {
692*74e9b5f2SOlivier Houchard
693*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(ring, buffer, sizeof(void *),
694*74e9b5f2SOlivier Houchard ticket, NULL);
695*74e9b5f2SOlivier Houchard }
696*74e9b5f2SOlivier Houchard
697*74e9b5f2SOlivier Houchard CK_CC_INLINE static void *
ck_ring_enqueue_reserve_mpsc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,unsigned int * ticket,unsigned int * size)698*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpsc_size(struct ck_ring *ring,
699*74e9b5f2SOlivier Houchard struct ck_ring_buffer *buffer,
700*74e9b5f2SOlivier Houchard unsigned int *ticket,
701*74e9b5f2SOlivier Houchard unsigned int *size)
702*74e9b5f2SOlivier Houchard {
703*74e9b5f2SOlivier Houchard
704*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(ring, buffer, sizeof(void *),
705*74e9b5f2SOlivier Houchard ticket, size);
706*74e9b5f2SOlivier Houchard }
707*74e9b5f2SOlivier Houchard
708*74e9b5f2SOlivier Houchard CK_CC_INLINE static void
ck_ring_enqueue_commit_mpsc(struct ck_ring * ring,unsigned int ticket)709*74e9b5f2SOlivier Houchard ck_ring_enqueue_commit_mpsc(struct ck_ring *ring, unsigned int ticket)
710*74e9b5f2SOlivier Houchard {
711*74e9b5f2SOlivier Houchard
712*74e9b5f2SOlivier Houchard _ck_ring_enqueue_commit_mp(ring, ticket);
713*74e9b5f2SOlivier Houchard return;
714*74e9b5f2SOlivier Houchard }
715*74e9b5f2SOlivier Houchard
7161fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_mpsc(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry)7171fb62fb0SOlivier Houchard ck_ring_enqueue_mpsc(struct ck_ring *ring,
7181fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
7191fb62fb0SOlivier Houchard const void *entry)
7201fb62fb0SOlivier Houchard {
7211fb62fb0SOlivier Houchard
7221fb62fb0SOlivier Houchard return _ck_ring_enqueue_mp(ring, buffer, &entry,
7231fb62fb0SOlivier Houchard sizeof(entry), NULL);
7241fb62fb0SOlivier Houchard }
7251fb62fb0SOlivier Houchard
7261fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_enqueue_mpsc_size(struct ck_ring * ring,struct ck_ring_buffer * buffer,const void * entry,unsigned int * size)7271fb62fb0SOlivier Houchard ck_ring_enqueue_mpsc_size(struct ck_ring *ring,
7281fb62fb0SOlivier Houchard struct ck_ring_buffer *buffer,
7291fb62fb0SOlivier Houchard const void *entry,
7301fb62fb0SOlivier Houchard unsigned int *size)
7311fb62fb0SOlivier Houchard {
7321fb62fb0SOlivier Houchard
7331fb62fb0SOlivier Houchard return _ck_ring_enqueue_mp_size(ring, buffer, &entry,
7341fb62fb0SOlivier Houchard sizeof(entry), size);
7351fb62fb0SOlivier Houchard }
7361fb62fb0SOlivier Houchard
7371fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ring_dequeue_mpsc(struct ck_ring * ring,const struct ck_ring_buffer * buffer,void * data)7381fb62fb0SOlivier Houchard ck_ring_dequeue_mpsc(struct ck_ring *ring,
7391fb62fb0SOlivier Houchard const struct ck_ring_buffer *buffer,
7401fb62fb0SOlivier Houchard void *data)
7411fb62fb0SOlivier Houchard {
7421fb62fb0SOlivier Houchard
7431fb62fb0SOlivier Houchard return _ck_ring_dequeue_sc(ring, buffer, (void **)data,
7441fb62fb0SOlivier Houchard sizeof(void *));
7451fb62fb0SOlivier Houchard }
7461fb62fb0SOlivier Houchard
7471fb62fb0SOlivier Houchard /*
7481fb62fb0SOlivier Houchard * CK_RING_PROTOTYPE is used to define a type-safe interface for inlining
7491fb62fb0SOlivier Houchard * values of a particular type in the ring the buffer.
7501fb62fb0SOlivier Houchard */
7511fb62fb0SOlivier Houchard #define CK_RING_PROTOTYPE(name, type) \
752*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
753*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spsc_##name(struct ck_ring *a, \
754*74e9b5f2SOlivier Houchard struct type *b) \
755*74e9b5f2SOlivier Houchard { \
756*74e9b5f2SOlivier Houchard \
757*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(a, b, \
758*74e9b5f2SOlivier Houchard sizeof(struct type), NULL); \
759*74e9b5f2SOlivier Houchard } \
760*74e9b5f2SOlivier Houchard \
761*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
762*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spsc_size_##name(struct ck_ring *a, \
763*74e9b5f2SOlivier Houchard struct type *b, \
764*74e9b5f2SOlivier Houchard unsigned int *c) \
765*74e9b5f2SOlivier Houchard { \
766*74e9b5f2SOlivier Houchard \
767*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(a, b, \
768*74e9b5f2SOlivier Houchard sizeof(struct type), c); \
769*74e9b5f2SOlivier Houchard } \
770*74e9b5f2SOlivier Houchard \
7711fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
7721fb62fb0SOlivier Houchard ck_ring_enqueue_spsc_size_##name(struct ck_ring *a, \
7731fb62fb0SOlivier Houchard struct type *b, \
7741fb62fb0SOlivier Houchard struct type *c, \
7751fb62fb0SOlivier Houchard unsigned int *d) \
7761fb62fb0SOlivier Houchard { \
7771fb62fb0SOlivier Houchard \
7781fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp_size(a, b, c, \
7791fb62fb0SOlivier Houchard sizeof(struct type), d); \
7801fb62fb0SOlivier Houchard } \
7811fb62fb0SOlivier Houchard \
7821fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
7831fb62fb0SOlivier Houchard ck_ring_enqueue_spsc_##name(struct ck_ring *a, \
7841fb62fb0SOlivier Houchard struct type *b, \
7851fb62fb0SOlivier Houchard struct type *c) \
7861fb62fb0SOlivier Houchard { \
7871fb62fb0SOlivier Houchard \
7881fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp(a, b, c, \
7891fb62fb0SOlivier Houchard sizeof(struct type), NULL); \
7901fb62fb0SOlivier Houchard } \
7911fb62fb0SOlivier Houchard \
7921fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
7931fb62fb0SOlivier Houchard ck_ring_dequeue_spsc_##name(struct ck_ring *a, \
7941fb62fb0SOlivier Houchard struct type *b, \
7951fb62fb0SOlivier Houchard struct type *c) \
7961fb62fb0SOlivier Houchard { \
7971fb62fb0SOlivier Houchard \
7981fb62fb0SOlivier Houchard return _ck_ring_dequeue_sc(a, b, c, \
7991fb62fb0SOlivier Houchard sizeof(struct type)); \
8001fb62fb0SOlivier Houchard } \
8011fb62fb0SOlivier Houchard \
802*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
803*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spmc_##name(struct ck_ring *a, \
804*74e9b5f2SOlivier Houchard struct type *b) \
805*74e9b5f2SOlivier Houchard { \
806*74e9b5f2SOlivier Houchard \
807*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(a, b, \
808*74e9b5f2SOlivier Houchard sizeof(struct type), NULL); \
809*74e9b5f2SOlivier Houchard } \
810*74e9b5f2SOlivier Houchard \
811*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
812*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spmc_size_##name(struct ck_ring *a, \
813*74e9b5f2SOlivier Houchard struct type *b, \
814*74e9b5f2SOlivier Houchard unsigned int *c) \
815*74e9b5f2SOlivier Houchard { \
816*74e9b5f2SOlivier Houchard \
817*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_sp(a, b, \
818*74e9b5f2SOlivier Houchard sizeof(struct type), c); \
819*74e9b5f2SOlivier Houchard } \
820*74e9b5f2SOlivier Houchard \
8211fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
8221fb62fb0SOlivier Houchard ck_ring_enqueue_spmc_size_##name(struct ck_ring *a, \
8231fb62fb0SOlivier Houchard struct type *b, \
8241fb62fb0SOlivier Houchard struct type *c, \
8251fb62fb0SOlivier Houchard unsigned int *d) \
8261fb62fb0SOlivier Houchard { \
8271fb62fb0SOlivier Houchard \
8281fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp_size(a, b, c, \
8291fb62fb0SOlivier Houchard sizeof(struct type), d); \
8301fb62fb0SOlivier Houchard } \
8311fb62fb0SOlivier Houchard \
8321fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
8331fb62fb0SOlivier Houchard ck_ring_enqueue_spmc_##name(struct ck_ring *a, \
8341fb62fb0SOlivier Houchard struct type *b, \
8351fb62fb0SOlivier Houchard struct type *c) \
8361fb62fb0SOlivier Houchard { \
8371fb62fb0SOlivier Houchard \
8381fb62fb0SOlivier Houchard return _ck_ring_enqueue_sp(a, b, c, \
8391fb62fb0SOlivier Houchard sizeof(struct type), NULL); \
8401fb62fb0SOlivier Houchard } \
8411fb62fb0SOlivier Houchard \
8421fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
8431fb62fb0SOlivier Houchard ck_ring_trydequeue_spmc_##name(struct ck_ring *a, \
8441fb62fb0SOlivier Houchard struct type *b, \
8451fb62fb0SOlivier Houchard struct type *c) \
8461fb62fb0SOlivier Houchard { \
8471fb62fb0SOlivier Houchard \
8481fb62fb0SOlivier Houchard return _ck_ring_trydequeue_mc(a, \
8491fb62fb0SOlivier Houchard b, c, sizeof(struct type)); \
8501fb62fb0SOlivier Houchard } \
8511fb62fb0SOlivier Houchard \
8521fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
8531fb62fb0SOlivier Houchard ck_ring_dequeue_spmc_##name(struct ck_ring *a, \
8541fb62fb0SOlivier Houchard struct type *b, \
8551fb62fb0SOlivier Houchard struct type *c) \
8561fb62fb0SOlivier Houchard { \
8571fb62fb0SOlivier Houchard \
8581fb62fb0SOlivier Houchard return _ck_ring_dequeue_mc(a, b, c, \
8591fb62fb0SOlivier Houchard sizeof(struct type)); \
8601fb62fb0SOlivier Houchard } \
8611fb62fb0SOlivier Houchard \
862*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
863*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpsc_##name(struct ck_ring *a, \
864*74e9b5f2SOlivier Houchard struct type *b, \
865*74e9b5f2SOlivier Houchard unsigned int *c) \
866*74e9b5f2SOlivier Houchard { \
867*74e9b5f2SOlivier Houchard \
868*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(a, b, \
869*74e9b5f2SOlivier Houchard sizeof(struct type), c, NULL); \
870*74e9b5f2SOlivier Houchard } \
871*74e9b5f2SOlivier Houchard \
872*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
873*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpsc_size_##name(struct ck_ring *a, \
874*74e9b5f2SOlivier Houchard struct type *b, \
875*74e9b5f2SOlivier Houchard unsigned int *c, \
876*74e9b5f2SOlivier Houchard unsigned int *d) \
877*74e9b5f2SOlivier Houchard { \
878*74e9b5f2SOlivier Houchard \
879*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(a, b, \
880*74e9b5f2SOlivier Houchard sizeof(struct type), c, d); \
881*74e9b5f2SOlivier Houchard } \
882*74e9b5f2SOlivier Houchard \
8831fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
8841fb62fb0SOlivier Houchard ck_ring_enqueue_mpsc_##name(struct ck_ring *a, \
8851fb62fb0SOlivier Houchard struct type *b, \
8861fb62fb0SOlivier Houchard struct type *c) \
8871fb62fb0SOlivier Houchard { \
8881fb62fb0SOlivier Houchard \
8891fb62fb0SOlivier Houchard return _ck_ring_enqueue_mp(a, b, c, \
8901fb62fb0SOlivier Houchard sizeof(struct type), NULL); \
8911fb62fb0SOlivier Houchard } \
8921fb62fb0SOlivier Houchard \
8931fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
8941fb62fb0SOlivier Houchard ck_ring_enqueue_mpsc_size_##name(struct ck_ring *a, \
8951fb62fb0SOlivier Houchard struct type *b, \
8961fb62fb0SOlivier Houchard struct type *c, \
8971fb62fb0SOlivier Houchard unsigned int *d) \
8981fb62fb0SOlivier Houchard { \
8991fb62fb0SOlivier Houchard \
9001fb62fb0SOlivier Houchard return _ck_ring_enqueue_mp_size(a, b, c, \
9011fb62fb0SOlivier Houchard sizeof(struct type), d); \
9021fb62fb0SOlivier Houchard } \
9031fb62fb0SOlivier Houchard \
9041fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
9051fb62fb0SOlivier Houchard ck_ring_dequeue_mpsc_##name(struct ck_ring *a, \
9061fb62fb0SOlivier Houchard struct type *b, \
9071fb62fb0SOlivier Houchard struct type *c) \
9081fb62fb0SOlivier Houchard { \
9091fb62fb0SOlivier Houchard \
9101fb62fb0SOlivier Houchard return _ck_ring_dequeue_sc(a, b, c, \
9111fb62fb0SOlivier Houchard sizeof(struct type)); \
9121fb62fb0SOlivier Houchard } \
9131fb62fb0SOlivier Houchard \
914*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
915*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpmc_##name(struct ck_ring *a, \
916*74e9b5f2SOlivier Houchard struct type *b, \
917*74e9b5f2SOlivier Houchard unsigned int *c) \
918*74e9b5f2SOlivier Houchard { \
919*74e9b5f2SOlivier Houchard \
920*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(a, b, \
921*74e9b5f2SOlivier Houchard sizeof(struct type), c, NULL); \
922*74e9b5f2SOlivier Houchard } \
923*74e9b5f2SOlivier Houchard \
924*74e9b5f2SOlivier Houchard CK_CC_INLINE static struct type * \
925*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpmc_size_##name(struct ck_ring *a, \
926*74e9b5f2SOlivier Houchard struct type *b, \
927*74e9b5f2SOlivier Houchard unsigned int *c, \
928*74e9b5f2SOlivier Houchard unsigned int *d) \
929*74e9b5f2SOlivier Houchard { \
930*74e9b5f2SOlivier Houchard \
931*74e9b5f2SOlivier Houchard return _ck_ring_enqueue_reserve_mp(a, b, \
932*74e9b5f2SOlivier Houchard sizeof(struct type), c, d); \
933*74e9b5f2SOlivier Houchard } \
934*74e9b5f2SOlivier Houchard \
9351fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
9361fb62fb0SOlivier Houchard ck_ring_enqueue_mpmc_size_##name(struct ck_ring *a, \
9371fb62fb0SOlivier Houchard struct type *b, \
9381fb62fb0SOlivier Houchard struct type *c, \
9391fb62fb0SOlivier Houchard unsigned int *d) \
9401fb62fb0SOlivier Houchard { \
9411fb62fb0SOlivier Houchard \
9421fb62fb0SOlivier Houchard return _ck_ring_enqueue_mp_size(a, b, c, \
9431fb62fb0SOlivier Houchard sizeof(struct type), d); \
9441fb62fb0SOlivier Houchard } \
9451fb62fb0SOlivier Houchard \
9461fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
9471fb62fb0SOlivier Houchard ck_ring_enqueue_mpmc_##name(struct ck_ring *a, \
9481fb62fb0SOlivier Houchard struct type *b, \
9491fb62fb0SOlivier Houchard struct type *c) \
9501fb62fb0SOlivier Houchard { \
9511fb62fb0SOlivier Houchard \
9521fb62fb0SOlivier Houchard return _ck_ring_enqueue_mp(a, b, c, \
9531fb62fb0SOlivier Houchard sizeof(struct type), NULL); \
9541fb62fb0SOlivier Houchard } \
9551fb62fb0SOlivier Houchard \
9561fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
9571fb62fb0SOlivier Houchard ck_ring_trydequeue_mpmc_##name(struct ck_ring *a, \
9581fb62fb0SOlivier Houchard struct type *b, \
9591fb62fb0SOlivier Houchard struct type *c) \
9601fb62fb0SOlivier Houchard { \
9611fb62fb0SOlivier Houchard \
9621fb62fb0SOlivier Houchard return _ck_ring_trydequeue_mc(a, \
9631fb62fb0SOlivier Houchard b, c, sizeof(struct type)); \
9641fb62fb0SOlivier Houchard } \
9651fb62fb0SOlivier Houchard \
9661fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
9671fb62fb0SOlivier Houchard ck_ring_dequeue_mpmc_##name(struct ck_ring *a, \
9681fb62fb0SOlivier Houchard struct type *b, \
9691fb62fb0SOlivier Houchard struct type *c) \
9701fb62fb0SOlivier Houchard { \
9711fb62fb0SOlivier Houchard \
9721fb62fb0SOlivier Houchard return _ck_ring_dequeue_mc(a, b, c, \
9731fb62fb0SOlivier Houchard sizeof(struct type)); \
9741fb62fb0SOlivier Houchard }
9751fb62fb0SOlivier Houchard
9761fb62fb0SOlivier Houchard /*
9771fb62fb0SOlivier Houchard * A single producer with one concurrent consumer.
9781fb62fb0SOlivier Houchard */
9791fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_SPSC(name, a, b, c) \
9801fb62fb0SOlivier Houchard ck_ring_enqueue_spsc_##name(a, b, c)
9811fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_SPSC_SIZE(name, a, b, c, d) \
9821fb62fb0SOlivier Houchard ck_ring_enqueue_spsc_size_##name(a, b, c, d)
983*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_SPSC(name, a, b, c) \
984*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spsc_##name(a, b, c)
985*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_SPSC_SIZE(name, a, b, c, d) \
986*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spsc_size_##name(a, b, c, d)
9871fb62fb0SOlivier Houchard #define CK_RING_DEQUEUE_SPSC(name, a, b, c) \
9881fb62fb0SOlivier Houchard ck_ring_dequeue_spsc_##name(a, b, c)
9891fb62fb0SOlivier Houchard
9901fb62fb0SOlivier Houchard /*
9911fb62fb0SOlivier Houchard * A single producer with any number of concurrent consumers.
9921fb62fb0SOlivier Houchard */
9931fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_SPMC(name, a, b, c) \
9941fb62fb0SOlivier Houchard ck_ring_enqueue_spmc_##name(a, b, c)
9951fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_SPMC_SIZE(name, a, b, c, d) \
9961fb62fb0SOlivier Houchard ck_ring_enqueue_spmc_size_##name(a, b, c, d)
997*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_SPMC(name, a, b, c) \
998*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spmc_##name(a, b, c)
999*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_SPMC_SIZE(name, a, b, c, d) \
1000*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_spmc_size_##name(a, b, c, d)
10011fb62fb0SOlivier Houchard #define CK_RING_TRYDEQUEUE_SPMC(name, a, b, c) \
10021fb62fb0SOlivier Houchard ck_ring_trydequeue_spmc_##name(a, b, c)
10031fb62fb0SOlivier Houchard #define CK_RING_DEQUEUE_SPMC(name, a, b, c) \
10041fb62fb0SOlivier Houchard ck_ring_dequeue_spmc_##name(a, b, c)
10051fb62fb0SOlivier Houchard
10061fb62fb0SOlivier Houchard /*
10071fb62fb0SOlivier Houchard * Any number of concurrent producers with up to one
10081fb62fb0SOlivier Houchard * concurrent consumer.
10091fb62fb0SOlivier Houchard */
10101fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_MPSC(name, a, b, c) \
10111fb62fb0SOlivier Houchard ck_ring_enqueue_mpsc_##name(a, b, c)
10121fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_MPSC_SIZE(name, a, b, c, d) \
10131fb62fb0SOlivier Houchard ck_ring_enqueue_mpsc_size_##name(a, b, c, d)
1014*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_MPSC(name, a, b, c) \
1015*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpsc_##name(a, b, c)
1016*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_MPSC_SIZE(name, a, b, c, d) \
1017*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpsc_size_##name(a, b, c, d)
10181fb62fb0SOlivier Houchard #define CK_RING_DEQUEUE_MPSC(name, a, b, c) \
10191fb62fb0SOlivier Houchard ck_ring_dequeue_mpsc_##name(a, b, c)
10201fb62fb0SOlivier Houchard
10211fb62fb0SOlivier Houchard /*
10221fb62fb0SOlivier Houchard * Any number of concurrent producers and consumers.
10231fb62fb0SOlivier Houchard */
10241fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_MPMC(name, a, b, c) \
10251fb62fb0SOlivier Houchard ck_ring_enqueue_mpmc_##name(a, b, c)
10261fb62fb0SOlivier Houchard #define CK_RING_ENQUEUE_MPMC_SIZE(name, a, b, c, d) \
10271fb62fb0SOlivier Houchard ck_ring_enqueue_mpmc_size_##name(a, b, c, d)
1028*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_MPMC(name, a, b, c) \
1029*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpmc_##name(a, b, c)
1030*74e9b5f2SOlivier Houchard #define CK_RING_ENQUEUE_RESERVE_MPMC_SIZE(name, a, b, c, d) \
1031*74e9b5f2SOlivier Houchard ck_ring_enqueue_reserve_mpmc_size_##name(a, b, c, d)
10321fb62fb0SOlivier Houchard #define CK_RING_TRYDEQUEUE_MPMC(name, a, b, c) \
10331fb62fb0SOlivier Houchard ck_ring_trydequeue_mpmc_##name(a, b, c)
10341fb62fb0SOlivier Houchard #define CK_RING_DEQUEUE_MPMC(name, a, b, c) \
10351fb62fb0SOlivier Houchard ck_ring_dequeue_mpmc_##name(a, b, c)
10361fb62fb0SOlivier Houchard
10371fb62fb0SOlivier Houchard #endif /* CK_RING_H */
1038