The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/queue.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993-1987 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  *
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  *
   23  * any improvements or extensions that they make and grant Carnegie Mellon rights
   24  * to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        queue.h,v $
   29  * Revision 2.6  93/11/17  17:19:37  dbg
   30  *      Added remqueue_macro.
   31  *      [93/05/11            dbg]
   32  * 
   33  *      Added enqueue_tail_macro, dequeue_head_macro.  Added ANSI
   34  *      function prototypes.  Used macro_help.
   35  *      [93/04/01            dbg]
   36  * 
   37  * Revision 2.5  92/05/21  17:15:24  jfriedl
   38  *      Removed comment starter from within comments to shut up gcc warnings.
   39  *      [92/05/16            jfriedl]
   40  * 
   41  * Revision 2.4  91/05/14  16:45:55  mrt
   42  *      Correcting copyright
   43  * 
   44  * Revision 2.3  91/02/05  17:28:43  mrt
   45  *      Changed to new Mach copyright
   46  *      [91/02/01  16:16:28  mrt]
   47  * 
   48  * Revision 2.2  89/09/08  11:26:11  dbg
   49  *      Streamlined generic queue macros.
   50  *      [89/08/17            dbg]
   51  * 
   52  * 19-Dec-88  David Golub (dbg) at Carnegie-Mellon University
   53  *      Added queue_remove_last; removed round_queue.  [Changes from
   54  *      mwyoung: 19 Dec 88.]
   55  *
   56  * 29-Nov-88  David Golub (dbg) at Carnegie-Mellon University
   57  *      Removed include of cputypes.h.  Added queue_iterate.
   58  *      Split into two groups the macros that operate directly on
   59  *      queues (or expect the queue chain to be first in a structure)
   60  *      and those that operate on generic structures (where the chain
   61  *      may be anywhere).
   62  *
   63  * 17-Jan-88  Daniel Julin (dpj) at Carnegie-Mellon University
   64  *      Added queue_enter_first, queue_last and queue_prev for use by
   65  *      the TCP netport code.
   66  *
   67  * 12-Jun-85  Avadis Tevanian (avie) at Carnegie-Mellon University
   68  *      Created.
   69  *
   70  */
   71 /*
   72  *      File:   queue.h
   73  *      Author: Avadis Tevanian, Jr.
   74  *      Date:   1985
   75  *
   76  *      Type definitions for generic queues.
   77  *
   78  */
   79 
   80 #ifndef _KERN_QUEUE_H_
   81 #define _KERN_QUEUE_H_
   82 
   83 #include <kern/lock.h>
   84 #include <kern/macro_help.h>
   85 
   86 /*
   87  *      Queue of abstract objects.  Queue is maintained
   88  *      within that object.
   89  *
   90  *      Supports fast removal from within the queue.
   91  *
   92  *      How to declare a queue of elements of type "foo_t":
   93  *              In the "*foo_t" type, you must have a field of
   94  *              type "queue_chain_t" to hold together this queue.
   95  *              There may be more than one chain through a
   96  *              "foo_t", for use by different queues.
   97  *
   98  *              Declare the queue as a "queue_t" type.
   99  *
  100  *              Elements of the queue (of type "foo_t", that is)
  101  *              are referred to by reference, and cast to type
  102  *              "queue_entry_t" within this module.
  103  */
  104 
  105 /*
  106  *      A generic doubly-linked list (queue).
  107  */
  108 
  109 struct queue_entry {
  110         struct queue_entry      *next;          /* next element */
  111         struct queue_entry      *prev;          /* previous element */
  112 };
  113 
  114 typedef struct queue_entry      *queue_t;
  115 typedef struct queue_entry      queue_head_t;
  116 typedef struct queue_entry      queue_chain_t;
  117 typedef struct queue_entry      *queue_entry_t;
  118 
  119 /*
  120  *      enqueue puts "elt" on the "queue".
  121  *      dequeue returns the first element in the "queue".
  122  *      remqueue removes the specified "elt" from the specified "queue".
  123  */
  124 
  125 #define enqueue(queue,elt)      enqueue_tail(queue, elt)
  126 #define dequeue(queue)          dequeue_head(queue)
  127 
  128 void            enqueue_head(queue_t que, queue_entry_t elt);
  129 void            enqueue_tail(queue_t que, queue_entry_t elt);
  130 queue_entry_t   dequeue_head(queue_t que);
  131 queue_entry_t   dequeue_tail(queue_t que);
  132 void            remqueue(queue_t que, queue_entry_t elt);
  133 
  134 /*
  135  *      Macro:          queue_init
  136  *      Function:
  137  *              Initialize the given queue.
  138  *      Header:
  139  *              void queue_init(q)
  140  *                      queue_t         q;      *MODIFIED*
  141  */
  142 #define queue_init(q)   ((q)->next = (q)->prev = q)
  143 
  144 /*
  145  *      Macro:          queue_first
  146  *      Function:
  147  *              Returns the first entry in the queue,
  148  *      Header:
  149  *              queue_entry_t queue_first(q)
  150  *                      queue_t q;              *IN*
  151  */
  152 #define queue_first(q)  ((q)->next)
  153 
  154 /*
  155  *      Macro:          queue_next
  156  *      Function:
  157  *              Returns the entry after an item in the queue.
  158  *      Header:
  159  *              queue_entry_t queue_next(qc)
  160  *                      queue_t qc;
  161  */
  162 #define queue_next(qc)  ((qc)->next)
  163 
  164 /*
  165  *      Macro:          queue_last
  166  *      Function:
  167  *              Returns the last entry in the queue.
  168  *      Header:
  169  *              queue_entry_t queue_last(q)
  170  *                      queue_t q;               *IN*
  171  */
  172 #define queue_last(q)   ((q)->prev)
  173 
  174 /*
  175  *      Macro:          queue_prev
  176  *      Function:
  177  *              Returns the entry before an item in the queue.
  178  *      Header:
  179  *              queue_entry_t queue_prev(qc)
  180  *                      queue_t qc;
  181  */
  182 #define queue_prev(qc)  ((qc)->prev)
  183 
  184 /*
  185  *      Macro:          queue_end
  186  *      Function:
  187  *              Tests whether a new entry is really the end of
  188  *              the queue.
  189  *      Header:
  190  *              boolean_t queue_end(q, qe)
  191  *                      queue_t q;
  192  *                      queue_entry_t qe;
  193  */
  194 #define queue_end(q, qe)        ((q) == (qe))
  195 
  196 /*
  197  *      Macro:          queue_empty
  198  *      Function:
  199  *              Tests whether a queue is empty.
  200  *      Header:
  201  *              boolean_t queue_empty(q)
  202  *                      queue_t q;
  203  */
  204 #define queue_empty(q)          queue_end((q), queue_first(q))
  205 
  206 
  207 /*
  208  *      Macro:          enqueue_tail_macro
  209  *      Function:
  210  *              Adds the element at the tail of the queue.
  211  *      Header:
  212  *              void enqueue_tail_macro(queue_t que, queue_entry_t elt)
  213  */
  214 #define enqueue_tail_macro(que, elt) \
  215     MACRO_BEGIN \
  216         (elt)->next = (que); \
  217         ((elt)->prev = (que)->prev)->next = (elt); \
  218         (que)->prev = (elt); \
  219     MACRO_END
  220 
  221 /*
  222  *      Macro:          dequeue_head_macro
  223  *      Function:
  224  *              Removes the element at the head of the queue.
  225  *              Assumes that the queue is not empty.
  226  *      Header:
  227  *              void dequeue_tail_macro(queue_t que, queue_entry_t& elt)
  228  *              (elt is an lvalue)
  229  */
  230 #define dequeue_head_macro(que, elt) \
  231     MACRO_BEGIN \
  232         (elt) = (que)->next; \
  233         ((que)->next = (elt)->next)->prev = (que); \
  234     MACRO_END
  235 
  236 /*
  237  *      Macro:          remqueue_macro
  238  *      Function:
  239  *              Removes an arbitrary element from the queue.
  240  *              Assumes that the element is on the queue.
  241  *      Header:
  242  *              void remqueue_macro(queue_t que, queue_entry_t elt)
  243  */
  244 #define remqueue_macro(que, elt) \
  245     MACRO_BEGIN \
  246         (elt)->next->prev = (elt)->prev; \
  247         (elt)->prev->next = (elt)->next; \
  248     MACRO_END
  249 
  250 /*----------------------------------------------------------------*/
  251 /*
  252  * Macros that operate on generic structures.  The queue
  253  * chain may be at any location within the structure, and there
  254  * may be more than one chain.
  255  */
  256 
  257 /*
  258  *      Macro:          queue_enter
  259  *      Function:
  260  *              Insert a new element at the tail of the queue.
  261  *      Header:
  262  *              void queue_enter(q, elt, type, field)
  263  *                      queue_t q;
  264  *                      <type> elt;
  265  *                      <type> is what's in our queue
  266  *                      <field> is the chain field in (*<type>)
  267  */
  268 #define queue_enter(head, elt, type, field)                     \
  269     MACRO_BEGIN                                                 \
  270         register queue_entry_t prev;                            \
  271                                                                 \
  272         prev = (head)->prev;                                    \
  273         if ((head) == prev) {                                   \
  274                 (head)->next = (queue_entry_t) (elt);           \
  275         }                                                       \
  276         else {                                                  \
  277                 ((type)prev)->field.next = (queue_entry_t)(elt);\
  278         }                                                       \
  279         (elt)->field.prev = prev;                               \
  280         (elt)->field.next = head;                               \
  281         (head)->prev = (queue_entry_t) elt;                     \
  282     MACRO_END
  283 
  284 /*
  285  *      Macro:          queue_enter_first
  286  *      Function:
  287  *              Insert a new element at the head of the queue.
  288  *      Header:
  289  *              void queue_enter_first(q, elt, type, field)
  290  *                      queue_t q;
  291  *                      <type> elt;
  292  *                      <type> is what's in our queue
  293  *                      <field> is the chain field in (*<type>)
  294  */
  295 #define queue_enter_first(head, elt, type, field)               \
  296     MACRO_BEGIN                                                 \
  297         register queue_entry_t next;                            \
  298                                                                 \
  299         next = (head)->next;                                    \
  300         if ((head) == next) {                                   \
  301                 (head)->prev = (queue_entry_t) (elt);           \
  302         }                                                       \
  303         else {                                                  \
  304                 ((type)next)->field.prev = (queue_entry_t)(elt);\
  305         }                                                       \
  306         (elt)->field.next = next;                               \
  307         (elt)->field.prev = head;                               \
  308         (head)->next = (queue_entry_t) elt;                     \
  309     MACRO_END
  310 
  311 /*
  312  *      Macro:          queue_field [internal use only]
  313  *      Function:
  314  *              Find the queue_chain_t (or queue_t) for the
  315  *              given element (thing) in the given queue (head)
  316  */
  317 #define queue_field(head, thing, type, field)                   \
  318                 (((head) == (thing)) ? (head) : &((type)(thing))->field)
  319 
  320 /*
  321  *      Macro:          queue_remove
  322  *      Function:
  323  *              Remove an arbitrary item from the queue.
  324  *      Header:
  325  *              void queue_remove(q, qe, type, field)
  326  *                      arguments as in queue_enter
  327  */
  328 #define queue_remove(head, elt, type, field)                    \
  329     MACRO_BEGIN                                                 \
  330         register queue_entry_t  next, prev;                     \
  331                                                                 \
  332         next = (elt)->field.next;                               \
  333         prev = (elt)->field.prev;                               \
  334                                                                 \
  335         if ((head) == next)                                     \
  336                 (head)->prev = prev;                            \
  337         else                                                    \
  338                 ((type)next)->field.prev = prev;                \
  339                                                                 \
  340         if ((head) == prev)                                     \
  341                 (head)->next = next;                            \
  342         else                                                    \
  343                 ((type)prev)->field.next = next;                \
  344     MACRO_END
  345 
  346 /*
  347  *      Macro:          queue_remove_first
  348  *      Function:
  349  *              Remove and return the entry at the head of
  350  *              the queue.
  351  *      Header:
  352  *              queue_remove_first(head, entry, type, field)
  353  *              entry is returned by reference
  354  */
  355 #define queue_remove_first(head, entry, type, field)            \
  356     MACRO_BEGIN                                                 \
  357         register queue_entry_t  next;                           \
  358                                                                 \
  359         (entry) = (type) ((head)->next);                        \
  360         next = (entry)->field.next;                             \
  361                                                                 \
  362         if ((head) == next)                                     \
  363                 (head)->prev = (head);                          \
  364         else                                                    \
  365                 ((type)(next))->field.prev = (head);            \
  366         (head)->next = next;                                    \
  367     MACRO_END
  368 
  369 /*
  370  *      Macro:          queue_remove_last
  371  *      Function:
  372  *              Remove and return the entry at the tail of
  373  *              the queue.
  374  *      Header:
  375  *              queue_remove_last(head, entry, type, field)
  376  *              entry is returned by reference
  377  */
  378 #define queue_remove_last(head, entry, type, field)             \
  379     MACRO_BEGIN                                                 \
  380         register queue_entry_t  prev;                           \
  381                                                                 \
  382         (entry) = (type) ((head)->prev);                        \
  383         prev = (entry)->field.prev;                             \
  384                                                                 \
  385         if ((head) == prev)                                     \
  386                 (head)->next = (head);                          \
  387         else                                                    \
  388                 ((type)(prev))->field.next = (head);            \
  389         (head)->prev = prev;                                    \
  390     MACRO_END
  391 
  392 /*
  393  *      Macro:          queue_assign
  394  */
  395 #define queue_assign(to, from, type, field)                     \
  396     MACRO_BEGIN                                                 \
  397         ((type)((from)->prev))->field.next = (to);              \
  398         ((type)((from)->next))->field.prev = (to);              \
  399         *to = *from;                                            \
  400     MACRO_END
  401 
  402 /*
  403  *      Macro:          queue_iterate
  404  *      Function:
  405  *              iterate over each item in the queue.
  406  *              Generates a 'for' loop, setting elt to
  407  *              each item in turn (by reference).
  408  *      Header:
  409  *              queue_iterate(q, elt, type, field)
  410  *                      queue_t q;
  411  *                      <type> elt;
  412  *                      <type> is what's in our queue
  413  *                      <field> is the chain field in (*<type>)
  414  */
  415 #define queue_iterate(head, elt, type, field)                   \
  416         for ((elt) = (type) queue_first(head);                  \
  417              !queue_end((head), (queue_entry_t)(elt));          \
  418              (elt) = (type) queue_next(&(elt)->field))
  419 
  420 
  421 
  422 /*----------------------------------------------------------------*/
  423 /*
  424  *      Define macros for queues with locks.
  425  */
  426 struct mpqueue_head {
  427         struct queue_entry      head;           /* header for queue */
  428         struct slock            lock;           /* lock for queue */
  429 };
  430 
  431 typedef struct mpqueue_head     mpqueue_head_t;
  432 
  433 #define round_mpq(size)         (size)
  434 
  435 #define mpqueue_init(q) \
  436     MACRO_BEGIN \
  437         queue_init(&(q)->head); \
  438         simple_lock_init(&(q)->lock); \
  439     MACRO_END
  440 
  441 #define mpenqueue_tail(q, elt) \
  442     MACRO_BEGIN \
  443         simple_lock(&(q)->lock); \
  444         enqueue_tail(&(q)->head, elt); \
  445         simple_unlock(&(q)->lock); \
  446     MACRO_END
  447 
  448 #define mpdequeue_head(q, elt) \
  449     MACRO_BEGIN \
  450         simple_lock(&(q)->lock); \
  451         if (queue_empty(&(q)->head)) \
  452                 *(elt) = 0; \
  453         else \
  454                 *(elt) = dequeue_head(&(q)->head); \
  455         simple_unlock(&(q)->lock); \
  456     MACRO_END
  457 
  458 #endif  /* _KERN_QUEUE_H_ */

Cache object: 07fb93e592d540d2bf7789a7ebcd4470


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.