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