21 #ifndef _XENO_NUCLEUS_QUEUE_H
22 #define _XENO_NUCLEUS_QUEUE_H
24 #include <nucleus/types.h>
25 #include <nucleus/assert.h>
29 typedef struct xnholder {
31 struct xnholder *next;
32 struct xnholder *last;
36 static inline void inith(xnholder_t *holder)
39 holder->last = holder;
40 holder->next = holder;
43 static inline void ath(xnholder_t *head, xnholder_t *holder)
47 holder->next = head->next;
48 holder->next->last = holder;
52 static inline void dth(xnholder_t *holder)
54 holder->last->next = holder->next;
55 holder->next->last = holder->last;
60 typedef struct xnqueue {
64 #if defined(__KERNEL__) && XENO_DEBUG(QUEUES)
70 #if XENO_DEBUG(QUEUES) && (defined(CONFIG_SMP) || XENO_DEBUG(XNLOCK))
71 #define XNQUEUE_INITIALIZER(q) { { &(q).head, &(q).head }, 0, XNARCH_LOCK_UNLOCKED }
73 #define XNQUEUE_INITIALIZER(q) { { &(q).head, &(q).head }, 0 }
76 #define DEFINE_XNQUEUE(q) xnqueue_t q = XNQUEUE_INITIALIZER(q)
78 static inline void initq(xnqueue_t *qslot)
82 #if defined(__KERNEL__) && XENO_DEBUG(QUEUES)
83 xnlock_init(&qslot->lock);
87 #if XENO_DEBUG(QUEUES)
89 #if defined(__KERNEL__) || defined(__XENO_SIM__)
91 #define XENO_DEBUG_CHECK_QUEUE(__qslot) \
96 xnlock_get_irqsave(&(__qslot)->lock,s); \
97 curr = (__qslot)->head.last; \
98 while (curr != &(__qslot)->head && nelems < (__qslot)->elems) \
99 curr = curr->last, nelems++; \
100 if (curr != &(__qslot)->head || nelems != (__qslot)->elems) \
101 xnpod_fatal("corrupted queue, qslot->elems=%d/%d, qslot=%p at %s:%d", \
105 __FILE__,__LINE__); \
106 xnlock_put_irqrestore(&(__qslot)->lock,s); \
109 #define XENO_DEBUG_INSERT_QUEUE(__qslot,__holder) \
113 xnlock_get_irqsave(&(__qslot)->lock,s); \
114 curr = (__qslot)->head.last; \
115 while (curr != &(__qslot)->head && (__holder) != curr) \
117 if (curr == (__holder)) \
118 xnpod_fatal("inserting element twice, holder=%p, qslot=%p at %s:%d", \
121 __FILE__,__LINE__); \
122 if ((__holder)->last == NULL) \
123 xnpod_fatal("holder=%p not initialized, qslot=%p", \
126 xnlock_put_irqrestore(&(__qslot)->lock,s); \
129 #define XENO_DEBUG_REMOVE_QUEUE(__qslot,__holder) \
133 xnlock_get_irqsave(&(__qslot)->lock,s); \
134 curr = (__qslot)->head.last; \
135 while (curr != &(__qslot)->head && (__holder) != curr) \
137 if (curr == &(__qslot)->head) \
138 xnpod_fatal("removing non-linked element, holder=%p, qslot=%p at %s:%d", \
141 __FILE__,__LINE__); \
142 xnlock_put_irqrestore(&(__qslot)->lock,s); \
150 #define XENO_DEBUG_CHECK_QUEUE(__qslot)
151 #define XENO_DEBUG_INSERT_QUEUE(__qslot,__holder)
152 #define XENO_DEBUG_REMOVE_QUEUE(__qslot,__holder)
159 #define insertq(__qslot,__head,__holder) \
160 ({ XENO_DEBUG_CHECK_QUEUE(__qslot); \
161 XENO_DEBUG_INSERT_QUEUE(__qslot,__holder); \
162 ath((__head)->last,__holder); \
163 ++(__qslot)->elems; })
165 #define prependq(__qslot,__holder) \
166 ({ XENO_DEBUG_CHECK_QUEUE(__qslot); \
167 XENO_DEBUG_INSERT_QUEUE(__qslot,__holder); \
168 ath(&(__qslot)->head,__holder); \
169 ++(__qslot)->elems; })
171 #define appendq(__qslot,__holder) \
172 ({ XENO_DEBUG_CHECK_QUEUE(__qslot); \
173 XENO_DEBUG_INSERT_QUEUE(__qslot,__holder); \
174 ath((__qslot)->head.last,__holder); \
175 ++(__qslot)->elems; })
177 #define removeq(__qslot,__holder) \
178 ({ XENO_DEBUG_CHECK_QUEUE(__qslot); \
179 XENO_DEBUG_REMOVE_QUEUE(__qslot,__holder); \
181 --(__qslot)->elems; })
185 static inline void insertq(xnqueue_t *qslot,
186 xnholder_t *head, xnholder_t *holder)
189 ath(head->last, holder);
193 static inline void prependq(xnqueue_t *qslot, xnholder_t *holder)
196 ath(&qslot->head, holder);
200 static inline void appendq(xnqueue_t *qslot, xnholder_t *holder)
203 ath(qslot->head.last, holder);
207 static inline void removeq(xnqueue_t *qslot, xnholder_t *holder)
215 static inline xnholder_t *getheadq(xnqueue_t *qslot)
217 xnholder_t *holder = qslot->head.next;
218 return holder == &qslot->head ? NULL : holder;
221 static inline xnholder_t *getq(xnqueue_t *qslot)
223 xnholder_t *holder = getheadq(qslot);
225 removeq(qslot, holder);
229 static inline xnholder_t *nextq(xnqueue_t *qslot, xnholder_t *holder)
231 xnholder_t *nextholder = holder->next;
232 return nextholder == &qslot->head ? NULL : nextholder;
235 static inline xnholder_t *popq(xnqueue_t *qslot, xnholder_t *holder)
237 xnholder_t *nextholder = nextq(qslot, holder);
238 removeq(qslot, holder);
242 static inline int countq(xnqueue_t *qslot)
247 static inline int emptyq_p(xnqueue_t *qslot)
249 return qslot->head.next == &qslot->head;
252 static inline void moveq(xnqueue_t *dstq, xnqueue_t *srcq)
254 xnholder_t *headsrc = srcq->head.next;
255 xnholder_t *tailsrc = srcq->head.last;
256 xnholder_t *headdst = &dstq->head;
262 headsrc->last->next = tailsrc->next;
263 tailsrc->next->last = headsrc->last;
264 headsrc->last = headdst;
265 tailsrc->next = headdst->next;
266 headdst->next->last = tailsrc;
267 headdst->next = headsrc;
268 dstq->elems += srcq->elems;
274 typedef struct xnpholder {
281 static inline void initph(xnpholder_t *holder)
283 inith(&holder->plink);
290 typedef struct xnpqueue { xnqueue_t pqueue; } xnpqueue_t;
292 static inline void initpq(xnpqueue_t *pqslot)
294 initq(&pqslot->pqueue);
297 static inline void insertpq(xnpqueue_t *pqslot,
298 xnpholder_t *head, xnpholder_t *holder)
301 insertq(&pqslot->pqueue, &head->plink, &holder->plink);
304 static inline void insertpqf(xnpqueue_t *pqslot, xnpholder_t *holder,
int prio)
310 for (curr = pqslot->pqueue.head.last;
311 curr != &pqslot->pqueue.head; curr = curr->last) {
312 if (prio <= ((xnpholder_t *)curr)->prio)
318 insertq(&pqslot->pqueue, curr->next, &holder->plink);
321 static inline void insertpql(xnpqueue_t *pqslot, xnpholder_t *holder,
int prio)
327 for (curr = pqslot->pqueue.head.next;
328 curr != &pqslot->pqueue.head; curr = curr->next) {
329 if (prio >= ((xnpholder_t *)curr)->prio)
335 insertq(&pqslot->pqueue, curr, &holder->plink);
338 static inline xnpholder_t *findpqh(xnpqueue_t *pqslot,
int prio)
344 for (curr = pqslot->pqueue.head.next;
345 curr != &pqslot->pqueue.head; curr = curr->next) {
346 if (prio >= ((xnpholder_t *)curr)->prio)
350 if (curr && ((xnpholder_t *)curr)->prio == prio)
351 return (xnpholder_t *)curr;
356 static inline void insertpqfr(xnpqueue_t *pqslot, xnpholder_t *holder,
int prio)
365 for (curr = pqslot->pqueue.head.last;
366 curr != &pqslot->pqueue.head; curr = curr->last) {
367 if (prio >= ((xnpholder_t *)curr)->prio)
373 insertq(&pqslot->pqueue, curr->next, &holder->plink);
376 static inline void insertpqlr(xnpqueue_t *pqslot, xnpholder_t *holder,
int prio)
385 for (curr = pqslot->pqueue.head.next;
386 curr != &pqslot->pqueue.head; curr = curr->next) {
387 if (prio <= ((xnpholder_t *)curr)->prio)
393 insertq(&pqslot->pqueue, curr, &holder->plink);
396 static inline xnpholder_t *findpqhr(xnpqueue_t *pqslot,
int prio)
405 for (curr = pqslot->pqueue.head.next;
406 curr != &pqslot->pqueue.head; curr = curr->next) {
407 if (prio <= ((xnpholder_t *)curr)->prio)
411 if (curr && ((xnpholder_t *)curr)->prio == prio)
412 return (xnpholder_t *)curr;
417 static inline void appendpq(xnpqueue_t *pqslot, xnpholder_t *holder)
420 appendq(&pqslot->pqueue, &holder->plink);
423 static inline void prependpq(xnpqueue_t *pqslot, xnpholder_t *holder)
426 prependq(&pqslot->pqueue, &holder->plink);
429 static inline void removepq(xnpqueue_t *pqslot, xnpholder_t *holder)
431 removeq(&pqslot->pqueue, &holder->plink);
434 static inline xnpholder_t *getheadpq(xnpqueue_t *pqslot)
436 return (xnpholder_t *)getheadq(&pqslot->pqueue);
439 static inline xnpholder_t *nextpq(xnpqueue_t *pqslot, xnpholder_t *holder)
441 return (xnpholder_t *)nextq(&pqslot->pqueue, &holder->plink);
444 static inline xnpholder_t *getpq(xnpqueue_t *pqslot)
446 return (xnpholder_t *)getq(&pqslot->pqueue);
449 static inline xnpholder_t *poppq(xnpqueue_t *pqslot, xnpholder_t *holder)
451 return (xnpholder_t *)popq(&pqslot->pqueue, &holder->plink);
454 static inline int countpq(xnpqueue_t *pqslot)
456 return countq(&pqslot->pqueue);
459 static inline int emptypq_p(xnpqueue_t *pqslot)
461 return emptyq_p(&pqslot->pqueue);
466 typedef struct xngholder {
473 static inline void initgh(xngholder_t *holder,
void *data)
475 inith(&holder->glink.plink);
481 typedef struct xngqueue {
485 void (*starvation) (xnqueue_t *);
490 static inline void initgq(xngqueue_t *gqslot,
492 void (*starvation) (xnqueue_t *),
495 initpq(&gqslot->gqueue);
496 gqslot->freehq = freehq;
497 gqslot->starvation = starvation;
498 gqslot->threshold = threshold;
501 static inline xngholder_t *allocgh(xngqueue_t *gqslot)
503 if (countq(gqslot->freehq) < gqslot->threshold)
504 gqslot->starvation(gqslot->freehq);
506 return (xngholder_t *)getq(gqslot->freehq);
509 static inline void *removegh(xngqueue_t *gqslot, xngholder_t *holder)
511 removepq(&gqslot->gqueue, &holder->glink);
512 appendq(gqslot->freehq, &holder->glink.plink);
516 static inline void insertgqf(xngqueue_t *gqslot,
void *data,
int prio)
518 xngholder_t *holder = allocgh(gqslot);
520 insertpqf(&gqslot->gqueue, &holder->glink, prio);
523 static inline void insertgql(xngqueue_t *gqslot,
void *data,
int prio)
525 xngholder_t *holder = allocgh(gqslot);
527 insertpql(&gqslot->gqueue, &holder->glink, prio);
530 static inline void appendgq(xngqueue_t *gqslot,
void *data)
532 xngholder_t *holder = allocgh(gqslot);
534 appendpq(&gqslot->gqueue, &holder->glink);
537 static inline void prependgq(xngqueue_t *gqslot,
void *data)
539 xngholder_t *holder = allocgh(gqslot);
541 prependpq(&gqslot->gqueue, &holder->glink);
544 static inline xngholder_t *getheadgq(xngqueue_t *gqslot)
546 return (xngholder_t *)getheadpq(&gqslot->gqueue);
549 static inline xngholder_t *nextgq(xngqueue_t *gqslot, xngholder_t *holder)
551 return (xngholder_t *)nextpq(&gqslot->gqueue, &holder->glink);
554 static inline void *getgq(xngqueue_t *gqslot)
556 xngholder_t *holder = getheadgq(gqslot);
561 appendq(gqslot->freehq, &getpq(&gqslot->gqueue)->plink);
566 static inline xngholder_t *popgq(xngqueue_t *gqslot, xngholder_t *holder)
568 xngholder_t *nextholder = nextgq(gqslot, holder);
569 removegh(gqslot, holder);
573 static inline xngholder_t *findgq(xngqueue_t *gqslot,
void *data)
577 for (holder = gqslot->gqueue.pqueue.head.next;
578 holder != &gqslot->gqueue.pqueue.head; holder = holder->next) {
579 if (((xngholder_t *)holder)->data == data)
580 return (xngholder_t *)holder;
586 static inline void *removegq(xngqueue_t *gqslot,
void *data)
588 xngholder_t *holder = findgq(gqslot, data);
589 return holder ? removegh(gqslot, holder) : NULL;
592 static inline int countgq(xngqueue_t *gqslot)
594 return countpq(&gqslot->gqueue);
597 static inline int emptygq_p(xngqueue_t *gqslot)
599 return emptypq_p(&gqslot->gqueue);