Skip to content

Commit eaf9ef5

Browse files
oleg-nesterovIngo Molnar
authored andcommitted
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 <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Al Viro <[email protected]> Cc: Bart Van Assche <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Neil Brown <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent b1ea06a commit eaf9ef5

File tree

2 files changed

+21
-44
lines changed

2 files changed

+21
-44
lines changed

include/linux/wait.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,6 @@ void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
984984
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
985985
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
986986
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);
988987
long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
989988
int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
990989
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);

kernel/sched/wait.c

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -270,37 +270,6 @@ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
270270
}
271271
EXPORT_SYMBOL(finish_wait);
272272

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-
304273
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
305274
{
306275
int ret = default_wake_function(wait, mode, sync, key);
@@ -438,20 +407,29 @@ int __sched
438407
__wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
439408
wait_bit_action_f *action, unsigned mode)
440409
{
441-
do {
442-
int ret;
410+
int ret = 0;
443411

412+
for (;;) {
444413
prepare_to_wait_exclusive(wq, &q->wait, mode);
445-
if (!test_bit(q->key.bit_nr, q->key.flags))
446-
continue;
447-
ret = action(&q->key, mode);
448-
if (!ret)
449-
continue;
450-
abort_exclusive_wait(wq, &q->wait, &q->key);
451-
return ret;
452-
} while (test_and_set_bit(q->key.bit_nr, q->key.flags));
453-
finish_wait(wq, &q->wait);
454-
return 0;
414+
if (test_bit(q->key.bit_nr, q->key.flags)) {
415+
ret = action(&q->key, mode);
416+
/*
417+
* See the comment in prepare_to_wait_event().
418+
* finish_wait() does not necessarily takes wq->lock,
419+
* but test_and_set_bit() implies mb() which pairs with
420+
* smp_mb__after_atomic() before wake_up_page().
421+
*/
422+
if (ret)
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+
}
455433
}
456434
EXPORT_SYMBOL(__wait_on_bit_lock);
457435

0 commit comments

Comments
 (0)