xref: /freebsd/sys/contrib/ck/include/ck_ring.h (revision 74e9b5f29ad0056bbe11a30c91dfa0705fa19cd5)
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