Rev 1467 | Rev 1579 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1467 | Rev 1502 | ||
---|---|---|---|
Line 133... | Line 133... | ||
133 | goto out; |
133 | goto out; |
134 | 134 | ||
135 | grab_locks: |
135 | grab_locks: |
136 | spinlock_lock(&t->lock); |
136 | spinlock_lock(&t->lock); |
137 | if ((wq = t->sleep_queue)) { /* assignment */ |
137 | if ((wq = t->sleep_queue)) { /* assignment */ |
- | 138 | if (!(t->sleep_interruptible)) { |
|
- | 139 | /* |
|
- | 140 | * The sleep cannot be interrupted. |
|
- | 141 | */ |
|
- | 142 | spinlock_unlock(&t->lock); |
|
- | 143 | goto out; |
|
- | 144 | } |
|
- | 145 | ||
138 | if (!spinlock_trylock(&wq->lock)) { |
146 | if (!spinlock_trylock(&wq->lock)) { |
139 | spinlock_unlock(&t->lock); |
147 | spinlock_unlock(&t->lock); |
140 | goto grab_locks; /* avoid deadlock */ |
148 | goto grab_locks; /* avoid deadlock */ |
141 | } |
149 | } |
142 | 150 | ||
Line 157... | Line 165... | ||
157 | interrupts_restore(ipl); |
165 | interrupts_restore(ipl); |
158 | } |
166 | } |
159 | 167 | ||
160 | /** Sleep until either wakeup, timeout or interruption occurs |
168 | /** Sleep until either wakeup, timeout or interruption occurs |
161 | * |
169 | * |
162 | * This is a sleep implementation which allows itself to be |
170 | * This is a sleep implementation which allows itself to time out or to be |
163 | * interrupted from the sleep, restoring a failover context. |
171 | * interrupted from the sleep, restoring a failover context. |
164 | * |
172 | * |
165 | * Sleepers are organised in a FIFO fashion in a structure called wait queue. |
173 | * Sleepers are organised in a FIFO fashion in a structure called wait queue. |
166 | * |
174 | * |
167 | * This function is really basic in that other functions as waitq_sleep() |
175 | * This function is really basic in that other functions as waitq_sleep() |
168 | * and all the *_timeout() functions use it. |
176 | * and all the *_timeout() functions use it. |
169 | * |
177 | * |
170 | * @param wq Pointer to wait queue. |
178 | * @param wq Pointer to wait queue. |
171 | * @param usec Timeout in microseconds. |
179 | * @param usec Timeout in microseconds. |
172 | * @param nonblocking Blocking vs. non-blocking operation mode switch. |
180 | * @param flags Specify mode of the sleep. |
173 | * |
181 | * |
- | 182 | * The sleep can be interrupted only if the |
|
- | 183 | * SYNCH_FLAGS_INTERRUPTIBLE bit is specified in flags. |
|
- | 184 | |
|
174 | * If usec is greater than zero, regardless of the value of nonblocking, |
185 | * If usec is greater than zero, regardless of the value of the |
175 | * the call will not return until either timeout or wakeup comes. |
186 | * SYNCH_FLAGS_NON_BLOCKING bit in flags, the call will not return until either timeout, |
- | 187 | * interruption or wakeup comes. |
|
176 | * |
188 | * |
177 | * If usec is zero and @nonblocking is zero (false), the call |
189 | * If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is not set in flags, the call |
178 | * will not return until wakeup comes. |
190 | * will not return until wakeup or interruption comes. |
179 | * |
191 | * |
180 | * If usec is zero and nonblocking is non-zero (true), the call will |
192 | * If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is set in flags, the call will |
181 | * immediately return, reporting either success or failure. |
193 | * immediately return, reporting either success or failure. |
182 | * |
194 | * |
183 | * @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, |
195 | * @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, ESYNCH_INTERRUPTED, |
184 | * ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED. |
196 | * ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED. |
185 | * |
197 | * |
186 | * @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time |
198 | * @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time |
187 | * of the call there was no pending wakeup. |
199 | * of the call there was no pending wakeup. |
188 | * |
200 | * |
Line 195... | Line 207... | ||
195 | * asleep at all. |
207 | * asleep at all. |
196 | * |
208 | * |
197 | * @li ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was |
209 | * @li ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was |
198 | * attempted. |
210 | * attempted. |
199 | */ |
211 | */ |
200 | int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking) |
212 | int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int flags) |
201 | { |
213 | { |
202 | ipl_t ipl; |
214 | ipl_t ipl; |
203 | int rc; |
215 | int rc; |
204 | 216 | ||
205 | ipl = waitq_sleep_prepare(wq); |
217 | ipl = waitq_sleep_prepare(wq); |
206 | rc = waitq_sleep_timeout_unsafe(wq, usec, nonblocking); |
218 | rc = waitq_sleep_timeout_unsafe(wq, usec, flags); |
207 | waitq_sleep_finish(wq, rc, ipl); |
219 | waitq_sleep_finish(wq, rc, ipl); |
208 | return rc; |
220 | return rc; |
209 | } |
221 | } |
210 | 222 | ||
211 | /** Prepare to sleep in a waitq. |
223 | /** Prepare to sleep in a waitq. |
Line 274... | Line 286... | ||
274 | * This call must be preceeded by a call to waitq_sleep_prepare() |
286 | * This call must be preceeded by a call to waitq_sleep_prepare() |
275 | * and followed by a call to waitq_slee_finish(). |
287 | * and followed by a call to waitq_slee_finish(). |
276 | * |
288 | * |
277 | * @param wq See waitq_sleep_timeout(). |
289 | * @param wq See waitq_sleep_timeout(). |
278 | * @param usec See waitq_sleep_timeout(). |
290 | * @param usec See waitq_sleep_timeout(). |
279 | * @param nonblocking See waitq_sleep_timeout(). |
291 | * @param flags See waitq_sleep_timeout(). |
280 | * |
292 | * |
281 | * @return See waitq_sleep_timeout(). |
293 | * @return See waitq_sleep_timeout(). |
282 | */ |
294 | */ |
283 | int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int nonblocking) |
295 | int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int flags) |
284 | { |
296 | { |
285 | /* checks whether to go to sleep at all */ |
297 | /* checks whether to go to sleep at all */ |
286 | if (wq->missed_wakeups) { |
298 | if (wq->missed_wakeups) { |
287 | wq->missed_wakeups--; |
299 | wq->missed_wakeups--; |
288 | return ESYNCH_OK_ATOMIC; |
300 | return ESYNCH_OK_ATOMIC; |
289 | } |
301 | } |
290 | else { |
302 | else { |
291 | if (nonblocking && (usec == 0)) { |
303 | if ((flags & SYNCH_FLAGS_NON_BLOCKING) && (usec == 0)) { |
292 | /* return immediatelly instead of going to sleep */ |
304 | /* return immediatelly instead of going to sleep */ |
293 | return ESYNCH_WOULD_BLOCK; |
305 | return ESYNCH_WOULD_BLOCK; |
294 | } |
306 | } |
295 | } |
307 | } |
296 | 308 | ||
297 | /* |
309 | /* |
298 | * Now we are firmly decided to go to sleep. |
310 | * Now we are firmly decided to go to sleep. |
299 | */ |
311 | */ |
300 | spinlock_lock(&THREAD->lock); |
312 | spinlock_lock(&THREAD->lock); |
301 | 313 | ||
- | 314 | if (flags & SYNCH_FLAGS_INTERRUPTIBLE) { |
|
302 | /* |
315 | /* |
303 | * Set context that will be restored if the sleep |
316 | * Set context that will be restored if the sleep |
304 | * of this thread is ever interrupted. |
317 | * of this thread is ever interrupted. |
305 | */ |
318 | */ |
- | 319 | THREAD->sleep_interruptible = true; |
|
306 | if (!context_save(&THREAD->sleep_interruption_context)) { |
320 | if (!context_save(&THREAD->sleep_interruption_context)) { |
307 | /* Short emulation of scheduler() return code. */ |
321 | /* Short emulation of scheduler() return code. */ |
308 | spinlock_unlock(&THREAD->lock); |
322 | spinlock_unlock(&THREAD->lock); |
309 | return ESYNCH_INTERRUPTED; |
323 | return ESYNCH_INTERRUPTED; |
- | 324 | } |
|
- | 325 | } else { |
|
- | 326 | THREAD->sleep_interruptible = false; |
|
310 | } |
327 | } |
311 | 328 | ||
312 | if (usec) { |
329 | if (usec) { |
313 | /* We use the timeout variant. */ |
330 | /* We use the timeout variant. */ |
314 | if (!context_save(&THREAD->sleep_timeout_context)) { |
331 | if (!context_save(&THREAD->sleep_timeout_context)) { |