aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2016-09-06 10:00:53 -0400
committerIngo Molnar <mingo@kernel.org>2016-09-30 04:54:03 -0400
commiteaf9ef52241b545fe63621266bfc6fd8b06559ff (patch)
tree7cc771e86505f117bcdfabccf13048fc9dc78451
parentb1ea06a90f528e516929a4da1d9b8838752bceb9 (diff)
sched/wait: Avoid abort_exclusive_wait() in __wait_on_bit_lock()
__wait_on_bit_lock() doesn't need abort_exclusive_wait() too. Right now it can't use prepare_to_wait_event() (see the next change), but it can do the additional finish_wait() if action() fails. abort_exclusive_wait() no longer has callers, remove it. 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/20160906140053.GA6164@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--include/linux/wait.h1
-rw-r--r--kernel/sched/wait.c64
2 files changed, 21 insertions, 44 deletions
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 7261dcbe5afe..19c75f9545ce 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -984,7 +984,6 @@ void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
984void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state); 984void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
985long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state); 985long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
986void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); 986void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
987void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, void *key);
988long wait_woken(wait_queue_t *wait, unsigned mode, long timeout); 987long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
989int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); 988int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
990int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); 989int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c
index 261239392258..0cb615d69013 100644
--- a/kernel/sched/wait.c
+++ b/kernel/sched/wait.c
@@ -270,37 +270,6 @@ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
270} 270}
271EXPORT_SYMBOL(finish_wait); 271EXPORT_SYMBOL(finish_wait);
272 272
273/**
274 * abort_exclusive_wait - abort exclusive waiting in a queue
275 * @q: waitqueue waited on
276 * @wait: wait descriptor
277 * @key: key to identify a wait bit queue or %NULL
278 *
279 * Sets current thread back to running state and removes
280 * the wait descriptor from the given waitqueue if still
281 * queued.
282 *
283 * Wakes up the next waiter if the caller is concurrently
284 * woken up through the queue.
285 *
286 * This prevents waiter starvation where an exclusive waiter
287 * aborts and is woken up concurrently and no one wakes up
288 * the next waiter.
289 */
290void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, void *key)
291{
292 unsigned long flags;
293
294 __set_current_state(TASK_RUNNING);
295 spin_lock_irqsave(&q->lock, flags);
296 if (!list_empty(&wait->task_list))
297 list_del_init(&wait->task_list);
298 else if (waitqueue_active(q))
299 __wake_up_locked_key(q, TASK_NORMAL, key);
300 spin_unlock_irqrestore(&q->lock, flags);
301}
302EXPORT_SYMBOL(abort_exclusive_wait);
303
304int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) 273int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
305{ 274{
306 int ret = default_wake_function(wait, mode, sync, key); 275 int ret = default_wake_function(wait, mode, sync, key);
@@ -438,20 +407,29 @@ int __sched
438__wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, 407__wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
439 wait_bit_action_f *action, unsigned mode) 408 wait_bit_action_f *action, unsigned mode)
440{ 409{
441 do { 410 int ret = 0;
442 int ret;
443 411
412 for (;;) {
444 prepare_to_wait_exclusive(wq, &q->wait, mode); 413 prepare_to_wait_exclusive(wq, &q->wait, mode);
445 if (!test_bit(q->key.bit_nr, q->key.flags)) 414 if (test_bit(q->key.bit_nr, q->key.flags)) {
446 continue; 415 ret = action(&q->key, mode);
447 ret = action(&q->key, mode); 416 /*
448 if (!ret) 417 * See the comment in prepare_to_wait_event().
449 continue; 418 * finish_wait() does not necessarily takes wq->lock,
450 abort_exclusive_wait(wq, &q->wait, &q->key); 419 * but test_and_set_bit() implies mb() which pairs with
451 return ret; 420 * smp_mb__after_atomic() before wake_up_page().
452 } while (test_and_set_bit(q->key.bit_nr, q->key.flags)); 421 */
453 finish_wait(wq, &q->wait); 422 if (ret)
454 return 0; 423 finish_wait(wq, &q->wait);
424 }
425 if (!test_and_set_bit(q->key.bit_nr, q->key.flags)) {
426 if (!ret)
427 finish_wait(wq, &q->wait);
428 return 0;
429 } else if (ret) {
430 return ret;
431 }
432 }
455} 433}
456EXPORT_SYMBOL(__wait_on_bit_lock); 434EXPORT_SYMBOL(__wait_on_bit_lock);
457 435