Skip to content

Commit da9647e

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched/completions: Fix complete_all() semantics
Documentation/scheduler/completion.txt says this about complete_all(): "calls complete_all() to signal all current and future waiters." Which doesn't strictly match the current semantics. Currently complete_all() is equivalent to UINT_MAX/2 complete() invocations, which is distinctly less than 'all current and future waiters' (enumerable vs innumerable), although it has worked in practice. However, Dmitry had a weird case where it might matter, so change completions to use saturation semantics for complete()/complete_all(). Once done hits UINT_MAX (and complete_all() sets it there) it will never again be decremented. Requested-by: Dmitry Torokhov <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 59f8c29 commit da9647e

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

kernel/sched/completion.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ void complete(struct completion *x)
3131
unsigned long flags;
3232

3333
spin_lock_irqsave(&x->wait.lock, flags);
34-
x->done++;
34+
if (x->done != UINT_MAX)
35+
x->done++;
3536
__wake_up_locked(&x->wait, TASK_NORMAL, 1);
3637
spin_unlock_irqrestore(&x->wait.lock, flags);
3738
}
@@ -51,7 +52,7 @@ void complete_all(struct completion *x)
5152
unsigned long flags;
5253

5354
spin_lock_irqsave(&x->wait.lock, flags);
54-
x->done += UINT_MAX/2;
55+
x->done = UINT_MAX;
5556
__wake_up_locked(&x->wait, TASK_NORMAL, 0);
5657
spin_unlock_irqrestore(&x->wait.lock, flags);
5758
}
@@ -79,7 +80,8 @@ do_wait_for_common(struct completion *x,
7980
if (!x->done)
8081
return timeout;
8182
}
82-
x->done--;
83+
if (x->done != UINT_MAX)
84+
x->done--;
8385
return timeout ?: 1;
8486
}
8587

@@ -280,7 +282,7 @@ bool try_wait_for_completion(struct completion *x)
280282
spin_lock_irqsave(&x->wait.lock, flags);
281283
if (!x->done)
282284
ret = 0;
283-
else
285+
else if (x->done != UINT_MAX)
284286
x->done--;
285287
spin_unlock_irqrestore(&x->wait.lock, flags);
286288
return ret;

0 commit comments

Comments
 (0)