[2.4] add wait_event_interruptible_timeout
PATCH 1/1 [2.4] add wait_event_interruptible_timeout
The sleep_on* series of calls is unsafe, and prone to race conditions. They've been unofficially deprecated for a while. Instead, we're supposed to use the wait_event* series of calls.
There's only one problem with this. There's no equivalent of sleep_on_timeout/interruptible_sleep_on_timeout.
So, the attached patch adds 'wait_event_timeout' and 'wait_event_interruptible_timeout' The diff is generated against 2.4.20-pre7, but should apply cleanly to just about any 2.4/2.2 release, and maybe even 2.5 as well.
Back to the bit mines..
- Pizza
Signature · 4 lines
Solomon Peachy [email protected] AbsoluteValue Systems http://www.linux-wlan.com 715-D North Drive +1 (321) 259-0737 (office) Melbourne, FL 32934 +1 (321) 259-0286 (fax)
sched.h renamed from sched.h.old +81 -0
@@ -855,6 +855,87 @@ __ret; \ }) +#define __wait_event_timeout (wq, condition, timeout, ret) \ +do { \ + int __ret = 0; \ + if (!(condition)) { \ + wait_queue_t __wait; \ + unsigned long expire; \ + init_waitqueue_entry(&__wait, current); \ + \ + expire = timeout + jiffies; \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_UNINTERRUPTIBLE); \ + if (condition) \ + break; \ + if (jiffies > expire) { \ + ret = jiffies - expire; \ + break; \ + } \ + schedule_timeout(timeout); \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ + } \ +} while (0) +/* +retval == 0; condition met; we're good. +retval > 0; timed out. +*/ +#define wait_event_timeout (wq, condition, timeout) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __wait_event_timeout(wq, condition, \ + timeout, __ret); \ + __ret; \ +}) + +#define __wait_event_interruptible_timeout (wq, condition, timeout, ret) \ +do { \ + int __ret = 0; \ + if (!(condition)) { \ + wait_queue_t __wait; \ + unsigned long expire; \ + init_waitqueue_entry(&__wait, current); \ + \ + expire = timeout + jiffies; \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (jiffies > expire) { \ + ret = jiffies - expire; \ + break; \ + } \ + if (!signal_pending(current)) { \ + schedule_timeout(timeout); \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ + } \ +} while (0) + +/* +retval == 0; condition met; we're good. +retval < 0; interrupted by signal. +retval > 0; timed out. +*/ +#define wait_event_interruptible_timeout (wq, condition, timeout) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, \ + timeout, __ret); \ + __ret; \ +}) +#define REMOVE_LINKS (p) do { \ (p)->next_task->prev_task = (p)->prev_task; \ (p)->prev_task->next_task = (p)->next_task; \