xref: /freebsd/sys/contrib/ck/include/ck_stack.h (revision 1fb62fb0)
1*1fb62fb0SOlivier Houchard /*
2*1fb62fb0SOlivier Houchard  * Copyright 2009-2015 Samy Al Bahra.
3*1fb62fb0SOlivier Houchard  * All rights reserved.
4*1fb62fb0SOlivier Houchard  *
5*1fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
6*1fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
7*1fb62fb0SOlivier Houchard  * are met:
8*1fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
9*1fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
10*1fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
11*1fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
12*1fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
13*1fb62fb0SOlivier Houchard  *
14*1fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*1fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*1fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*1fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*1fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*1fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*1fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*1fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*1fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*1fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*1fb62fb0SOlivier Houchard  * SUCH DAMAGE.
25*1fb62fb0SOlivier Houchard  */
26*1fb62fb0SOlivier Houchard 
27*1fb62fb0SOlivier Houchard #ifndef CK_STACK_H
28*1fb62fb0SOlivier Houchard #define CK_STACK_H
29*1fb62fb0SOlivier Houchard 
30*1fb62fb0SOlivier Houchard #include <ck_cc.h>
31*1fb62fb0SOlivier Houchard #include <ck_pr.h>
32*1fb62fb0SOlivier Houchard #include <ck_stdbool.h>
33*1fb62fb0SOlivier Houchard #include <ck_stddef.h>
34*1fb62fb0SOlivier Houchard 
35*1fb62fb0SOlivier Houchard struct ck_stack_entry {
36*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *next;
37*1fb62fb0SOlivier Houchard };
38*1fb62fb0SOlivier Houchard typedef struct ck_stack_entry ck_stack_entry_t;
39*1fb62fb0SOlivier Houchard 
40*1fb62fb0SOlivier Houchard struct ck_stack {
41*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *head;
42*1fb62fb0SOlivier Houchard 	char *generation CK_CC_PACKED;
43*1fb62fb0SOlivier Houchard } CK_CC_ALIASED;
44*1fb62fb0SOlivier Houchard typedef struct ck_stack ck_stack_t;
45*1fb62fb0SOlivier Houchard 
46*1fb62fb0SOlivier Houchard #define CK_STACK_INITIALIZER { NULL, NULL }
47*1fb62fb0SOlivier Houchard 
48*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_PUSH_UPMC
49*1fb62fb0SOlivier Houchard #define CK_F_STACK_PUSH_UPMC
50*1fb62fb0SOlivier Houchard /*
51*1fb62fb0SOlivier Houchard  * Stack producer operation safe for multiple unique producers and multiple consumers.
52*1fb62fb0SOlivier Houchard  */
53*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_stack_push_upmc(struct ck_stack * target,struct ck_stack_entry * entry)54*1fb62fb0SOlivier Houchard ck_stack_push_upmc(struct ck_stack *target, struct ck_stack_entry *entry)
55*1fb62fb0SOlivier Houchard {
56*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *stack;
57*1fb62fb0SOlivier Houchard 
58*1fb62fb0SOlivier Houchard 	stack = ck_pr_load_ptr(&target->head);
59*1fb62fb0SOlivier Houchard 	entry->next = stack;
60*1fb62fb0SOlivier Houchard 	ck_pr_fence_store();
61*1fb62fb0SOlivier Houchard 
62*1fb62fb0SOlivier Houchard 	while (ck_pr_cas_ptr_value(&target->head, stack, entry, &stack) == false) {
63*1fb62fb0SOlivier Houchard 		entry->next = stack;
64*1fb62fb0SOlivier Houchard 		ck_pr_fence_store();
65*1fb62fb0SOlivier Houchard 	}
66*1fb62fb0SOlivier Houchard 
67*1fb62fb0SOlivier Houchard 	return;
68*1fb62fb0SOlivier Houchard }
69*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_PUSH_UPMC */
70*1fb62fb0SOlivier Houchard 
71*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_TRYPUSH_UPMC
72*1fb62fb0SOlivier Houchard #define CK_F_STACK_TRYPUSH_UPMC
73*1fb62fb0SOlivier Houchard /*
74*1fb62fb0SOlivier Houchard  * Stack producer operation for multiple unique producers and multiple consumers.
75*1fb62fb0SOlivier Houchard  * Returns true on success and false on failure.
76*1fb62fb0SOlivier Houchard  */
77*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_stack_trypush_upmc(struct ck_stack * target,struct ck_stack_entry * entry)78*1fb62fb0SOlivier Houchard ck_stack_trypush_upmc(struct ck_stack *target, struct ck_stack_entry *entry)
79*1fb62fb0SOlivier Houchard {
80*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *stack;
81*1fb62fb0SOlivier Houchard 
82*1fb62fb0SOlivier Houchard 	stack = ck_pr_load_ptr(&target->head);
83*1fb62fb0SOlivier Houchard 	entry->next = stack;
84*1fb62fb0SOlivier Houchard 	ck_pr_fence_store();
85*1fb62fb0SOlivier Houchard 
86*1fb62fb0SOlivier Houchard 	return ck_pr_cas_ptr(&target->head, stack, entry);
87*1fb62fb0SOlivier Houchard }
88*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_TRYPUSH_UPMC */
89*1fb62fb0SOlivier Houchard 
90*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_POP_UPMC
91*1fb62fb0SOlivier Houchard #define CK_F_STACK_POP_UPMC
92*1fb62fb0SOlivier Houchard /*
93*1fb62fb0SOlivier Houchard  * Stack consumer operation safe for multiple unique producers and multiple consumers.
94*1fb62fb0SOlivier Houchard  */
95*1fb62fb0SOlivier Houchard CK_CC_INLINE static struct ck_stack_entry *
ck_stack_pop_upmc(struct ck_stack * target)96*1fb62fb0SOlivier Houchard ck_stack_pop_upmc(struct ck_stack *target)
97*1fb62fb0SOlivier Houchard {
98*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *entry, *next;
99*1fb62fb0SOlivier Houchard 
100*1fb62fb0SOlivier Houchard 	entry = ck_pr_load_ptr(&target->head);
101*1fb62fb0SOlivier Houchard 	if (entry == NULL)
102*1fb62fb0SOlivier Houchard 		return NULL;
103*1fb62fb0SOlivier Houchard 
104*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
105*1fb62fb0SOlivier Houchard 	next = entry->next;
106*1fb62fb0SOlivier Houchard 	while (ck_pr_cas_ptr_value(&target->head, entry, next, &entry) == false) {
107*1fb62fb0SOlivier Houchard 		if (entry == NULL)
108*1fb62fb0SOlivier Houchard 			break;
109*1fb62fb0SOlivier Houchard 
110*1fb62fb0SOlivier Houchard 		ck_pr_fence_load();
111*1fb62fb0SOlivier Houchard 		next = entry->next;
112*1fb62fb0SOlivier Houchard 	}
113*1fb62fb0SOlivier Houchard 
114*1fb62fb0SOlivier Houchard 	return entry;
115*1fb62fb0SOlivier Houchard }
116*1fb62fb0SOlivier Houchard #endif
117*1fb62fb0SOlivier Houchard 
118*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_TRYPOP_UPMC
119*1fb62fb0SOlivier Houchard #define CK_F_STACK_TRYPOP_UPMC
120*1fb62fb0SOlivier Houchard /*
121*1fb62fb0SOlivier Houchard  * Stack production operation for multiple unique producers and multiple consumers.
122*1fb62fb0SOlivier Houchard  * Returns true on success and false on failure. The value pointed to by the second
123*1fb62fb0SOlivier Houchard  * argument is set to a valid ck_stack_entry_t reference if true is returned. If
124*1fb62fb0SOlivier Houchard  * false is returned, then the value pointed to by the second argument is undefined.
125*1fb62fb0SOlivier Houchard  */
126*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_stack_trypop_upmc(struct ck_stack * target,struct ck_stack_entry ** r)127*1fb62fb0SOlivier Houchard ck_stack_trypop_upmc(struct ck_stack *target, struct ck_stack_entry **r)
128*1fb62fb0SOlivier Houchard {
129*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *entry;
130*1fb62fb0SOlivier Houchard 
131*1fb62fb0SOlivier Houchard 	entry = ck_pr_load_ptr(&target->head);
132*1fb62fb0SOlivier Houchard 	if (entry == NULL)
133*1fb62fb0SOlivier Houchard 		return false;
134*1fb62fb0SOlivier Houchard 
135*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
136*1fb62fb0SOlivier Houchard 	if (ck_pr_cas_ptr(&target->head, entry, entry->next) == true) {
137*1fb62fb0SOlivier Houchard 		*r = entry;
138*1fb62fb0SOlivier Houchard 		return true;
139*1fb62fb0SOlivier Houchard 	}
140*1fb62fb0SOlivier Houchard 
141*1fb62fb0SOlivier Houchard 	return false;
142*1fb62fb0SOlivier Houchard }
143*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_TRYPOP_UPMC */
144*1fb62fb0SOlivier Houchard 
145*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_BATCH_POP_UPMC
146*1fb62fb0SOlivier Houchard #define CK_F_STACK_BATCH_POP_UPMC
147*1fb62fb0SOlivier Houchard /*
148*1fb62fb0SOlivier Houchard  * Pop all items off the stack.
149*1fb62fb0SOlivier Houchard  */
150*1fb62fb0SOlivier Houchard CK_CC_INLINE static struct ck_stack_entry *
ck_stack_batch_pop_upmc(struct ck_stack * target)151*1fb62fb0SOlivier Houchard ck_stack_batch_pop_upmc(struct ck_stack *target)
152*1fb62fb0SOlivier Houchard {
153*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *entry;
154*1fb62fb0SOlivier Houchard 
155*1fb62fb0SOlivier Houchard 	entry = ck_pr_fas_ptr(&target->head, NULL);
156*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
157*1fb62fb0SOlivier Houchard 	return entry;
158*1fb62fb0SOlivier Houchard }
159*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_BATCH_POP_UPMC */
160*1fb62fb0SOlivier Houchard 
161*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_PUSH_MPMC
162*1fb62fb0SOlivier Houchard #define CK_F_STACK_PUSH_MPMC
163*1fb62fb0SOlivier Houchard /*
164*1fb62fb0SOlivier Houchard  * Stack producer operation safe for multiple producers and multiple consumers.
165*1fb62fb0SOlivier Houchard  */
166*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_stack_push_mpmc(struct ck_stack * target,struct ck_stack_entry * entry)167*1fb62fb0SOlivier Houchard ck_stack_push_mpmc(struct ck_stack *target, struct ck_stack_entry *entry)
168*1fb62fb0SOlivier Houchard {
169*1fb62fb0SOlivier Houchard 
170*1fb62fb0SOlivier Houchard 	ck_stack_push_upmc(target, entry);
171*1fb62fb0SOlivier Houchard 	return;
172*1fb62fb0SOlivier Houchard }
173*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_PUSH_MPMC */
174*1fb62fb0SOlivier Houchard 
175*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_TRYPUSH_MPMC
176*1fb62fb0SOlivier Houchard #define CK_F_STACK_TRYPUSH_MPMC
177*1fb62fb0SOlivier Houchard /*
178*1fb62fb0SOlivier Houchard  * Stack producer operation safe for multiple producers and multiple consumers.
179*1fb62fb0SOlivier Houchard  */
180*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_stack_trypush_mpmc(struct ck_stack * target,struct ck_stack_entry * entry)181*1fb62fb0SOlivier Houchard ck_stack_trypush_mpmc(struct ck_stack *target, struct ck_stack_entry *entry)
182*1fb62fb0SOlivier Houchard {
183*1fb62fb0SOlivier Houchard 
184*1fb62fb0SOlivier Houchard 	return ck_stack_trypush_upmc(target, entry);
185*1fb62fb0SOlivier Houchard }
186*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_TRYPUSH_MPMC */
187*1fb62fb0SOlivier Houchard 
188*1fb62fb0SOlivier Houchard #ifdef CK_F_PR_CAS_PTR_2_VALUE
189*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_POP_MPMC
190*1fb62fb0SOlivier Houchard #define CK_F_STACK_POP_MPMC
191*1fb62fb0SOlivier Houchard /*
192*1fb62fb0SOlivier Houchard  * Stack consumer operation safe for multiple producers and multiple consumers.
193*1fb62fb0SOlivier Houchard  */
194*1fb62fb0SOlivier Houchard CK_CC_INLINE static struct ck_stack_entry *
ck_stack_pop_mpmc(struct ck_stack * target)195*1fb62fb0SOlivier Houchard ck_stack_pop_mpmc(struct ck_stack *target)
196*1fb62fb0SOlivier Houchard {
197*1fb62fb0SOlivier Houchard 	struct ck_stack original, update;
198*1fb62fb0SOlivier Houchard 
199*1fb62fb0SOlivier Houchard 	original.generation = ck_pr_load_ptr(&target->generation);
200*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
201*1fb62fb0SOlivier Houchard 	original.head = ck_pr_load_ptr(&target->head);
202*1fb62fb0SOlivier Houchard 	if (original.head == NULL)
203*1fb62fb0SOlivier Houchard 		return NULL;
204*1fb62fb0SOlivier Houchard 
205*1fb62fb0SOlivier Houchard 	/* Order with respect to next pointer. */
206*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
207*1fb62fb0SOlivier Houchard 
208*1fb62fb0SOlivier Houchard 	update.generation = original.generation + 1;
209*1fb62fb0SOlivier Houchard 	update.head = original.head->next;
210*1fb62fb0SOlivier Houchard 
211*1fb62fb0SOlivier Houchard 	while (ck_pr_cas_ptr_2_value(target, &original, &update, &original) == false) {
212*1fb62fb0SOlivier Houchard 		if (original.head == NULL)
213*1fb62fb0SOlivier Houchard 			return NULL;
214*1fb62fb0SOlivier Houchard 
215*1fb62fb0SOlivier Houchard 		update.generation = original.generation + 1;
216*1fb62fb0SOlivier Houchard 
217*1fb62fb0SOlivier Houchard 		/* Order with respect to next pointer. */
218*1fb62fb0SOlivier Houchard 		ck_pr_fence_load();
219*1fb62fb0SOlivier Houchard 		update.head = original.head->next;
220*1fb62fb0SOlivier Houchard 	}
221*1fb62fb0SOlivier Houchard 
222*1fb62fb0SOlivier Houchard 	return original.head;
223*1fb62fb0SOlivier Houchard }
224*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_POP_MPMC */
225*1fb62fb0SOlivier Houchard 
226*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_TRYPOP_MPMC
227*1fb62fb0SOlivier Houchard #define CK_F_STACK_TRYPOP_MPMC
228*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_stack_trypop_mpmc(struct ck_stack * target,struct ck_stack_entry ** r)229*1fb62fb0SOlivier Houchard ck_stack_trypop_mpmc(struct ck_stack *target, struct ck_stack_entry **r)
230*1fb62fb0SOlivier Houchard {
231*1fb62fb0SOlivier Houchard 	struct ck_stack original, update;
232*1fb62fb0SOlivier Houchard 
233*1fb62fb0SOlivier Houchard 	original.generation = ck_pr_load_ptr(&target->generation);
234*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
235*1fb62fb0SOlivier Houchard 	original.head = ck_pr_load_ptr(&target->head);
236*1fb62fb0SOlivier Houchard 	if (original.head == NULL)
237*1fb62fb0SOlivier Houchard 		return false;
238*1fb62fb0SOlivier Houchard 
239*1fb62fb0SOlivier Houchard 	update.generation = original.generation + 1;
240*1fb62fb0SOlivier Houchard 	ck_pr_fence_load();
241*1fb62fb0SOlivier Houchard 	update.head = original.head->next;
242*1fb62fb0SOlivier Houchard 
243*1fb62fb0SOlivier Houchard 	if (ck_pr_cas_ptr_2_value(target, &original, &update, &original) == true) {
244*1fb62fb0SOlivier Houchard 		*r = original.head;
245*1fb62fb0SOlivier Houchard 		return true;
246*1fb62fb0SOlivier Houchard 	}
247*1fb62fb0SOlivier Houchard 
248*1fb62fb0SOlivier Houchard 	return false;
249*1fb62fb0SOlivier Houchard }
250*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_TRYPOP_MPMC */
251*1fb62fb0SOlivier Houchard #endif /* CK_F_PR_CAS_PTR_2_VALUE */
252*1fb62fb0SOlivier Houchard 
253*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_BATCH_POP_MPMC
254*1fb62fb0SOlivier Houchard #define CK_F_STACK_BATCH_POP_MPMC
255*1fb62fb0SOlivier Houchard /*
256*1fb62fb0SOlivier Houchard  * This is equivalent to the UP/MC version as NULL does not need a
257*1fb62fb0SOlivier Houchard  * a generation count.
258*1fb62fb0SOlivier Houchard  */
259*1fb62fb0SOlivier Houchard CK_CC_INLINE static struct ck_stack_entry *
ck_stack_batch_pop_mpmc(struct ck_stack * target)260*1fb62fb0SOlivier Houchard ck_stack_batch_pop_mpmc(struct ck_stack *target)
261*1fb62fb0SOlivier Houchard {
262*1fb62fb0SOlivier Houchard 
263*1fb62fb0SOlivier Houchard 	return ck_stack_batch_pop_upmc(target);
264*1fb62fb0SOlivier Houchard }
265*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_BATCH_POP_MPMC */
266*1fb62fb0SOlivier Houchard 
267*1fb62fb0SOlivier Houchard #ifndef CK_F_STACK_PUSH_MPNC
268*1fb62fb0SOlivier Houchard #define CK_F_STACK_PUSH_MPNC
269*1fb62fb0SOlivier Houchard /*
270*1fb62fb0SOlivier Houchard  * Stack producer operation safe with no concurrent consumers.
271*1fb62fb0SOlivier Houchard  */
272*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_stack_push_mpnc(struct ck_stack * target,struct ck_stack_entry * entry)273*1fb62fb0SOlivier Houchard ck_stack_push_mpnc(struct ck_stack *target, struct ck_stack_entry *entry)
274*1fb62fb0SOlivier Houchard {
275*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *stack;
276*1fb62fb0SOlivier Houchard 
277*1fb62fb0SOlivier Houchard 	entry->next = NULL;
278*1fb62fb0SOlivier Houchard 	ck_pr_fence_store_atomic();
279*1fb62fb0SOlivier Houchard 	stack = ck_pr_fas_ptr(&target->head, entry);
280*1fb62fb0SOlivier Houchard 	ck_pr_store_ptr(&entry->next, stack);
281*1fb62fb0SOlivier Houchard 	ck_pr_fence_store();
282*1fb62fb0SOlivier Houchard 
283*1fb62fb0SOlivier Houchard 	return;
284*1fb62fb0SOlivier Houchard }
285*1fb62fb0SOlivier Houchard #endif /* CK_F_STACK_PUSH_MPNC */
286*1fb62fb0SOlivier Houchard 
287*1fb62fb0SOlivier Houchard /*
288*1fb62fb0SOlivier Houchard  * Stack producer operation for single producer and no concurrent consumers.
289*1fb62fb0SOlivier Houchard  */
290*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_stack_push_spnc(struct ck_stack * target,struct ck_stack_entry * entry)291*1fb62fb0SOlivier Houchard ck_stack_push_spnc(struct ck_stack *target, struct ck_stack_entry *entry)
292*1fb62fb0SOlivier Houchard {
293*1fb62fb0SOlivier Houchard 
294*1fb62fb0SOlivier Houchard 	entry->next = target->head;
295*1fb62fb0SOlivier Houchard 	target->head = entry;
296*1fb62fb0SOlivier Houchard 	return;
297*1fb62fb0SOlivier Houchard }
298*1fb62fb0SOlivier Houchard 
299*1fb62fb0SOlivier Houchard /*
300*1fb62fb0SOlivier Houchard  * Stack consumer operation for no concurrent producers and single consumer.
301*1fb62fb0SOlivier Houchard  */
302*1fb62fb0SOlivier Houchard CK_CC_INLINE static struct ck_stack_entry *
ck_stack_pop_npsc(struct ck_stack * target)303*1fb62fb0SOlivier Houchard ck_stack_pop_npsc(struct ck_stack *target)
304*1fb62fb0SOlivier Houchard {
305*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *n;
306*1fb62fb0SOlivier Houchard 
307*1fb62fb0SOlivier Houchard 	if (target->head == NULL)
308*1fb62fb0SOlivier Houchard 		return NULL;
309*1fb62fb0SOlivier Houchard 
310*1fb62fb0SOlivier Houchard 	n = target->head;
311*1fb62fb0SOlivier Houchard 	target->head = n->next;
312*1fb62fb0SOlivier Houchard 
313*1fb62fb0SOlivier Houchard 	return n;
314*1fb62fb0SOlivier Houchard }
315*1fb62fb0SOlivier Houchard 
316*1fb62fb0SOlivier Houchard /*
317*1fb62fb0SOlivier Houchard  * Pop all items off a stack.
318*1fb62fb0SOlivier Houchard  */
319*1fb62fb0SOlivier Houchard CK_CC_INLINE static struct ck_stack_entry *
ck_stack_batch_pop_npsc(struct ck_stack * target)320*1fb62fb0SOlivier Houchard ck_stack_batch_pop_npsc(struct ck_stack *target)
321*1fb62fb0SOlivier Houchard {
322*1fb62fb0SOlivier Houchard 	struct ck_stack_entry *n;
323*1fb62fb0SOlivier Houchard 
324*1fb62fb0SOlivier Houchard 	n = target->head;
325*1fb62fb0SOlivier Houchard 	target->head = NULL;
326*1fb62fb0SOlivier Houchard 
327*1fb62fb0SOlivier Houchard 	return n;
328*1fb62fb0SOlivier Houchard }
329*1fb62fb0SOlivier Houchard 
330*1fb62fb0SOlivier Houchard /*
331*1fb62fb0SOlivier Houchard  * Stack initialization function. Guarantees initialization across processors.
332*1fb62fb0SOlivier Houchard  */
333*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_stack_init(struct ck_stack * stack)334*1fb62fb0SOlivier Houchard ck_stack_init(struct ck_stack *stack)
335*1fb62fb0SOlivier Houchard {
336*1fb62fb0SOlivier Houchard 
337*1fb62fb0SOlivier Houchard 	stack->head = NULL;
338*1fb62fb0SOlivier Houchard 	stack->generation = NULL;
339*1fb62fb0SOlivier Houchard 	return;
340*1fb62fb0SOlivier Houchard }
341*1fb62fb0SOlivier Houchard 
342*1fb62fb0SOlivier Houchard /* Defines a container_of functions for */
343*1fb62fb0SOlivier Houchard #define CK_STACK_CONTAINER(T, M, N) CK_CC_CONTAINER(ck_stack_entry_t, T, M, N)
344*1fb62fb0SOlivier Houchard 
345*1fb62fb0SOlivier Houchard #define CK_STACK_ISEMPTY(m) ((m)->head == NULL)
346*1fb62fb0SOlivier Houchard #define CK_STACK_FIRST(s)   ((s)->head)
347*1fb62fb0SOlivier Houchard #define CK_STACK_NEXT(m)    ((m)->next)
348*1fb62fb0SOlivier Houchard #define CK_STACK_FOREACH(stack, entry)				\
349*1fb62fb0SOlivier Houchard 	for ((entry) = CK_STACK_FIRST(stack);			\
350*1fb62fb0SOlivier Houchard 	     (entry) != NULL;					\
351*1fb62fb0SOlivier Houchard 	     (entry) = CK_STACK_NEXT(entry))
352*1fb62fb0SOlivier Houchard #define CK_STACK_FOREACH_SAFE(stack, entry, T)			\
353*1fb62fb0SOlivier Houchard 	for ((entry) = CK_STACK_FIRST(stack);			\
354*1fb62fb0SOlivier Houchard 	     (entry) != NULL && ((T) = (entry)->next, 1);	\
355*1fb62fb0SOlivier Houchard 	     (entry) = (T))
356*1fb62fb0SOlivier Houchard 
357*1fb62fb0SOlivier Houchard #endif /* CK_STACK_H */
358