root/include/linux/tqueue.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. queue_task_irq
  2. queue_task_irq_off
  3. queue_task
  4. run_task_queue

   1 /*
   2  * tqueue.h --- task queue handling for Linux.
   3  *
   4  * Mostly based on a proposed bottom-half replacement code written by
   5  * Kai Petzke, wpp@marie.physik.tu-berlin.de.
   6  *
   7  * Modified for use in the Linux kernel by Theodore Ts'o,
   8  * tytso@mit.edu.  Any bugs are my fault, not Kai's.
   9  *
  10  * The original comment follows below.
  11  */
  12 
  13 #ifndef _LINUX_TQUEUE_H
  14 #define _LINUX_TQUEUE_H
  15 
  16 #include <asm/bitops.h>
  17 #include <asm/system.h>
  18 
  19 /*
  20  * New proposed "bottom half" handlers:
  21  * (C) 1994 Kai Petzke, wpp@marie.physik.tu-berlin.de
  22  *
  23  * Advantages:
  24  * - Bottom halfs are implemented as a linked list.  You can have as many
  25  *   of them, as you want.
  26  * - No more scanning of a bit field is required upon call of a bottom half.
  27  * - Support for chained bottom half lists.  The run_task_queue() function can be
  28  *   used as a bottom half handler.  This is for example useful for bottom
  29  *   halfs, which want to be delayed until the next clock tick.
  30  *
  31  * Problems:
  32  * - The queue_task_irq() inline function is only atomic with respect to itself.
  33  *   Problems can occur, when queue_task_irq() is called from a normal system
  34  *   call, and an interrupt comes in.  No problems occur, when queue_task_irq()
  35  *   is called from an interrupt or bottom half, and interrupted, as run_task_queue()
  36  *   will not be executed/continued before the last interrupt returns.  If in
  37  *   doubt, use queue_task(), not queue_task_irq().
  38  * - Bottom halfs are called in the reverse order that they were linked into
  39  *   the list.
  40  */
  41 
  42 struct tq_struct {
  43         struct tq_struct *next;         /* linked list of active bh's */
  44         int sync;                       /* must be initialized to zero */
  45         void (*routine)(void *);        /* function to call */
  46         void *data;                     /* argument to function */
  47 };
  48 
  49 typedef struct tq_struct * task_queue;
  50 
  51 #define DECLARE_TASK_QUEUE(q)  task_queue q = NULL
  52 
  53 extern task_queue tq_timer, tq_immediate, tq_scheduler;
  54 
  55 /*
  56  * To implement your own list of active bottom halfs, use the following
  57  * two definitions:
  58  *
  59  * struct tq_struct *my_bh = NULL;
  60  * struct tq_struct run_my_bh = {
  61  *      0, 0, (void *)(void *) run_task_queue, &my_bh
  62  * };
  63  *
  64  * To activate a bottom half on your list, use:
  65  *
  66  *     queue_task(tq_pointer, &my_bh);
  67  *
  68  * To run the bottom halfs on your list put them on the immediate list by:
  69  *
  70  *     queue_task(&run_my_bh, &tq_immediate);
  71  *
  72  * This allows you to do deferred procession.  For example, you could
  73  * have a bottom half list tq_timer, which is marked active by the timer
  74  * interrupt.
  75  */
  76 
  77 /*
  78  * queue_task_irq: put the bottom half handler "bh_pointer" on the list
  79  * "bh_list".  You may call this function only from an interrupt
  80  * handler or a bottom half handler.
  81  */
  82 extern __inline__ void queue_task_irq(struct tq_struct *bh_pointer,
     /* [previous][next][first][last][top][bottom][index][help] */
  83                                task_queue *bh_list)
  84 {
  85         if (!set_bit(0,&bh_pointer->sync)) {
  86                 bh_pointer->next = *bh_list;
  87                 *bh_list = bh_pointer;
  88         }
  89 }
  90 
  91 /*
  92  * queue_task_irq_off: put the bottom half handler "bh_pointer" on the list
  93  * "bh_list".  You may call this function only when interrupts are off.
  94  */
  95 extern __inline__ void queue_task_irq_off(struct tq_struct *bh_pointer,
     /* [previous][next][first][last][top][bottom][index][help] */
  96                                  task_queue *bh_list)
  97 {
  98         if (!(bh_pointer->sync & 1)) {
  99                 bh_pointer->sync = 1;
 100                 bh_pointer->next = *bh_list;
 101                 *bh_list = bh_pointer;
 102         }
 103 }
 104 
 105 
 106 /*
 107  * queue_task: as queue_task_irq, but can be called from anywhere.
 108  */
 109 extern __inline__ void queue_task(struct tq_struct *bh_pointer,
     /* [previous][next][first][last][top][bottom][index][help] */
 110                            task_queue *bh_list)
 111 {
 112         if (!set_bit(0,&bh_pointer->sync)) {
 113                 unsigned long flags;
 114                 save_flags(flags);
 115                 cli();
 116                 bh_pointer->next = *bh_list;
 117                 *bh_list = bh_pointer;
 118                 restore_flags(flags);
 119         }
 120 }
 121 
 122 /*
 123  * Call all "bottom halfs" on a given list.
 124  */
 125 extern __inline__ void run_task_queue(task_queue *list)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         struct tq_struct *p;
 128 
 129         p = xchg(list,NULL);
 130         while (p) {
 131                 void *arg;
 132                 void (*f) (void *);
 133                 struct tq_struct *save_p;
 134                 arg    = p -> data;
 135                 f      = p -> routine;
 136                 save_p = p;
 137                 p      = p -> next;
 138                 save_p -> sync = 0;
 139                 (*f)(arg);
 140         }
 141 }
 142 
 143 #endif /* _LINUX_TQUEUE_H */

/* [previous][next][first][last][top][bottom][index][help] */