]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/circle_queue.h
2 * Copyright (c) 2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #ifndef _KERN_CIRCLE_QUEUE_H_
30 #define _KERN_CIRCLE_QUEUE_H_
32 #include <kern/queue.h>
33 #include <kern/assert.h>
38 * Circle Queue Management APIs
40 * These are similar to the queues from queue.h,
41 * but the circle queue head is a single pointer to the first element
45 typedef struct circle_queue_head
{
47 } circle_queue_head_t
, *circle_queue_t
;
50 circle_queue_empty(circle_queue_t cq
)
52 return cq
->head
== NULL
;
55 static inline queue_entry_t
56 circle_queue_first(circle_queue_t cq
)
61 static inline queue_entry_t
62 circle_queue_last(circle_queue_t cq
)
64 queue_entry_t elt
= circle_queue_first(cq
);
66 __builtin_assume(elt
->prev
!= NULL
);
72 static inline queue_entry_t
73 circle_queue_next(circle_queue_t cq
, queue_entry_t elt
)
75 return elt
->next
== cq
->head
? NULL
: elt
->next
;
79 circle_queue_length(circle_queue_t cq
)
81 queue_entry_t elt
= circle_queue_first(cq
);
84 for (; elt
; elt
= circle_queue_next(cq
, elt
)) {
91 circle_enqueue_tail(circle_queue_t cq
, queue_entry_t elt
)
93 queue_entry_t head
= circle_queue_first(cq
);
94 queue_entry_t tail
= circle_queue_last(cq
);
97 cq
->head
= elt
->next
= elt
->prev
= elt
;
107 circle_enqueue_head(circle_queue_t cq
, queue_entry_t elt
)
109 circle_enqueue_tail(cq
, elt
);
114 circle_dequeue(circle_queue_t cq
, queue_entry_t elt
)
116 queue_entry_t elt_prev
= elt
->prev
;
117 queue_entry_t elt_next
= elt
->next
;
119 if (elt
== elt_next
) {
120 assert(cq
->head
== elt
);
123 elt_prev
->next
= elt_next
;
124 elt_next
->prev
= elt_prev
;
125 if (cq
->head
== elt
) {
129 __DEQUEUE_ELT_CLEANUP(elt
);
132 static inline queue_entry_t
133 circle_dequeue_head(circle_queue_t cq
)
135 queue_entry_t elt
= circle_queue_first(cq
);
137 circle_dequeue(cq
, elt
);
142 static inline queue_entry_t
143 circle_dequeue_tail(circle_queue_t cq
)
145 queue_entry_t elt
= circle_queue_last(cq
);
147 circle_dequeue(cq
, elt
);
155 * Convert a cirle_queue_entry_t pointer to a queue element pointer.
156 * Get a pointer to the user-defined element containing
157 * a given cirle_queue_entry_t
159 * <type> * cqe_element(cirle_queue_entry_t qe, <type>, field)
160 * qe - queue entry to convert
161 * <type> - what's in the queue (e.g., struct some_data)
162 * <field> - is the chain field in <type>
164 * Do not use pointer types for <type>
166 #define cqe_element(qe, type, field) __container_of(qe, type, field)
171 * Iterate over each queue_entry_t structure.
172 * Generates a 'for' loop, setting 'qe' to
173 * each queue_entry_t in the queue.
175 * cqe_foreach(queue_entry_t qe, queue_t head)
176 * qe - iteration variable
177 * head - pointer to queue_head_t (head of queue)
179 * This should only be used with Method 1 queue iteration (linkage chains)
181 #define cqe_foreach(qe, head) \
182 for (qe = circle_queue_first(head); qe; qe = circle_queue_next(head, qe))
185 * Macro: cqe_foreach_safe
187 * Safely iterate over each queue_entry_t structure.
189 * Use this iterator macro if you plan to remove the
190 * queue_entry_t, qe, from the queue during the
193 * cqe_foreach_safe(queue_entry_t qe, queue_t head)
194 * qe - iteration variable
195 * head - pointer to queue_head_t (head of queue)
197 * This should only be used with Method 1 queue iteration (linkage chains)
199 #define cqe_foreach_safe(qe, head) \
200 for (queue_entry_t _ne, _qe = circle_queue_first(head); \
201 (qe = _qe) && (_ne = circle_queue_next(head, _qe), 1); \
205 * Macro: cqe_foreach_element
207 * Iterate over each _element_ in a queue
208 * where each queue_entry_t points to another
209 * queue_entry_t, i.e., managed by the [de|en]queue_head/
210 * [de|en]queue_tail / remqueue / etc. function.
212 * cqe_foreach_element(<type> *elt, queue_t head, <field>)
213 * elt - iteration variable
214 * <type> - what's in the queue (e.g., struct some_data)
215 * <field> - is the chain field in <type>
217 * This should only be used with Method 1 queue iteration (linkage chains)
219 #define cqe_foreach_element(elt, head, field) \
220 for (queue_entry_t _qe = circle_queue_first(head); \
221 _qe && (elt = cqe_element(_qe, typeof(*(elt)), field), 1); \
222 _qe = circle_queue_next(head, _qe))
225 * Macro: cqe_foreach_element_safe
227 * Safely iterate over each _element_ in a queue
228 * where each queue_entry_t points to another
229 * queue_entry_t, i.e., managed by the [de|en]queue_head/
230 * [de|en]queue_tail / remqueue / etc. function.
232 * Use this iterator macro if you plan to remove the
233 * element, elt, from the queue during the iteration.
235 * cqe_foreach_element_safe(<type> *elt, queue_t head, <field>)
236 * elt - iteration variable
237 * <type> - what's in the queue (e.g., struct some_data)
238 * <field> - is the chain field in <type>
240 * This should only be used with Method 1 queue iteration (linkage chains)
242 #define cqe_foreach_element_safe(elt, head, field) \
243 for (queue_entry_t _ne, _qe = circle_queue_first(head); \
244 _qe && (elt = cqe_element(_qe, typeof(*(elt)), field), \
245 _ne = circle_queue_next(head, _qe), 1); \
248 /* Dequeue an element from head, or return NULL if the queue is empty */
249 #define cqe_dequeue_head(head, type, field) ({ \
250 queue_entry_t _tmp_entry = circle_dequeue_head((head)); \
251 type *_tmp_element = (type*) NULL; \
252 if (_tmp_entry != (queue_entry_t) NULL) \
253 _tmp_element = cqe_element(_tmp_entry, type, field); \
257 /* Dequeue an element from tail, or return NULL if the queue is empty */
258 #define cqe_dequeue_tail(head, type, field) ({ \
259 queue_entry_t _tmp_entry = circle_dequeue_tail((head)); \
260 type *_tmp_element = (type*) NULL; \
261 if (_tmp_entry != (queue_entry_t) NULL) \
262 _tmp_element = cqe_element(_tmp_entry, type, field); \
266 /* Peek at the first element, or return NULL if the queue is empty */
267 #define cqe_queue_first(head, type, field) ({ \
268 queue_entry_t _tmp_entry = circle_queue_first((head)); \
269 type *_tmp_element = (type*) NULL; \
270 if (_tmp_entry != (queue_entry_t) NULL) \
271 _tmp_element = cqe_element(_tmp_entry, type, field); \
275 /* Peek at the next element, or return NULL if it is last */
276 #define cqe_queue_next(elt, head, type, field) ({ \
277 queue_entry_t _tmp_entry = circle_queue_next((head), (elt)); \
278 type *_tmp_element = (type*) NULL; \
279 if (_tmp_entry != (queue_entry_t) NULL) \
280 _tmp_element = cqe_element(_tmp_entry, type, field); \
284 /* Peek at the tail element, or return NULL if the queue is empty */
285 #define cqe_queue_last(head, type, field) ({ \
286 queue_entry_t _tmp_entry = circle_queue_last((head)); \
287 type *_tmp_element = (type*) NULL; \
288 if (_tmp_entry != (queue_entry_t) NULL) \
289 _tmp_element = cqe_element(_tmp_entry, type, field); \
294 * Macro: circle_queue_init
296 * Initialize the given circle queue.
298 * void circle_queue_init(q)
299 * circle_queue_t q; \* MODIFIED *\
301 #define circle_queue_init(q) \
308 #endif /* _KERN_QUEUE_H_ */