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 |