Rev 25 | Rev 404 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 25 | Rev 382 | ||
---|---|---|---|
Line 24... | Line 24... | ||
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | #include <context.h> |
- | |
30 | #include <proc/thread.h> |
- | |
31 | - | ||
32 | #include <synch/synch.h> |
- | |
33 | #include <synch/waitq.h> |
29 | #include <synch/waitq.h> |
- | 30 | #include <synch/synch.h> |
|
34 | #include <synch/spinlock.h> |
31 | #include <synch/spinlock.h> |
35 | - | ||
- | 32 | #include <proc/thread.h> |
|
36 | #include <arch/asm.h> |
33 | #include <arch/asm.h> |
37 | #include <arch/types.h> |
34 | #include <arch/types.h> |
- | 35 | #include <time/timeout.h> |
|
38 | #include <arch.h> |
36 | #include <arch.h> |
39 | - | ||
- | 37 | #include <context.h> |
|
40 | #include <list.h> |
38 | #include <list.h> |
41 | 39 | ||
42 | #include <time/timeout.h> |
40 | /** Initialize wait queue |
43 | 41 | * |
|
- | 42 | * Initialize wait queue. |
|
- | 43 | * |
|
- | 44 | * @param wq Pointer to wait queue to be initialized. |
|
- | 45 | */ |
|
44 | void waitq_initialize(waitq_t *wq) |
46 | void waitq_initialize(waitq_t *wq) |
45 | { |
47 | { |
46 | spinlock_initialize(&wq->lock); |
48 | spinlock_initialize(&wq->lock); |
47 | list_initialize(&wq->head); |
49 | list_initialize(&wq->head); |
48 | wq->missed_wakeups = 0; |
50 | wq->missed_wakeups = 0; |
49 | } |
51 | } |
50 | 52 | ||
- | 53 | /** Handle timeout during waitq_sleep_timeout() call |
|
51 | /* |
54 | * |
52 | * Called with interrupts disabled from clock() when sleep_timeout |
55 | * This routine is called when waitq_sleep_timeout() timeouts. |
53 | * timeouts. This function is not allowed to enable interrupts. |
56 | * Interrupts are disabled. |
54 | * |
57 | * |
55 | * It is supposed to try to remove 'its' thread from the waitqueue; it |
58 | * It is supposed to try to remove 'its' thread from the wait queue; |
56 | * can eventually fail to achieve this goal when these two events |
59 | * it can eventually fail to achieve this goal when these two events |
57 | * overlap; in that case it behaves just as though there was no |
60 | * overlap. In that case it behaves just as though there was no |
58 | * timeout at all |
61 | * timeout at all. |
- | 62 | * |
|
- | 63 | * @param data Pointer to the thread that called waitq_sleep_timeout(). |
|
59 | */ |
64 | */ |
60 | void waitq_interrupted_sleep(void *data) |
65 | void waitq_interrupted_sleep(void *data) |
61 | { |
66 | { |
62 | thread_t *t = (thread_t *) data; |
67 | thread_t *t = (thread_t *) data; |
63 | waitq_t *wq; |
68 | waitq_t *wq; |
Line 90... | Line 95... | ||
90 | 95 | ||
91 | out: |
96 | out: |
92 | spinlock_unlock(&threads_lock); |
97 | spinlock_unlock(&threads_lock); |
93 | } |
98 | } |
94 | 99 | ||
- | 100 | /** Sleep until either wakeup or timeout occurs |
|
95 | /* |
101 | * |
96 | * This is a sleep implementation which allows itself to be |
102 | * This is a sleep implementation which allows itself to be |
97 | * interrupted from the sleep, restoring a failover context. |
103 | * interrupted from the sleep, restoring a failover context. |
98 | * |
104 | * |
- | 105 | * Sleepers are organised in FIFO fashion in a structure called wait queue. |
|
- | 106 | * |
|
99 | * This function is really basic in that other functions as waitq_sleep() |
107 | * This function is really basic in that other functions as waitq_sleep() |
100 | * and all the *_timeout() functions use it. |
108 | * and all the *_timeout() functions use it. |
101 | * |
109 | * |
- | 110 | * @param wq Pointer to wait queue. |
|
- | 111 | * @param usec Timeout value in microseconds. |
|
102 | * The third argument controls whether only a conditional sleep |
112 | * @param nonblocking Controls whether only a conditional sleep |
103 | * (non-blocking sleep) is called for when the second argument is 0. |
113 | * (non-blocking sleep) is called for when the usec argument is 0. |
- | 114 | * |
|
- | 115 | * Relation between 'usec' and 'nonblocking' is described by this table: |
|
104 | * |
116 | * |
105 | * usec | nonblocking | what happens if there is no missed_wakeup |
117 | * usec | nonblocking | what happens if there is no missed_wakeup |
106 | * -----+-------------+-------------------------------------------- |
118 | * -----+-------------+-------------------------------------------- |
107 | * 0 | 0 | blocks without timeout until wakeup |
119 | * 0 | 0 | blocks without timeout until wakeup |
108 | * 0 | <> 0 | immediately returns ESYNCH_WOULD_BLOCK |
120 | * 0 | <> 0 | immediately returns ESYNCH_WOULD_BLOCK |
109 | * > 0 | x | blocks with timeout until timeout or wakeup |
121 | * > 0 | x | blocks with timeout until timeout or wakeup |
110 | * |
122 | * |
111 | * return values: |
123 | * @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, |
112 | * ESYNCH_WOULD_BLOCK |
124 | * ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED. |
- | 125 | * |
|
- | 126 | * Meaning of the return values is described by the following chart: |
|
- | 127 | * |
|
- | 128 | * ESYNCH_WOULD_BLOCK Sleep failed because at the time of the call, |
|
- | 129 | * there was no pending wakeup. |
|
113 | * ESYNCH_TIMEOUT |
130 | * ESYNCH_TIMEOUT Sleep timed out. |
114 | * ESYNCH_OK_ATOMIC |
131 | * ESYNCH_OK_ATOMIC Sleep succeeded; at the time of the call, |
115 | * ESYNCH_OK_BLOCKED |
132 | * where was a pending wakeup. |
- | 133 | * ESYNCH_OK_BLOCKED Sleep succeeded; the full sleep was attempted. |
|
116 | */ |
134 | */ |
117 | int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking) |
135 | int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking) |
118 | { |
136 | { |
119 | volatile pri_t pri; /* must be live after context_restore() */ |
137 | volatile pri_t pri; /* must be live after context_restore() */ |
120 | 138 | ||
Line 190... | Line 208... | ||
190 | 208 | ||
191 | return ESYNCH_OK_BLOCKED; |
209 | return ESYNCH_OK_BLOCKED; |
192 | } |
210 | } |
193 | 211 | ||
194 | 212 | ||
- | 213 | /** Wake up first thread sleeping in a wait queue |
|
195 | /* |
214 | * |
- | 215 | * Wake up first thread sleeping in a wait queue. |
|
196 | * This is the SMP- and IRQ-safe wrapper meant for general use. |
216 | * This is the SMP- and IRQ-safe wrapper meant for |
- | 217 | * general use. |
|
197 | */ |
218 | * |
- | 219 | * Besides its 'normal' wakeup operation, it attempts |
|
- | 220 | * to unregister possible timeout. |
|
198 | /* |
221 | * |
- | 222 | * @param wq Pointer to wait queue. |
|
- | 223 | * @param all If this is non-zero, all sleeping threads |
|
199 | * Besides its 'normal' wakeup operation, it attempts to unregister possible timeout. |
224 | * will be woken up and missed count will be zeroed. |
200 | */ |
225 | */ |
201 | void waitq_wakeup(waitq_t *wq, int all) |
226 | void waitq_wakeup(waitq_t *wq, int all) |
202 | { |
227 | { |
203 | pri_t pri; |
228 | pri_t pri; |
204 | 229 | ||
Line 209... | Line 234... | ||
209 | 234 | ||
210 | spinlock_unlock(&wq->lock); |
235 | spinlock_unlock(&wq->lock); |
211 | cpu_priority_restore(pri); |
236 | cpu_priority_restore(pri); |
212 | } |
237 | } |
213 | 238 | ||
- | 239 | /** Internal SMP- and IRQ-unsafe version of waitq_wakeup() |
|
214 | /* |
240 | * |
215 | * This is the internal SMP- and IRQ-unsafe version of waitq_wakeup. |
241 | * This is the internal SMP- and IRQ-unsafe version |
216 | * It assumes wq->lock is already locked. |
242 | * of waitq_wakeup(). It assumes wq->lock is already |
- | 243 | * locked and interrupts are already disabled. |
|
- | 244 | * |
|
- | 245 | * @param wq Pointer to wait queue. |
|
- | 246 | * @param all If this is non-zero, all sleeping threads |
|
- | 247 | * will be woken up and missed count will be zeroed. |
|
217 | */ |
248 | */ |
218 | void _waitq_wakeup_unsafe(waitq_t *wq, int all) |
249 | void _waitq_wakeup_unsafe(waitq_t *wq, int all) |
219 | { |
250 | { |
220 | thread_t *t; |
251 | thread_t *t; |
221 | 252 |