mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
sched/wait: Avoid abort_exclusive_wait() in ___wait_event()
___wait_event() doesn't really need abort_exclusive_wait(), we can simply change prepare_to_wait_event() to remove the waiter from q->task_list if it was interrupted. This simplifies the code/logic, and this way prepare_to_wait_event() can have more users, see the next change. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Bart Van Assche <bvanassche@acm.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Neil Brown <neilb@suse.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20160908164815.GA18801@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org> -- include/linux/wait.h | 7 +------ kernel/sched/wait.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 16 deletions(-)
This commit is contained in:
parent
38a3e1fc1d
commit
b1ea06a90f
2 changed files with 26 additions and 16 deletions
|
@ -280,12 +280,7 @@ wait_queue_head_t *bit_waitqueue(void *, int);
|
||||||
\
|
\
|
||||||
if (___wait_is_interruptible(state) && __int) { \
|
if (___wait_is_interruptible(state) && __int) { \
|
||||||
__ret = __int; \
|
__ret = __int; \
|
||||||
if (exclusive) { \
|
goto __out; \
|
||||||
abort_exclusive_wait(&wq, &__wait, \
|
|
||||||
NULL); \
|
|
||||||
goto __out; \
|
|
||||||
} \
|
|
||||||
break; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
cmd; \
|
cmd; \
|
||||||
|
|
|
@ -199,24 +199,39 @@ EXPORT_SYMBOL(prepare_to_wait_exclusive);
|
||||||
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
|
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
long ret = 0;
|
||||||
if (signal_pending_state(state, current))
|
|
||||||
return -ERESTARTSYS;
|
|
||||||
|
|
||||||
wait->private = current;
|
wait->private = current;
|
||||||
wait->func = autoremove_wake_function;
|
wait->func = autoremove_wake_function;
|
||||||
|
|
||||||
spin_lock_irqsave(&q->lock, flags);
|
spin_lock_irqsave(&q->lock, flags);
|
||||||
if (list_empty(&wait->task_list)) {
|
if (unlikely(signal_pending_state(state, current))) {
|
||||||
if (wait->flags & WQ_FLAG_EXCLUSIVE)
|
/*
|
||||||
__add_wait_queue_tail(q, wait);
|
* Exclusive waiter must not fail if it was selected by wakeup,
|
||||||
else
|
* it should "consume" the condition we were waiting for.
|
||||||
__add_wait_queue(q, wait);
|
*
|
||||||
|
* The caller will recheck the condition and return success if
|
||||||
|
* we were already woken up, we can not miss the event because
|
||||||
|
* wakeup locks/unlocks the same q->lock.
|
||||||
|
*
|
||||||
|
* But we need to ensure that set-condition + wakeup after that
|
||||||
|
* can't see us, it should wake up another exclusive waiter if
|
||||||
|
* we fail.
|
||||||
|
*/
|
||||||
|
list_del_init(&wait->task_list);
|
||||||
|
ret = -ERESTARTSYS;
|
||||||
|
} else {
|
||||||
|
if (list_empty(&wait->task_list)) {
|
||||||
|
if (wait->flags & WQ_FLAG_EXCLUSIVE)
|
||||||
|
__add_wait_queue_tail(q, wait);
|
||||||
|
else
|
||||||
|
__add_wait_queue(q, wait);
|
||||||
|
}
|
||||||
|
set_current_state(state);
|
||||||
}
|
}
|
||||||
set_current_state(state);
|
|
||||||
spin_unlock_irqrestore(&q->lock, flags);
|
spin_unlock_irqrestore(&q->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(prepare_to_wait_event);
|
EXPORT_SYMBOL(prepare_to_wait_event);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue