Skip to content

Commit 38a3e1f

Browse files
oleg-nesterovIngo Molnar
authored andcommitted
sched/wait: Fix abort_exclusive_wait(), it should pass TASK_NORMAL to wake_up()
Otherwise this logic only works if mode is "compatible" with another exclusive waiter. If some wq has both TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE waiters, abort_exclusive_wait() won't wait an uninterruptible waiter. The main user is __wait_on_bit_lock() and currently it is fine but only because TASK_KILLABLE includes TASK_UNINTERRUPTIBLE and we do not have lock_page_interruptible() yet. Just use TASK_NORMAL and remove the "mode" arg from abort_exclusive_wait(). Yes, this means that (say) wake_up_interruptible() can wake up the non- interruptible waiter(s), but I think this is fine. And in fact I think that abort_exclusive_wait() must die, see the next change. 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 ab522e3 commit 38a3e1f

File tree

2 files changed

+6
-8
lines changed

2 files changed

+6
-8
lines changed

include/linux/wait.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,8 @@ wait_queue_head_t *bit_waitqueue(void *, int);
281281
if (___wait_is_interruptible(state) && __int) { \
282282
__ret = __int; \
283283
if (exclusive) { \
284-
abort_exclusive_wait(&wq, &__wait, \
285-
state, NULL); \
284+
abort_exclusive_wait(&wq, &__wait, \
285+
NULL); \
286286
goto __out; \
287287
} \
288288
break; \
@@ -989,7 +989,7 @@ void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
989989
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
990990
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
991991
void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
992-
void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, unsigned int mode, void *key);
992+
void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, void *key);
993993
long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
994994
int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
995995
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);

kernel/sched/wait.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ EXPORT_SYMBOL(finish_wait);
259259
* abort_exclusive_wait - abort exclusive waiting in a queue
260260
* @q: waitqueue waited on
261261
* @wait: wait descriptor
262-
* @mode: runstate of the waiter to be woken
263262
* @key: key to identify a wait bit queue or %NULL
264263
*
265264
* Sets current thread back to running state and removes
@@ -273,8 +272,7 @@ EXPORT_SYMBOL(finish_wait);
273272
* aborts and is woken up concurrently and no one wakes up
274273
* the next waiter.
275274
*/
276-
void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
277-
unsigned int mode, void *key)
275+
void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, void *key)
278276
{
279277
unsigned long flags;
280278

@@ -283,7 +281,7 @@ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
283281
if (!list_empty(&wait->task_list))
284282
list_del_init(&wait->task_list);
285283
else if (waitqueue_active(q))
286-
__wake_up_locked_key(q, mode, key);
284+
__wake_up_locked_key(q, TASK_NORMAL, key);
287285
spin_unlock_irqrestore(&q->lock, flags);
288286
}
289287
EXPORT_SYMBOL(abort_exclusive_wait);
@@ -434,7 +432,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
434432
ret = action(&q->key, mode);
435433
if (!ret)
436434
continue;
437-
abort_exclusive_wait(wq, &q->wait, mode, &q->key);
435+
abort_exclusive_wait(wq, &q->wait, &q->key);
438436
return ret;
439437
} while (test_and_set_bit(q->key.bit_nr, q->key.flags));
440438
finish_wait(wq, &q->wait);

0 commit comments

Comments
 (0)