This commit was generated by cvs2svn to compensate for changes in r925,
[linux-2.6.git] / include / asm-xen / queues.h
1
2 /*
3  * Oh dear. Task queues were removed from Linux 2.6 and replaced by work 
4  * queues. Unfortunately the semantics is not the same. With task queues we 
5  * can defer work until a particular event occurs -- this is not
6  * straightforwardly done with work queues (queued work is performed asap, or
7  * after some fixed timeout). Conversely, work queues are a (slightly) neater
8  * way of deferring work to a process context than using task queues in 2.4.
9  * 
10  * This is a bit of a needless reimplementation -- should have just pulled
11  * the code from 2.4, but I tried leveraging work queues to simplify things.
12  * They didn't help. :-(
13  */
14
15 #ifndef __QUEUES_H__
16 #define __QUEUES_H__
17
18 #include <linux/version.h>
19 #include <linux/list.h>
20 #include <linux/workqueue.h>
21
22 struct tq_struct { 
23     void (*fn)(void *);
24     void *arg;
25     struct list_head list;
26     unsigned long pending;
27 };
28 #define INIT_TQUEUE(_name, _fn, _arg)               \
29     do {                                            \
30         INIT_LIST_HEAD(&(_name)->list);             \
31         (_name)->pending = 0;                       \
32         (_name)->fn = (_fn); (_name)->arg = (_arg); \
33     } while ( 0 )
34 #define DECLARE_TQUEUE(_name, _fn, _arg)            \
35     struct tq_struct _name = { (_fn), (_arg), LIST_HEAD_INIT((_name).list), 0 }
36
37 typedef struct {
38     struct list_head list;
39     spinlock_t       lock;
40 } task_queue;
41 #define DECLARE_TASK_QUEUE(_name) \
42     task_queue _name = { LIST_HEAD_INIT((_name).list), SPIN_LOCK_UNLOCKED }
43
44 static inline int queue_task(struct tq_struct *tqe, task_queue *tql)
45 {
46     unsigned long flags;
47     if ( test_and_set_bit(0, &tqe->pending) )
48         return 0;
49     spin_lock_irqsave(&tql->lock, flags);
50     list_add_tail(&tqe->list, &tql->list);
51     spin_unlock_irqrestore(&tql->lock, flags);
52     return 1;
53 }
54
55 static inline void run_task_queue(task_queue *tql)
56 {
57     struct list_head head, *ent;
58     struct tq_struct *tqe;
59     unsigned long flags;
60     void (*fn)(void *);
61     void *arg;
62
63     spin_lock_irqsave(&tql->lock, flags);
64     list_add(&head, &tql->list);
65     list_del_init(&tql->list);
66     spin_unlock_irqrestore(&tql->lock, flags);
67
68     while ( !list_empty(&head) )
69     {
70         ent = head.next;
71         list_del_init(ent);
72         tqe = list_entry(ent, struct tq_struct, list);
73         fn  = tqe->fn;
74         arg = tqe->arg;
75         wmb();
76         tqe->pending = 0;
77         fn(arg);
78     }
79 }
80
81 #endif /* __QUEUES_H__ */