add wait_event() to <linux/completion.h>
PATCH 1/1 add wait_event() to <linux/completion.h>
Folk periodically talk about evolving the "struct completion" support ... here's one:
int wait_event (struct completion *x, signed long timeout_jiffies);
Returns zero if the event happened, nonzero if it timed out. An example timeout action might be to cancel a request then use wait_for_completion(x) to synchronize with that.
It's been behaving for me so far. Questions from me:
- Is this appropriate to merge as-is? The tradeoff I'm thinking of is code duplication; this patch avoids it ("smaller==better" rule-of-thumb) but maybe someone has real tuning knowledge, or a "standard" lk policy applies. Or there might be bugs or api transgressions.
- One routine was unavailable to modules; now exported. That seemed to just be an oversight.
This doesn't add an "interruptible wait" api mode, which I'd expect some others might find a use for. This patch will let us clean up some dubious code in usbcore which is more or less trying to do a wait_event().
Thanks in advance for any comments.
- Dave
include/linux/completion.h renamed from include/linux-dist/completion.h +1 -0
@@ -28,6 +28,7 @@ }extern void FASTCALL (wait_for_completion (struct completion *)); +extern int FASTCALL (wait_timeout (struct completion *,signed long jiffies));extern void FASTCALL (complete (struct completion *));extern void FASTCALL (complete_all (struct completion *));
kernel/ksyms.c renamed from kernel-dist/ksyms.c +2 -0
@@ -404,7 +404,9 @@ EXPORT_SYMBOL(autoremove_wake_function);/* completion handling */ EXPORT_SYMBOL (wait_for_completion); +EXPORT_SYMBOL (wait_timeout);EXPORT_SYMBOL (complete); +EXPORT_SYMBOL (complete_all);/* The notion of irq probe/assignment is foreign to S/390 */
kernel/sched.c renamed from kernel-dist/sched.c +12 -1
@@ -1204,6 +1204,11 @@ void complete_all(struct completion *x)void wait_for_completion (struct completion *x) { +wait_timeout (x,MAX_SCHEDULE_TIMEOUT ); +} + +int wait_timeout (struct completion *x,signed long timeout_jiffies) +{might_sleep ();spin_lock_irq (&x->wait.lock);if (!x->done) {
@@ -1214,13 +1219,19 @@ void wait_for_completion(struct completido {__set_current_state (TASK_UNINTERRUPTIBLE );spin_unlock_irq (&x->wait.lock); -schedule (); + timeout_jiffies =schedule_timeout (timeout_jiffies); +if (timeout_jiffies ==0 ) { +__remove_wait_queue (&x->wait, &wait); +/* caller should wait again */ +return 1 ; + }spin_lock_irq (&x->wait.lock); }while (!x->done);__remove_wait_queue (&x->wait, &wait); } x->done--;spin_unlock_irq (&x->wait.lock); +return 0 ; }#define SLEEP_ON_VAR \