Commit 2feb53c6 authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds

[PATCH] completion API additions

Adds 3 new completion API calls, which are a straightforward extension of
the current APIs:

 int wait_for_completion_interruptible(struct completion *x);
 unsigned long wait_for_completion_timeout(struct completion *x,
                                                   unsigned long timeout);
 unsigned long wait_for_completion_interruptible_timeout(
                        struct completion *x, unsigned long timeout);

This enables the conversion of more semaphore-using code to completions.
There is code that cannot be converted right now (and is forced to use
semaphores) because these primitives are missing.  Thomas Gleixner has a
bunch of patches to make use of them.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Tested-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 11a61345
......@@ -28,6 +28,12 @@ static inline void init_completion(struct completion *x)
}
extern void FASTCALL(wait_for_completion(struct completion *));
extern int FASTCALL(wait_for_completion_interruptible(struct completion *x));
extern unsigned long FASTCALL(wait_for_completion_timeout(struct completion *x,
unsigned long timeout));
extern unsigned long FASTCALL(wait_for_completion_interruptible_timeout(
struct completion *x, unsigned long timeout));
extern void FASTCALL(complete(struct completion *));
extern void FASTCALL(complete_all(struct completion *));
......
......@@ -3005,6 +3005,101 @@ void fastcall __sched wait_for_completion(struct completion *x)
}
EXPORT_SYMBOL(wait_for_completion);
unsigned long fastcall __sched
wait_for_completion_timeout(struct completion *x, unsigned long timeout)
{
might_sleep();
spin_lock_irq(&x->wait.lock);
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
__set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&x->wait.lock);
timeout = schedule_timeout(timeout);
if (!timeout)
goto out;
spin_lock_irq(&x->wait.lock);
} while (!x->done);
__remove_wait_queue(&x->wait, &wait);
}
x->done--;
spin_unlock_irq(&x->wait.lock);
out:
return timeout;
}
EXPORT_SYMBOL(wait_for_completion_timeout);
int fastcall __sched wait_for_completion_interruptible(struct completion *x)
{
int ret = 0;
might_sleep();
spin_lock_irq(&x->wait.lock);
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
if (signal_pending(current)) {
ret = -ERESTARTSYS;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irq(&x->wait.lock);
schedule();
spin_lock_irq(&x->wait.lock);
} while (!x->done);
__remove_wait_queue(&x->wait, &wait);
}
x->done--;
out:
spin_unlock_irq(&x->wait.lock);
return ret;
}
EXPORT_SYMBOL(wait_for_completion_interruptible);
unsigned long fastcall __sched
wait_for_completion_interruptible_timeout(struct completion *x,
unsigned long timeout)
{
might_sleep();
spin_lock_irq(&x->wait.lock);
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
if (signal_pending(current)) {
timeout = -ERESTARTSYS;
goto out_unlock;
}
__set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irq(&x->wait.lock);
timeout = schedule_timeout(timeout);
if (!timeout)
goto out;
spin_lock_irq(&x->wait.lock);
} while (!x->done);
__remove_wait_queue(&x->wait, &wait);
}
x->done--;
out_unlock:
spin_unlock_irq(&x->wait.lock);
out:
return timeout;
}
EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
#define SLEEP_ON_VAR \
unsigned long flags; \
wait_queue_t wait; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment