aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/wait.h
diff options
context:
space:
mode:
authorMichal Nazarewicz <m.nazarewicz@samsung.com>2010-05-05 06:53:11 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:42 -0400
commit22c43c81a51e05f61e90445ceb59d486c12fd921 (patch)
tree88582f01bf413bdc4d9d95a512116c9fe44afa33 /include/linux/wait.h
parent24337c133ff92ba8d7c42819db17f7f2b0de3129 (diff)
wait_event_interruptible_locked() interface
New wait_event_interruptible{,_exclusive}_locked{,_irq} macros added. They work just like versions without _locked* suffix but require the wait queue's lock to be held. Also __wake_up_locked() is now exported as to pair it with the above macros. The use case of this new facility is when one uses wait queue's lock to protect a data structure. This may be advantageous if the structure needs to be protected by a spinlock anyway. In particular, with additional spinlock the following code has to be used to wait for a condition: spin_lock(&data.lock); ... for (ret = 0; !ret && !(condition); ) { spin_unlock(&data.lock); ret = wait_event_interruptible(data.wqh, (condition)); spin_lock(&data.lock); } ... spin_unlock(&data.lock); This looks bizarre plus wait_event_interruptible() locks the wait queue's lock anyway so there is a unlock+lock sequence where it could be avoided. To avoid those problems and benefit from wait queue's lock, a code similar to the following should be used: /* Waiting */ spin_lock(&data.wqh.lock); ... ret = wait_event_interruptible_locked(data.wqh, (condition)); ... spin_unlock(&data.wqh.lock); /* Waiting exclusively */ spin_lock(&data.whq.lock); ... ret = wait_event_interruptible_exclusive_locked(data.whq, (condition)); ... spin_unlock(&data.whq.lock); /* Waking up */ spin_lock(&data.wqh.lock); ... wake_up_locked(&data.wqh); ... spin_unlock(&data.wqh.lock); When spin_lock_irq() is used matching versions of macros need to be used (*_locked_irq()). Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com> Cc: Kyungmin Park <kyungmin.park@samsung.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Takashi Iwai <tiwai@suse.de> Cc: David Howells <dhowells@redhat.com> Cc: Andreas Herrmann <andreas.herrmann3@amd.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Mike Galbraith <efault@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include/linux/wait.h')
-rw-r--r--include/linux/wait.h149
1 files changed, 149 insertions, 0 deletions
diff --git a/include/linux/wait.h b/include/linux/wait.h
index a48e16b77d5e..fc3c040e5e3a 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -362,6 +362,155 @@ do { \
362 __ret; \ 362 __ret; \
363}) 363})
364 364
365
366#define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \
367({ \
368 int __ret = 0; \
369 DEFINE_WAIT(__wait); \
370 if (exclusive) \
371 __wait.flags |= WQ_FLAG_EXCLUSIVE; \
372 do { \
373 if (likely(list_empty(&__wait.task_list))) \
374 __add_wait_queue_tail(&(wq), &__wait); \
375 set_current_state(TASK_INTERRUPTIBLE); \
376 if (signal_pending(current)) { \
377 __ret = -ERESTARTSYS; \
378 break; \
379 } \
380 if (irq) \
381 spin_unlock_irq(&(wq).lock); \
382 else \
383 spin_unlock(&(wq).lock); \
384 schedule(); \
385 if (irq) \
386 spin_lock_irq(&(wq).lock); \
387 else \
388 spin_lock(&(wq).lock); \
389 } while (!(condition)); \
390 __remove_wait_queue(&(wq), &__wait); \
391 __set_current_state(TASK_RUNNING); \
392 __ret; \
393})
394
395
396/**
397 * wait_event_interruptible_locked - sleep until a condition gets true
398 * @wq: the waitqueue to wait on
399 * @condition: a C expression for the event to wait for
400 *
401 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
402 * @condition evaluates to true or a signal is received.
403 * The @condition is checked each time the waitqueue @wq is woken up.
404 *
405 * It must be called with wq.lock being held. This spinlock is
406 * unlocked while sleeping but @condition testing is done while lock
407 * is held and when this macro exits the lock is held.
408 *
409 * The lock is locked/unlocked using spin_lock()/spin_unlock()
410 * functions which must match the way they are locked/unlocked outside
411 * of this macro.
412 *
413 * wake_up_locked() has to be called after changing any variable that could
414 * change the result of the wait condition.
415 *
416 * The function will return -ERESTARTSYS if it was interrupted by a
417 * signal and 0 if @condition evaluated to true.
418 */
419#define wait_event_interruptible_locked(wq, condition) \
420 ((condition) \
421 ? 0 : __wait_event_interruptible_locked(wq, condition, 0, 0))
422
423/**
424 * wait_event_interruptible_locked_irq - sleep until a condition gets true
425 * @wq: the waitqueue to wait on
426 * @condition: a C expression for the event to wait for
427 *
428 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
429 * @condition evaluates to true or a signal is received.
430 * The @condition is checked each time the waitqueue @wq is woken up.
431 *
432 * It must be called with wq.lock being held. This spinlock is
433 * unlocked while sleeping but @condition testing is done while lock
434 * is held and when this macro exits the lock is held.
435 *
436 * The lock is locked/unlocked using spin_lock_irq()/spin_unlock_irq()
437 * functions which must match the way they are locked/unlocked outside
438 * of this macro.
439 *
440 * wake_up_locked() has to be called after changing any variable that could
441 * change the result of the wait condition.
442 *
443 * The function will return -ERESTARTSYS if it was interrupted by a
444 * signal and 0 if @condition evaluated to true.
445 */
446#define wait_event_interruptible_locked_irq(wq, condition) \
447 ((condition) \
448 ? 0 : __wait_event_interruptible_locked(wq, condition, 0, 1))
449
450/**
451 * wait_event_interruptible_exclusive_locked - sleep exclusively until a condition gets true
452 * @wq: the waitqueue to wait on
453 * @condition: a C expression for the event to wait for
454 *
455 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
456 * @condition evaluates to true or a signal is received.
457 * The @condition is checked each time the waitqueue @wq is woken up.
458 *
459 * It must be called with wq.lock being held. This spinlock is
460 * unlocked while sleeping but @condition testing is done while lock
461 * is held and when this macro exits the lock is held.
462 *
463 * The lock is locked/unlocked using spin_lock()/spin_unlock()
464 * functions which must match the way they are locked/unlocked outside
465 * of this macro.
466 *
467 * The process is put on the wait queue with an WQ_FLAG_EXCLUSIVE flag
468 * set thus when other process waits process on the list if this
469 * process is awaken further processes are not considered.
470 *
471 * wake_up_locked() has to be called after changing any variable that could
472 * change the result of the wait condition.
473 *
474 * The function will return -ERESTARTSYS if it was interrupted by a
475 * signal and 0 if @condition evaluated to true.
476 */
477#define wait_event_interruptible_exclusive_locked(wq, condition) \
478 ((condition) \
479 ? 0 : __wait_event_interruptible_locked(wq, condition, 1, 0))
480
481/**
482 * wait_event_interruptible_exclusive_locked_irq - sleep until a condition gets true
483 * @wq: the waitqueue to wait on
484 * @condition: a C expression for the event to wait for
485 *
486 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
487 * @condition evaluates to true or a signal is received.
488 * The @condition is checked each time the waitqueue @wq is woken up.
489 *
490 * It must be called with wq.lock being held. This spinlock is
491 * unlocked while sleeping but @condition testing is done while lock
492 * is held and when this macro exits the lock is held.
493 *
494 * The lock is locked/unlocked using spin_lock_irq()/spin_unlock_irq()
495 * functions which must match the way they are locked/unlocked outside
496 * of this macro.
497 *
498 * The process is put on the wait queue with an WQ_FLAG_EXCLUSIVE flag
499 * set thus when other process waits process on the list if this
500 * process is awaken further processes are not considered.
501 *
502 * wake_up_locked() has to be called after changing any variable that could
503 * change the result of the wait condition.
504 *
505 * The function will return -ERESTARTSYS if it was interrupted by a
506 * signal and 0 if @condition evaluated to true.
507 */
508#define wait_event_interruptible_exclusive_locked_irq(wq, condition) \
509 ((condition) \
510 ? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1))
511
512
513
365#define __wait_event_killable(wq, condition, ret) \ 514#define __wait_event_killable(wq, condition, ret) \
366do { \ 515do { \
367 DEFINE_WAIT(__wait); \ 516 DEFINE_WAIT(__wait); \