include/nucleus/queue.h

00001 /*
00002  * Copyright (C) 2001,2002,2003 Philippe Gerum <rpm@xenomai.org>.
00003  * Copyright (C) 2005 Dmitry Adamushko <dmitry.adamushko@gmail.com>
00004  *
00005  * Xenomai is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published
00007  * by the Free Software Foundation; either version 2 of the License,
00008  * or (at your option) any later version.
00009  *
00010  * Xenomai is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with Xenomai; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00018  * 02111-1307, USA.
00019  */
00020 
00021 #ifndef _XENO_NUCLEUS_QUEUE_H
00022 #define _XENO_NUCLEUS_QUEUE_H
00023 
00024 #include <nucleus/types.h>
00025 #include <nucleus/core.h>
00026 
00027 /* debug support */
00028 #include <nucleus/assert.h>
00029 
00030 #ifndef CONFIG_XENO_OPT_DEBUG_QUEUES
00031 #define CONFIG_XENO_OPT_DEBUG_QUEUES 0
00032 #endif
00033 
00034 /* Basic element holder */
00035 
00036 typedef struct xnholder {
00037 
00038     struct xnholder *next;
00039     struct xnholder *last;
00040 
00041 } xnholder_t;
00042 
00043 static inline void inith (xnholder_t *holder)
00044 {
00045     /* Holding queues are doubly-linked and circular */
00046     holder->last = holder;
00047     holder->next = holder;
00048 }
00049 
00050 static inline void ath (xnholder_t *head,
00051                         xnholder_t *holder)
00052 {
00053     /* Inserts the new element right after the heading one  */
00054     holder->last = head;
00055     holder->next = head->next;
00056     holder->next->last = holder;
00057     head->next = holder;
00058 }
00059 
00060 static inline void dth (xnholder_t *holder)
00061 {
00062     holder->last->next = holder->next;
00063     holder->next->last = holder->last;
00064 }
00065 
00066 /* Basic element queue */
00067 
00068 typedef struct xnqueue {
00069 
00070     xnholder_t head;
00071     int elems;
00072 #if defined(__KERNEL__) && XENO_DEBUG(QUEUES) && defined(CONFIG_SMP)
00073     xnlock_t lock;
00074 #endif /* __KERNEL__ && XENO_DEBUG(QUEUES) && CONFIG_SMP */
00075 
00076 } xnqueue_t;
00077 
00078 #if XENO_DEBUG(QUEUES) && defined(CONFIG_SMP)
00079 #define DECLARE_XNQUEUE(q) xnqueue_t q = { { &(q).head, &(q).head }, 0, XNARCH_LOCK_UNLOCKED }
00080 #else /* !(XENO_DEBUG(QUEUES) && CONFIG_SMP) */
00081 #define DECLARE_XNQUEUE(q) xnqueue_t q = { { &(q).head, &(q).head }, 0 }
00082 #endif /* XENO_DEBUG(QUEUES) && CONFIG_SMP */
00083 
00084 static inline void initq (xnqueue_t *qslot)
00085 {
00086     inith(&qslot->head);
00087     qslot->elems = 0;
00088 #if defined(__KERNEL__) && XENO_DEBUG(QUEUES) && defined(CONFIG_SMP)
00089     xnlock_init(&qslot->lock);
00090 #endif /* __KERNEL__ && XENO_DEBUG(QUEUES) && CONFIG_SMP */
00091 }
00092 
00093 #if XENO_DEBUG(QUEUES)
00094 
00095 #if defined(__KERNEL__) || defined(__XENO_SIM__)
00096 
00097 #define XENO_DEBUG_CHECK_QUEUE(__qslot)         \
00098 do { \
00099     xnholder_t *curr; \
00100     spl_t s; \
00101     int nelems = 0; \
00102     xnlock_get_irqsave(&(__qslot)->lock,s);     \
00103     curr = (__qslot)->head.last;                                  \
00104     while (curr != &(__qslot)->head && nelems < (__qslot)->elems)       \
00105         curr = curr->last, nelems++; \
00106     if (curr != &(__qslot)->head || nelems != (__qslot)->elems)   \
00107         xnpod_fatal("corrupted queue, qslot->elems=%d, qslot=%p at %s:%d", \
00108                     (__qslot)->elems,                             \
00109                     __qslot,                                      \
00110                     __FILE__,__LINE__);                           \
00111     xnlock_put_irqrestore(&(__qslot)->lock,s);  \
00112 } while(0)
00113 
00114 #define XENO_DEBUG_INSERT_QUEUE(__qslot,__holder)               \
00115 do { \
00116     xnholder_t *curr; \
00117     spl_t s; \
00118     xnlock_get_irqsave(&(__qslot)->lock,s);     \
00119     curr = (__qslot)->head.last;                           \
00120     while (curr != &(__qslot)->head && (__holder) != curr)      \
00121         curr = curr->last; \
00122     if (curr == (__holder))                                         \
00123         xnpod_fatal("inserting element twice, holder=%p, qslot=%p at %s:%d", \
00124                     __holder, \
00125                     __qslot, \
00126                     __FILE__,__LINE__); \
00127     if ((__holder)->last == NULL)                                  \
00128         xnpod_fatal("holder=%p not initialized, qslot=%p", \
00129                     __holder, \
00130                     __qslot); \
00131     xnlock_put_irqrestore(&(__qslot)->lock,s);  \
00132 } while(0)
00133 
00134 #define XENO_DEBUG_REMOVE_QUEUE(__qslot,__holder)       \
00135 do { \
00136     xnholder_t *curr; \
00137     spl_t s; \
00138     xnlock_get_irqsave(&(__qslot)->lock,s);     \
00139     curr = (__qslot)->head.last;                           \
00140     while (curr != &(__qslot)->head && (__holder) != curr)      \
00141         curr = curr->last; \
00142     if (curr == &(__qslot)->head)                                               \
00143         xnpod_fatal("removing non-linked element, holder=%p, qslot=%p at %s:%d", \
00144                     __holder, \
00145                     __qslot,    \
00146                     __FILE__,__LINE__); \
00147     xnlock_put_irqrestore(&(__qslot)->lock,s);  \
00148 } while(0)
00149 
00150 #else /* !(__KERNEL__ || __XENO_SIM__) */
00151 
00152 /* Disable queue checks in user-space code which does not run as part
00153    of any virtual machine, e.g. skin call interface libs. */
00154 
00155 #define XENO_DEBUG_CHECK_QUEUE(__qslot)
00156 #define XENO_DEBUG_INSERT_QUEUE(__qslot,__holder)
00157 #define XENO_DEBUG_REMOVE_QUEUE(__qslot,__holder)
00158 
00159 #endif /* __KERNEL__ || __XENO_SIM__ */
00160 
00161 /* Write the following as macros so that line numbering information
00162    keeps pointing at the real caller in diagnosis messages. */
00163 
00164 #define insertq(__qslot,__head,__holder)        \
00165 ({ XENO_DEBUG_CHECK_QUEUE(__qslot);             \
00166    XENO_DEBUG_INSERT_QUEUE(__qslot,__holder);   \
00167    ath((__head)->last,__holder);                \
00168    ++(__qslot)->elems; })
00169 
00170 #define prependq(__qslot,__holder)              \
00171 ({ XENO_DEBUG_CHECK_QUEUE(__qslot);             \
00172    XENO_DEBUG_INSERT_QUEUE(__qslot,__holder);   \
00173    ath(&(__qslot)->head,__holder);              \
00174    ++(__qslot)->elems; })
00175 
00176 #define appendq(__qslot,__holder)               \
00177 ({ XENO_DEBUG_CHECK_QUEUE(__qslot);             \
00178    XENO_DEBUG_INSERT_QUEUE(__qslot,__holder);   \
00179    ath((__qslot)->head.last,__holder);          \
00180    ++(__qslot)->elems; })
00181 
00182 #define removeq(__qslot,__holder)               \
00183 ({ XENO_DEBUG_CHECK_QUEUE(__qslot);             \
00184    XENO_DEBUG_REMOVE_QUEUE(__qslot,__holder);   \
00185    dth(__holder);                               \
00186    --(__qslot)->elems; })
00187 
00188 #else /* !XENO_DEBUG(QUEUES) */
00189 
00190 static inline void insertq (xnqueue_t *qslot,
00191                             xnholder_t *head,
00192                             xnholder_t *holder)
00193 {
00194     /* Insert the <holder> element before <head> */
00195     ath(head->last,holder);
00196     ++qslot->elems;
00197 }
00198 
00199 static inline void prependq (xnqueue_t *qslot,
00200                              xnholder_t *holder)
00201 {
00202     /* Prepend the element to the queue */
00203     ath(&qslot->head,holder);
00204     ++qslot->elems;
00205 }
00206 
00207 static inline void appendq (xnqueue_t *qslot,
00208                            xnholder_t *holder)
00209 {
00210     /* Append the element to the queue */
00211     ath(qslot->head.last,holder);
00212     ++qslot->elems;
00213 }
00214 
00215 static inline void removeq (xnqueue_t *qslot,
00216                             xnholder_t *holder)
00217 {
00218     dth(holder);
00219     --qslot->elems;
00220 }
00221 
00222 #endif /* XENO_DEBUG(QUEUES) */
00223 
00224 static inline xnholder_t *getheadq (xnqueue_t *qslot)
00225 {
00226     xnholder_t *holder = qslot->head.next;
00227     return holder == &qslot->head ? NULL : holder;
00228 }
00229 
00230 static inline xnholder_t *getq (xnqueue_t *qslot)
00231 {
00232     xnholder_t *holder = getheadq(qslot);
00233     if (holder) removeq(qslot,holder);
00234     return holder;
00235 }
00236 
00237 static inline xnholder_t *nextq (xnqueue_t *qslot,
00238                                  xnholder_t *holder)
00239 {
00240     xnholder_t *nextholder = holder->next;
00241     return nextholder == &qslot->head ? NULL : nextholder;
00242 }
00243 
00244 static inline xnholder_t *popq (xnqueue_t *qslot,
00245                                 xnholder_t *holder)
00246 {
00247     xnholder_t *nextholder = nextq(qslot,holder);
00248     removeq(qslot,holder);
00249     return nextholder;
00250 }
00251 
00252 static inline int countq (xnqueue_t *qslot)
00253 {
00254     return qslot->elems;
00255 }
00256 
00257 static inline int emptyq_p (xnqueue_t *qslot)
00258 {
00259     return qslot->head.next == &qslot->head;
00260 }
00261 
00262 static inline void moveq (xnqueue_t *dstq, xnqueue_t *srcq)
00263 {
00264     xnholder_t *headsrc = srcq->head.next;
00265     xnholder_t *tailsrc = srcq->head.last->last;
00266     xnholder_t *headdst = &dstq->head;
00267 
00268     headsrc->last->next = tailsrc->next;
00269     tailsrc->next->last = headsrc->last;
00270     headsrc->last = headdst;
00271     tailsrc->next = headdst->next;
00272     headdst->next->last = tailsrc;
00273     headdst->next = headsrc;
00274     dstq->elems += srcq->elems;
00275     srcq->elems = 0;
00276 }
00277 
00278 /* Prioritized element holder */
00279 
00280 typedef struct xnpholder {
00281 
00282     xnholder_t plink;
00283     int prio;
00284 
00285 } xnpholder_t;
00286 
00287 static inline void initph (xnpholder_t *holder)
00288 {
00289     inith(&holder->plink);
00290     /* Priority is set upon queue insertion */
00291 }
00292 
00293 /* Prioritized element queue */
00294 
00295 #define xnqueue_up   (-1)
00296 #define xnqueue_down   1
00297 
00298 typedef struct xnpqueue {
00299 
00300     xnqueue_t pqueue;
00301     int qdir;
00302 
00303 } xnpqueue_t;
00304 
00305 static inline void initpq (xnpqueue_t *pqslot,
00306                            int qdir,
00307                            int maxpri)
00308 {
00309     initq(&pqslot->pqueue);
00310     pqslot->qdir = qdir;
00311 }
00312 
00313 static inline void insertpq (xnpqueue_t *pqslot,
00314                              xnpholder_t *head,
00315                              xnpholder_t *holder)
00316 {
00317     /* Insert the <holder> element before <head> */
00318     insertq(&pqslot->pqueue,&head->plink,&holder->plink);
00319 }
00320 
00321 static inline void insertpqf (xnpqueue_t *pqslot,
00322                               xnpholder_t *holder,
00323                               int prio)
00324 {
00325     /* Insert the element at the end of its priority group (FIFO) */
00326 
00327     xnholder_t *curr;
00328 
00329     if (pqslot->qdir == xnqueue_down) {
00330         for (curr = pqslot->pqueue.head.last;
00331              curr != &pqslot->pqueue.head; curr = curr->last) {
00332                 if (prio <= ((xnpholder_t *)curr)->prio)
00333                     break;
00334         }
00335     }
00336     else {
00337         for (curr = pqslot->pqueue.head.last;
00338              curr != &pqslot->pqueue.head; curr = curr->last) {
00339                 if (prio >= ((xnpholder_t *)curr)->prio)
00340                     break;
00341         }
00342     }
00343 
00344     holder->prio = prio;
00345 
00346     insertq(&pqslot->pqueue,curr->next,&holder->plink);
00347 }
00348 
00349 static inline void insertpql (xnpqueue_t *pqslot,
00350                               xnpholder_t *holder,
00351                               int prio)
00352 {
00353     /* Insert the element at the front of its priority group (LIFO) */
00354 
00355     xnholder_t *curr;
00356 
00357     if (pqslot->qdir == xnqueue_down) {
00358         for (curr = pqslot->pqueue.head.next;
00359              curr != &pqslot->pqueue.head; curr = curr->next) {
00360                 if (prio >= ((xnpholder_t *)curr)->prio)
00361                     break;
00362         }
00363     }
00364     else {
00365         for (curr = pqslot->pqueue.head.next;
00366              curr != &pqslot->pqueue.head; curr = curr->next) {
00367                 if (prio <= ((xnpholder_t *)curr)->prio)
00368                     break;
00369         }
00370     }
00371 
00372     holder->prio = prio;
00373 
00374     insertq(&pqslot->pqueue,curr,&holder->plink);
00375 }
00376 
00377 static inline xnpholder_t *findpqh (xnpqueue_t *pqslot,
00378                                     int prio)
00379 {
00380     /* Find the element heading a given priority group */
00381 
00382     xnholder_t *curr;
00383 
00384     if (pqslot->qdir == xnqueue_down) {
00385         for (curr = pqslot->pqueue.head.next;
00386              curr != &pqslot->pqueue.head; curr = curr->next) {
00387                 if (prio >= ((xnpholder_t *)curr)->prio)
00388                     break;
00389         }
00390     }
00391     else {
00392         for (curr = pqslot->pqueue.head.next;
00393              curr != &pqslot->pqueue.head; curr = curr->next) {
00394                 if (prio <= ((xnpholder_t *)curr)->prio)
00395                     break;
00396         }
00397     }
00398 
00399     if (curr && ((xnpholder_t *)curr)->prio == prio)
00400         return (xnpholder_t *)curr;
00401 
00402     return NULL;
00403 }
00404 
00405 static inline void appendpq (xnpqueue_t *pqslot,
00406                              xnpholder_t *holder)
00407 {
00408     holder->prio = 0;
00409     appendq(&pqslot->pqueue,&holder->plink);
00410 }
00411 
00412 static inline void prependpq (xnpqueue_t *pqslot,
00413                               xnpholder_t *holder)
00414 {
00415     holder->prio = 0;
00416     prependq(&pqslot->pqueue,&holder->plink);
00417 }
00418 
00419 static inline void removepq (xnpqueue_t *pqslot,
00420                              xnpholder_t *holder)
00421 {
00422     removeq(&pqslot->pqueue,&holder->plink);
00423 }
00424 
00425 static inline xnpholder_t *getheadpq (xnpqueue_t *pqslot)
00426 {
00427     return (xnpholder_t *)getheadq(&pqslot->pqueue);
00428 }
00429 
00430 static inline xnpholder_t *nextpq (xnpqueue_t *pqslot,
00431                                    xnpholder_t *holder)
00432 {
00433     return (xnpholder_t *)nextq(&pqslot->pqueue,&holder->plink);
00434 }
00435 
00436 static inline xnpholder_t *getpq (xnpqueue_t *pqslot)
00437 {
00438     return (xnpholder_t *)getq(&pqslot->pqueue);
00439 }
00440 
00441 static inline xnpholder_t *poppq (xnpqueue_t *pqslot,
00442                                   xnpholder_t *holder)
00443 {
00444     return (xnpholder_t *)popq(&pqslot->pqueue,&holder->plink);
00445 }
00446 
00447 static inline int countpq (xnpqueue_t *pqslot)
00448 {
00449     return countq(&pqslot->pqueue);
00450 }
00451 
00452 static inline int emptypq_p (xnpqueue_t *pqslot)
00453 {
00454     return emptyq_p(&pqslot->pqueue);
00455 }
00456 
00457 /* Generic prioritized element holder */
00458 
00459 typedef struct xngholder {
00460 
00461     xnpholder_t glink;
00462     void *data;
00463 
00464 } xngholder_t;
00465 
00466 static inline void initgh (xngholder_t *holder, void *data)
00467 {
00468     inith(&holder->glink.plink);
00469     holder->data = data;
00470 }
00471 
00472 /* Generic element queue */
00473 
00474 typedef struct xngqueue {
00475 
00476     xnpqueue_t gqueue;
00477     xnqueue_t *freehq;
00478     void (*starvation)(xnqueue_t *);
00479     int threshold;
00480 
00481 } xngqueue_t;
00482 
00483 static inline void initgq (xngqueue_t *gqslot,
00484                            xnqueue_t *freehq,
00485                            void (*starvation)(xnqueue_t *),
00486                            int threshold,
00487                            int qdir,
00488                            int maxpri)
00489 {
00490     initpq(&gqslot->gqueue,qdir,maxpri);
00491     gqslot->freehq = freehq;
00492     gqslot->starvation = starvation;
00493     gqslot->threshold = threshold;
00494 }
00495 
00496 static inline xngholder_t *allocgh (xngqueue_t *gqslot)
00497 {
00498     if (countq(gqslot->freehq) < gqslot->threshold)
00499         gqslot->starvation(gqslot->freehq);
00500 
00501     return (xngholder_t *)getq(gqslot->freehq);
00502 }
00503 
00504 static inline void *removegh (xngqueue_t *gqslot,
00505                               xngholder_t *holder)
00506 {
00507     removepq(&gqslot->gqueue,&holder->glink);
00508     appendq(gqslot->freehq,&holder->glink.plink);
00509     return holder->data;
00510 }
00511 
00512 static inline void insertgqf (xngqueue_t *gqslot,
00513                              void *data,
00514                              int prio)
00515 {
00516     xngholder_t *holder = allocgh(gqslot);
00517     holder->data = data;
00518     return insertpqf(&gqslot->gqueue,&holder->glink,prio);
00519 }
00520 
00521 static inline void insertgql (xngqueue_t *gqslot,
00522                               void *data,
00523                               int prio)
00524 {
00525     xngholder_t *holder = allocgh(gqslot);
00526     holder->data = data;
00527     insertpql(&gqslot->gqueue,&holder->glink,prio);
00528 }
00529 
00530 static inline void appendgq (xngqueue_t *gqslot,
00531                              void *data)
00532 {
00533     xngholder_t *holder = allocgh(gqslot);
00534     holder->data = data;
00535     appendpq(&gqslot->gqueue,&holder->glink);
00536 }
00537 
00538 static inline void prependgq (xngqueue_t *gqslot,
00539                               void *data)
00540 {
00541     xngholder_t *holder = allocgh(gqslot);
00542     holder->data = data;
00543     prependpq(&gqslot->gqueue,&holder->glink);
00544 }
00545 
00546 static inline xngholder_t *getheadgq (xngqueue_t *gqslot)
00547 {
00548     return (xngholder_t *)getheadpq(&gqslot->gqueue);
00549 }
00550 
00551 static inline xngholder_t *nextgq (xngqueue_t *gqslot,
00552                                    xngholder_t *holder)
00553 {
00554     return (xngholder_t *)nextpq(&gqslot->gqueue,&holder->glink);
00555 }
00556 
00557 static inline void *getgq (xngqueue_t *gqslot)
00558 {
00559     xngholder_t *holder = getheadgq(gqslot);
00560     if (!holder) return NULL;
00561     appendq(gqslot->freehq,&getpq(&gqslot->gqueue)->plink);
00562     return holder->data;
00563 }
00564 
00565 static inline xngholder_t *popgq (xngqueue_t *gqslot,
00566                                   xngholder_t *holder)
00567 {
00568     xngholder_t *nextholder = nextgq(gqslot,holder);
00569     removegh(gqslot,holder);
00570     return nextholder;
00571 }
00572 
00573 static inline xngholder_t *findgq (xngqueue_t *gqslot,
00574                                    void *data)
00575 {
00576     xnholder_t *holder;
00577 
00578     for (holder = gqslot->gqueue.pqueue.head.next;
00579          holder != &gqslot->gqueue.pqueue.head; holder = holder->next) {
00580          if (((xngholder_t *)holder)->data == data)
00581              return (xngholder_t *)holder;
00582         }
00583 
00584     return NULL;
00585 }
00586 
00587 static inline void *removegq (xngqueue_t *gqslot,
00588                               void *data)
00589 {
00590     xngholder_t *holder = findgq(gqslot,data);
00591     return holder ? removegh(gqslot,holder) : NULL;
00592 }
00593 
00594 static inline int countgq (xngqueue_t *gqslot)
00595 {
00596     return countpq(&gqslot->gqueue);
00597 }
00598 
00599 static inline int emptygq_p (xngqueue_t *gqslot)
00600 {
00601     return emptypq_p(&gqslot->gqueue);
00602 }
00603 
00604 #ifdef CONFIG_XENO_OPT_SCALABLE_SCHED
00605 
00606 /* Multi-level priority queue, suitable for handling the runnable
00607    thread queue. */
00608 
00609 #if BITS_PER_LONG * BITS_PER_LONG < XNCORE_NR_PRIO
00610 #error "Internal bitmap cannot hold so many priority levels"
00611 #endif
00612 
00613 #define __MLQ_LONGS ((XNCORE_NR_PRIO+BITS_PER_LONG-1)/BITS_PER_LONG)
00614 
00615 typedef struct xnmlqueue {
00616 
00617     int qdir, maxpri;
00618 
00619     int elems;
00620 
00621     u_long himap,
00622            lomap[__MLQ_LONGS];
00623 
00624     struct xnqueue queue[XNCORE_NR_PRIO];
00625 
00626 } xnmlqueue_t;
00627 
00628 #undef __MLQ_LONGS
00629 
00630 static inline int countmlq(xnmlqueue_t *mlqslot)
00631 {
00632     return mlqslot->elems;
00633 }
00634 
00635 static inline int emptymlq_p(xnmlqueue_t *mlqslot)
00636 {
00637     return mlqslot->himap == 0;
00638 }
00639 
00640 static inline int indexmlq(xnmlqueue_t *mlqslot, int prio)
00641 {
00642     if (mlqslot->qdir == xnqueue_up) /* minprio > maxprio */
00643         return prio - mlqslot->maxpri;
00644     else
00645         return mlqslot->maxpri - prio;
00646 }
00647 
00648 static inline int ffsmlq(xnmlqueue_t *mlqslot)
00649 {
00650     int hi = ffnz(mlqslot->himap);
00651     int lo = ffnz(mlqslot->lomap[hi]);
00652     return hi * BITS_PER_LONG + lo; /* Result is undefined if none set. */
00653 }
00654 
00655 static inline void initmlq(xnmlqueue_t *mlqslot, int qdir, int maxpri)
00656 {
00657     int prio;
00658 
00659     mlqslot->elems = 0;
00660     mlqslot->qdir  = qdir;
00661     mlqslot->maxpri = maxpri;
00662     mlqslot->himap = 0;
00663     memset(&mlqslot->lomap,0,sizeof(mlqslot->lomap));
00664     
00665     for (prio = 0; prio < XNCORE_NR_PRIO; prio++)
00666         initq(&mlqslot->queue[prio]);
00667 }
00668 
00669 #define XNMLQUEUE_APPEND   0
00670 #define XNMLQUEUE_PREPEND  1
00671 
00672 static inline void addmlq(xnmlqueue_t *mlqslot,
00673                           xnpholder_t  *holder,
00674                           int idx,
00675                           int mode)
00676 {
00677     xnqueue_t *queue = &mlqslot->queue[idx];
00678     int hi = idx / BITS_PER_LONG;
00679     int lo = idx % BITS_PER_LONG;
00680 
00681     if (mode == XNMLQUEUE_PREPEND) /* Hopefully, this should be optimized away. */
00682         prependq(queue, &holder->plink);
00683     else
00684         appendq(queue, &holder->plink);
00685 
00686     mlqslot->elems++;
00687     __setbits(mlqslot->himap,1 << hi);
00688     __setbits(mlqslot->lomap[hi],1 << lo);
00689 }
00690 
00691 static inline void insertmlql(xnmlqueue_t *mlqslot,
00692                               xnpholder_t *holder,
00693                               int prio)
00694 {
00695     addmlq(mlqslot, holder, indexmlq(mlqslot,prio), XNMLQUEUE_PREPEND);
00696     holder->prio = prio;
00697 }
00698 
00699 static inline void insertmlqf(xnmlqueue_t *mlqslot,
00700                               xnpholder_t *holder,
00701                               int prio)
00702 {
00703     addmlq(mlqslot, holder, indexmlq(mlqslot,prio), XNMLQUEUE_APPEND);
00704     holder->prio = prio;
00705 }
00706 
00707 static inline void appendmlq(xnmlqueue_t *mlqslot,
00708                              xnpholder_t *holder)
00709 {
00710     addmlq(mlqslot, holder, mlqslot->maxpri, XNMLQUEUE_APPEND);
00711     holder->prio = mlqslot->maxpri;
00712 }
00713 
00714 static inline void prependmlq(xnmlqueue_t *mlqslot,
00715                               xnpholder_t *holder)
00716 {
00717     addmlq(mlqslot, holder, 0, XNMLQUEUE_PREPEND);
00718     holder->prio = 0;
00719 }
00720 
00721 static inline void removemlq(xnmlqueue_t *mlqslot,
00722                              xnpholder_t *holder)
00723 {
00724     int idx = indexmlq(mlqslot,holder->prio);
00725     xnqueue_t *queue = &mlqslot->queue[idx];
00726 
00727     mlqslot->elems--;
00728     
00729     removeq(queue, &holder->plink);
00730     
00731     if (emptyq_p(queue)) {
00732         int hi = idx / BITS_PER_LONG;
00733         int lo = idx % BITS_PER_LONG;
00734         __clrbits(mlqslot->lomap[hi],1 << lo);
00735         if (mlqslot->lomap[hi] == 0)
00736             __clrbits(mlqslot->himap,1 << hi);
00737     }
00738 }
00739 
00740 static inline xnpholder_t *findmlqh(xnmlqueue_t *mlqslot,
00741                                     int prio)
00742 {
00743     xnqueue_t *queue = &mlqslot->queue[indexmlq(mlqslot,prio)];
00744     return (xnpholder_t *)getheadq(queue);
00745 }
00746 
00747 static inline xnpholder_t *getheadmlq(xnmlqueue_t *mlqslot)
00748 {
00749     xnqueue_t *queue;
00750 
00751     if (emptymlq_p(mlqslot))
00752         return NULL;
00753 
00754     queue = &mlqslot->queue[ffsmlq(mlqslot)];
00755     
00756     return (xnpholder_t *)getheadq(queue);
00757 }
00758 
00759 static inline xnpholder_t *getmlq(xnmlqueue_t *mlqslot)
00760 {
00761     xnholder_t *holder;
00762     xnqueue_t *queue;
00763     int idx, hi, lo;
00764 
00765     if (emptymlq_p(mlqslot))
00766         return NULL;
00767 
00768     idx = ffsmlq(mlqslot);
00769     queue = &mlqslot->queue[idx];
00770     holder = getq(queue);
00771 
00772     XENO_ASSERT(QUEUES, holder,
00773         xnpod_fatal("corrupted multi-level queue, qslot=%p at %s:%d",
00774                     mlqslot,
00775                     __FILE__,__LINE__);
00776         );
00777 
00778     hi = idx / BITS_PER_LONG;
00779     lo = idx % BITS_PER_LONG;
00780 
00781     mlqslot->elems--;    
00782 
00783     if (emptyq_p(queue)) {
00784         __clrbits(mlqslot->lomap[hi],1 << lo);
00785         if (mlqslot->lomap[hi] == 0)
00786             __clrbits(mlqslot->himap,1 << hi);
00787     }
00788 
00789     return (xnpholder_t *)holder;
00790 }
00791 
00792 #endif /* CONFIG_XENO_OPT_SCALABLE_SCHED */
00793 
00794 #endif /* !_XENO_NUCLEUS_QUEUE_H */

Generated on Mon Dec 25 13:57:10 2006 for Xenomai API by  doxygen 1.4.6