1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#ifndef __WAIT_H__
#define __WAIT_H__
#include <mini-os/sched.h>
#include <mini-os/os.h>
#include <mini-os/waittypes.h>
#define DEFINE_WAIT(name) \
struct wait_queue name = { \
.thread = get_current(), \
.waiting = 0, \
}
static inline void init_waitqueue_head(struct wait_queue_head *h)
{
MINIOS_STAILQ_INIT(h);
}
static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread)
{
q->thread = thread;
q->waiting = 0;
}
static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
{
if (!q->waiting) {
MINIOS_STAILQ_INSERT_HEAD(h, q, thread_list);
q->waiting = 1;
}
}
static inline void remove_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
{
if (q->waiting) {
MINIOS_STAILQ_REMOVE(h, q, struct wait_queue, thread_list);
q->waiting = 0;
}
}
static inline void wake_up(struct wait_queue_head *head)
{
unsigned long flags;
struct wait_queue *curr, *tmp;
local_irq_save(flags);
MINIOS_STAILQ_FOREACH_SAFE(curr, head, thread_list, tmp)
wake(curr->thread);
local_irq_restore(flags);
}
#define add_waiter(w, wq) do { \
unsigned long flags; \
local_irq_save(flags); \
add_wait_queue(&wq, &w); \
block(get_current()); \
local_irq_restore(flags); \
} while (0)
#define remove_waiter(w, wq) do { \
unsigned long flags; \
local_irq_save(flags); \
remove_wait_queue(&wq, &w); \
local_irq_restore(flags); \
} while (0)
#define wait_event_deadline(wq, condition, deadline) do { \
unsigned long flags; \
DEFINE_WAIT(__wait); \
if(condition) \
break; \
for(;;) \
{ \
/* protect the list */ \
local_irq_save(flags); \
add_wait_queue(&wq, &__wait); \
get_current()->wakeup_time = deadline; \
clear_runnable(get_current()); \
local_irq_restore(flags); \
if((condition) || (deadline && NOW() >= deadline)) \
break; \
schedule(); \
} \
local_irq_save(flags); \
/* need to wake up */ \
wake(get_current()); \
remove_wait_queue(&wq, &__wait); \
local_irq_restore(flags); \
} while(0)
#define wait_event(wq, condition) wait_event_deadline(wq, condition, 0)
#endif /* __WAIT_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
|