diff options
author | Oleg Nesterov <oleg@redhat.com> | 2016-09-06 10:00:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-09-30 04:54:03 -0400 |
commit | eaf9ef52241b545fe63621266bfc6fd8b06559ff (patch) | |
tree | 7cc771e86505f117bcdfabccf13048fc9dc78451 | |
parent | b1ea06a90f528e516929a4da1d9b8838752bceb9 (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.h | 1 | ||||
-rw-r--r-- | kernel/sched/wait.c | 64 |
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); | |||
984 | void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state); | 984 | void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state); |
985 | long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state); | 985 | long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state); |
986 | void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); | 986 | void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); |
987 | void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, void *key); | ||
988 | long wait_woken(wait_queue_t *wait, unsigned mode, long timeout); | 987 | long wait_woken(wait_queue_t *wait, unsigned mode, long timeout); |
989 | int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | 988 | int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); |
990 | int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | 989 | int 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 | } |
271 | EXPORT_SYMBOL(finish_wait); | 271 | EXPORT_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 | */ | ||
290 | void 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 | } | ||
302 | EXPORT_SYMBOL(abort_exclusive_wait); | ||
303 | |||
304 | int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) | 273 | int 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 | } |
456 | EXPORT_SYMBOL(__wait_on_bit_lock); | 434 | EXPORT_SYMBOL(__wait_on_bit_lock); |
457 | 435 | ||