Changes in kernel/generic/src/synch/waitq.c [897fd8f1:63e27ef] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/synch/waitq.c
r897fd8f1 r63e27ef 45 45 46 46 #include <assert.h> 47 #include <errno.h>48 47 #include <synch/waitq.h> 49 48 #include <synch/spinlock.h> … … 239 238 * @param flags Specify mode of the sleep. 240 239 * 241 * @param[out] blocked On return, regardless of the return code,242 * `*blocked` is set to `true` iff the thread went to243 * sleep.244 *245 240 * The sleep can be interrupted only if the 246 241 * SYNCH_FLAGS_INTERRUPTIBLE bit is specified in flags. … … 256 251 * call will immediately return, reporting either success or failure. 257 252 * 258 * @return E AGAIN, meaning that the sleep failed because it was requested259 * as SYNCH_FLAGS_NON_BLOCKING, but there was no pending wakeup.260 * @return E TIMEOUT, meaning that the sleep timed out.261 * @return E INTR, meaning that somebody interrupted the sleeping262 * thread. Check the value of `*blocked` to see if the thread slept,263 * or if a pending interrupt forced it to return immediately.264 * @return EOK, meaning that none of the above conditions occured, and the265 * thread was woken up successfuly by `waitq_wakeup()`. Check266 * the value of `*blocked` to see if the thread slept or if267 * the wakeup was already pending.268 * 269 */ 270 int waitq_sleep_timeout(waitq_t *wq, uint32_t usec, unsigned int flags , bool *blocked)253 * @return ESYNCH_WOULD_BLOCK, meaning that the sleep failed because at the 254 * time of the call there was no pending wakeup 255 * @return ESYNCH_TIMEOUT, meaning that the sleep timed out. 256 * @return ESYNCH_INTERRUPTED, meaning that somebody interrupted the sleeping 257 * thread. 258 * @return ESYNCH_OK_ATOMIC, meaning that the sleep succeeded and that there 259 * was a pending wakeup at the time of the call. The caller was not put 260 * asleep at all. 261 * @return ESYNCH_OK_BLOCKED, meaning that the sleep succeeded; the full sleep 262 * was attempted. 263 * 264 */ 265 int waitq_sleep_timeout(waitq_t *wq, uint32_t usec, unsigned int flags) 271 266 { 272 267 assert((!PREEMPTION_DISABLED) || (PARAM_NON_BLOCKING(flags, usec))); 273 268 274 269 ipl_t ipl = waitq_sleep_prepare(wq); 275 bool nblocked; 276 int rc = waitq_sleep_timeout_unsafe(wq, usec, flags, &nblocked); 277 waitq_sleep_finish(wq, nblocked, ipl); 278 279 if (blocked != NULL) { 280 *blocked = nblocked; 281 } 270 int rc = waitq_sleep_timeout_unsafe(wq, usec, flags); 271 waitq_sleep_finish(wq, rc, ipl); 282 272 return rc; 283 273 } … … 330 320 * lock is released. 331 321 * 332 * @param wq Wait queue. 333 * @param blocked Out parameter of waitq_sleep_timeout_unsafe(). 334 * @param ipl Interrupt level returned by waitq_sleep_prepare(). 335 * 336 */ 337 void waitq_sleep_finish(waitq_t *wq, bool blocked, ipl_t ipl) 338 { 339 if (blocked) { 340 /* 322 * @param wq Wait queue. 323 * @param rc Return code of waitq_sleep_timeout_unsafe(). 324 * @param ipl Interrupt level returned by waitq_sleep_prepare(). 325 * 326 */ 327 void waitq_sleep_finish(waitq_t *wq, int rc, ipl_t ipl) 328 { 329 switch (rc) { 330 case ESYNCH_WOULD_BLOCK: 331 case ESYNCH_OK_ATOMIC: 332 irq_spinlock_unlock(&wq->lock, false); 333 break; 334 default: 335 /* 341 336 * Wait for a waitq_wakeup() or waitq_unsleep() to complete 342 337 * before returning from waitq_sleep() to the caller. Otherwise 343 338 * the caller might expect that the wait queue is no longer used 344 339 * and deallocate it (although the wakeup on a another cpu has 345 * not yet completed and is using the wait queue). 346 * 347 * Note that we have to do this for EOK and EINTR, but not 348 * necessarily for ETIMEOUT where the timeout handler stops 349 * using the waitq before waking us up. To be on the safe side, 350 * ensure the waitq is not in use anymore in this case as well. 340 * not yet completed and is using the wait queue). 341 * 342 * Note that we have to do this for ESYNCH_OK_BLOCKED and 343 * ESYNCH_INTERRUPTED, but not necessarily for ESYNCH_TIMEOUT 344 * where the timeout handler stops using the waitq before waking 345 * us up. To be on the safe side, ensure the waitq is not in use 346 * anymore in this case as well. 351 347 */ 352 348 waitq_complete_wakeup(wq); 353 } else { 354 irq_spinlock_unlock(&wq->lock, false); 349 break; 355 350 } 356 351 … … 368 363 * @param flags See waitq_sleep_timeout(). 369 364 * 370 * @param[out] blocked See waitq_sleep_timeout().371 *372 365 * @return See waitq_sleep_timeout(). 373 366 * 374 367 */ 375 int waitq_sleep_timeout_unsafe(waitq_t *wq, uint32_t usec, unsigned int flags, bool *blocked) 376 { 377 *blocked = false; 378 368 int waitq_sleep_timeout_unsafe(waitq_t *wq, uint32_t usec, unsigned int flags) 369 { 379 370 /* Checks whether to go to sleep at all */ 380 371 if (wq->missed_wakeups) { 381 372 wq->missed_wakeups--; 382 return E OK;373 return ESYNCH_OK_ATOMIC; 383 374 } else { 384 375 if (PARAM_NON_BLOCKING(flags, usec)) { 385 376 /* Return immediately instead of going to sleep */ 386 return E AGAIN;377 return ESYNCH_WOULD_BLOCK; 387 378 } 388 379 } … … 401 392 if (THREAD->interrupted) { 402 393 irq_spinlock_unlock(&THREAD->lock, false); 403 return EINTR; 394 irq_spinlock_unlock(&wq->lock, false); 395 return ESYNCH_INTERRUPTED; 404 396 } 405 397 … … 413 405 THREAD->last_cycle = get_cycle(); 414 406 irq_spinlock_unlock(&THREAD->lock, false); 415 return E INTR;407 return ESYNCH_INTERRUPTED; 416 408 } 417 409 } else … … 424 416 THREAD->last_cycle = get_cycle(); 425 417 irq_spinlock_unlock(&THREAD->lock, false); 426 return E TIMEOUT;418 return ESYNCH_TIMEOUT; 427 419 } 428 420 … … 441 433 THREAD->sleep_queue = wq; 442 434 443 /* Must be before entry to scheduler, because there are multiple444 * return vectors.445 */446 *blocked = true;447 448 435 irq_spinlock_unlock(&THREAD->lock, false); 449 436 … … 451 438 scheduler(); 452 439 453 return E OK;440 return ESYNCH_OK_BLOCKED; 454 441 } 455 442
Note:
See TracChangeset
for help on using the changeset viewer.