Rev 552 | Rev 615 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 552 | Rev 557 | ||
|---|---|---|---|
| Line 31... | Line 31... | ||
| 31 | #include <synch/spinlock.h> |
31 | #include <synch/spinlock.h> |
| 32 | #include <proc/thread.h> |
32 | #include <proc/thread.h> |
| 33 | #include <proc/scheduler.h> |
33 | #include <proc/scheduler.h> |
| 34 | #include <arch/asm.h> |
34 | #include <arch/asm.h> |
| 35 | #include <arch/types.h> |
35 | #include <arch/types.h> |
| - | 36 | #include <typedefs.h> |
|
| 36 | #include <time/timeout.h> |
37 | #include <time/timeout.h> |
| 37 | #include <arch.h> |
38 | #include <arch.h> |
| 38 | #include <context.h> |
39 | #include <context.h> |
| 39 | #include <list.h> |
40 | #include <list.h> |
| 40 | 41 | ||
| Line 65... | Line 66... | ||
| 65 | */ |
66 | */ |
| 66 | void waitq_interrupted_sleep(void *data) |
67 | void waitq_interrupted_sleep(void *data) |
| 67 | { |
68 | { |
| 68 | thread_t *t = (thread_t *) data; |
69 | thread_t *t = (thread_t *) data; |
| 69 | waitq_t *wq; |
70 | waitq_t *wq; |
| 70 | int do_wakeup = 0; |
71 | bool do_wakeup = false; |
| 71 | 72 | ||
| 72 | spinlock_lock(&threads_lock); |
73 | spinlock_lock(&threads_lock); |
| 73 | if (!list_member(&t->threads_link, &threads_head)) |
74 | if (!list_member(&t->threads_link, &threads_head)) |
| 74 | goto out; |
75 | goto out; |
| 75 | 76 | ||
| 76 | grab_locks: |
77 | grab_locks: |
| 77 | spinlock_lock(&t->lock); |
78 | spinlock_lock(&t->lock); |
| 78 | if (wq = t->sleep_queue) { |
79 | if (wq = t->sleep_queue) { /* assignment */ |
| 79 | if (!spinlock_trylock(&wq->lock)) { |
80 | if (!spinlock_trylock(&wq->lock)) { |
| 80 | spinlock_unlock(&t->lock); |
81 | spinlock_unlock(&t->lock); |
| 81 | goto grab_locks; /* avoid deadlock */ |
82 | goto grab_locks; /* avoid deadlock */ |
| 82 | } |
83 | } |
| 83 | 84 | ||
| 84 | list_remove(&t->wq_link); |
85 | list_remove(&t->wq_link); |
| 85 | t->saved_context = t->sleep_timeout_context; |
86 | t->saved_context = t->sleep_timeout_context; |
| 86 | do_wakeup = 1; |
87 | do_wakeup = true; |
| 87 | 88 | ||
| 88 | spinlock_unlock(&wq->lock); |
89 | spinlock_unlock(&wq->lock); |
| 89 | t->sleep_queue = NULL; |
90 | t->sleep_queue = NULL; |
| 90 | } |
91 | } |
| 91 | 92 | ||
| 92 | t->timeout_pending = 0; |
93 | t->timeout_pending = false; |
| 93 | spinlock_unlock(&t->lock); |
94 | spinlock_unlock(&t->lock); |
| 94 | 95 | ||
| - | 96 | if (do_wakeup) |
|
| 95 | if (do_wakeup) thread_ready(t); |
97 | thread_ready(t); |
| 96 | 98 | ||
| 97 | out: |
99 | out: |
| 98 | spinlock_unlock(&threads_lock); |
100 | spinlock_unlock(&threads_lock); |
| 99 | } |
101 | } |
| 100 | 102 | ||
| Line 191... | Line 193... | ||
| 191 | before_thread_runs(); |
193 | before_thread_runs(); |
| 192 | spinlock_unlock(&THREAD->lock); |
194 | spinlock_unlock(&THREAD->lock); |
| 193 | interrupts_restore(ipl); |
195 | interrupts_restore(ipl); |
| 194 | return ESYNCH_TIMEOUT; |
196 | return ESYNCH_TIMEOUT; |
| 195 | } |
197 | } |
| 196 | THREAD->timeout_pending = 1; |
198 | THREAD->timeout_pending = true; |
| 197 | timeout_register(&THREAD->sleep_timeout, (__u64) usec, waitq_interrupted_sleep, THREAD); |
199 | timeout_register(&THREAD->sleep_timeout, (__u64) usec, waitq_interrupted_sleep, THREAD); |
| 198 | } |
200 | } |
| 199 | 201 | ||
| 200 | list_append(&THREAD->wq_link, &wq->head); |
202 | list_append(&THREAD->wq_link, &wq->head); |
| 201 | 203 | ||
| Line 225... | Line 227... | ||
| 225 | * |
227 | * |
| 226 | * @param wq Pointer to wait queue. |
228 | * @param wq Pointer to wait queue. |
| 227 | * @param all If this is non-zero, all sleeping threads |
229 | * @param all If this is non-zero, all sleeping threads |
| 228 | * will be woken up and missed count will be zeroed. |
230 | * will be woken up and missed count will be zeroed. |
| 229 | */ |
231 | */ |
| 230 | void waitq_wakeup(waitq_t *wq, int all) |
232 | void waitq_wakeup(waitq_t *wq, bool all) |
| 231 | { |
233 | { |
| 232 | ipl_t ipl; |
234 | ipl_t ipl; |
| 233 | 235 | ||
| 234 | ipl = interrupts_disable(); |
236 | ipl = interrupts_disable(); |
| 235 | spinlock_lock(&wq->lock); |
237 | spinlock_lock(&wq->lock); |
| Line 248... | Line 250... | ||
| 248 | * |
250 | * |
| 249 | * @param wq Pointer to wait queue. |
251 | * @param wq Pointer to wait queue. |
| 250 | * @param all If this is non-zero, all sleeping threads |
252 | * @param all If this is non-zero, all sleeping threads |
| 251 | * will be woken up and missed count will be zeroed. |
253 | * will be woken up and missed count will be zeroed. |
| 252 | */ |
254 | */ |
| 253 | void _waitq_wakeup_unsafe(waitq_t *wq, int all) |
255 | void _waitq_wakeup_unsafe(waitq_t *wq, bool all) |
| 254 | { |
256 | { |
| 255 | thread_t *t; |
257 | thread_t *t; |
| 256 | 258 | ||
| 257 | loop: |
259 | loop: |
| 258 | if (list_empty(&wq->head)) { |
260 | if (list_empty(&wq->head)) { |
| 259 | wq->missed_wakeups++; |
261 | wq->missed_wakeups++; |
| - | 262 | if (all) |
|
| 260 | if (all) wq->missed_wakeups = 0; |
263 | wq->missed_wakeups = 0; |
| 261 | return; |
264 | return; |
| 262 | } |
265 | } |
| 263 | 266 | ||
| 264 | t = list_get_instance(wq->head.next, thread_t, wq_link); |
267 | t = list_get_instance(wq->head.next, thread_t, wq_link); |
| 265 | 268 | ||
| 266 | list_remove(&t->wq_link); |
269 | list_remove(&t->wq_link); |
| 267 | spinlock_lock(&t->lock); |
270 | spinlock_lock(&t->lock); |
| 268 | if (t->timeout_pending && timeout_unregister(&t->sleep_timeout)) |
271 | if (t->timeout_pending && timeout_unregister(&t->sleep_timeout)) |
| 269 | t->timeout_pending = 0; |
272 | t->timeout_pending = false; |
| 270 | t->sleep_queue = NULL; |
273 | t->sleep_queue = NULL; |
| 271 | spinlock_unlock(&t->lock); |
274 | spinlock_unlock(&t->lock); |
| 272 | 275 | ||
| 273 | thread_ready(t); |
276 | thread_ready(t); |
| 274 | 277 | ||
| - | 278 | if (all) |
|
| 275 | if (all) goto loop; |
279 | goto loop; |
| 276 | } |
280 | } |