Rev 2087 | Rev 2109 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2087 | Rev 2089 | ||
|---|---|---|---|
| Line 47... | Line 47... | ||
| 47 | #include <synch/spinlock.h> |
47 | #include <synch/spinlock.h> |
| 48 | #include <proc/thread.h> |
48 | #include <proc/thread.h> |
| 49 | #include <proc/scheduler.h> |
49 | #include <proc/scheduler.h> |
| 50 | #include <arch/asm.h> |
50 | #include <arch/asm.h> |
| 51 | #include <arch/types.h> |
51 | #include <arch/types.h> |
| 52 | #include <typedefs.h> |
- | |
| 53 | #include <time/timeout.h> |
52 | #include <time/timeout.h> |
| 54 | #include <arch.h> |
53 | #include <arch.h> |
| 55 | #include <context.h> |
54 | #include <context.h> |
| 56 | #include <adt/list.h> |
55 | #include <adt/list.h> |
| 57 | 56 | ||
| Line 115... | Line 114... | ||
| 115 | 114 | ||
| 116 | out: |
115 | out: |
| 117 | spinlock_unlock(&threads_lock); |
116 | spinlock_unlock(&threads_lock); |
| 118 | } |
117 | } |
| 119 | 118 | ||
| 120 | /** Interrupt sleeping thread. |
- | |
| 121 | * |
- | |
| 122 | * This routine attempts to interrupt a thread from its sleep in a waitqueue. |
- | |
| 123 | * If the thread is not found sleeping, no action is taken. |
- | |
| 124 | * |
- | |
| 125 | * @param t Thread to be interrupted. |
- | |
| 126 | */ |
- | |
| 127 | void waitq_interrupt_sleep(thread_t *t) |
- | |
| 128 | { |
- | |
| 129 | waitq_t *wq; |
- | |
| 130 | bool do_wakeup = false; |
- | |
| 131 | ipl_t ipl; |
- | |
| 132 | - | ||
| 133 | ipl = interrupts_disable(); |
- | |
| 134 | spinlock_lock(&threads_lock); |
- | |
| 135 | if (!thread_exists(t)) |
- | |
| 136 | goto out; |
- | |
| 137 | - | ||
| 138 | grab_locks: |
- | |
| 139 | spinlock_lock(&t->lock); |
- | |
| 140 | if ((wq = t->sleep_queue)) { /* assignment */ |
- | |
| 141 | if (!(t->sleep_interruptible)) { |
- | |
| 142 | /* |
- | |
| 143 | * The sleep cannot be interrupted. |
- | |
| 144 | */ |
- | |
| 145 | spinlock_unlock(&t->lock); |
- | |
| 146 | goto out; |
- | |
| 147 | } |
- | |
| 148 | - | ||
| 149 | if (!spinlock_trylock(&wq->lock)) { |
- | |
| 150 | spinlock_unlock(&t->lock); |
- | |
| 151 | goto grab_locks; /* avoid deadlock */ |
- | |
| 152 | } |
- | |
| 153 | - | ||
| 154 | if (t->timeout_pending && timeout_unregister(&t->sleep_timeout)) |
- | |
| 155 | t->timeout_pending = false; |
- | |
| 156 | - | ||
| 157 | list_remove(&t->wq_link); |
- | |
| 158 | t->saved_context = t->sleep_interruption_context; |
- | |
| 159 | do_wakeup = true; |
- | |
| 160 | t->sleep_queue = NULL; |
- | |
| 161 | spinlock_unlock(&wq->lock); |
- | |
| 162 | } |
- | |
| 163 | spinlock_unlock(&t->lock); |
- | |
| 164 | - | ||
| 165 | if (do_wakeup) |
- | |
| 166 | thread_ready(t); |
- | |
| 167 | - | ||
| 168 | out: |
- | |
| 169 | spinlock_unlock(&threads_lock); |
- | |
| 170 | interrupts_restore(ipl); |
- | |
| 171 | } |
- | |
| 172 | 119 | ||
| 173 | /** Sleep until either wakeup, timeout or interruption occurs |
120 | /** Sleep until either wakeup, timeout or interruption occurs |
| 174 | * |
121 | * |
| 175 | * This is a sleep implementation which allows itself to time out or to be |
122 | * This is a sleep implementation which allows itself to time out or to be |
| 176 | * interrupted from the sleep, restoring a failover context. |
123 | * interrupted from the sleep, restoring a failover context. |
| Line 423... | Line 370... | ||
| 423 | /* |
370 | /* |
| 424 | * Lock the thread prior to removing it from the wq. |
371 | * Lock the thread prior to removing it from the wq. |
| 425 | * This is not necessary because of mutual exclusion |
372 | * This is not necessary because of mutual exclusion |
| 426 | * (the link belongs to the wait queue), but because |
373 | * (the link belongs to the wait queue), but because |
| 427 | * of synchronization with waitq_timeouted_sleep() |
374 | * of synchronization with waitq_timeouted_sleep() |
| 428 | * and waitq_interrupt_sleep(). |
375 | * and thread_interrupt_sleep(). |
| 429 | * |
376 | * |
| 430 | * In order for these two functions to work, the following |
377 | * In order for these two functions to work, the following |
| 431 | * invariant must hold: |
378 | * invariant must hold: |
| 432 | * |
379 | * |
| 433 | * t->sleep_queue != NULL <=> t sleeps in a wait queue |
380 | * t->sleep_queue != NULL <=> t sleeps in a wait queue |