OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uC-libc/] [include/] [linux/] [tqueue.h] - Blame information for rev 1775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
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, tq_disk;
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,
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,
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,
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)
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 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.