diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-08-20 19:54:44 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-22 09:17:29 -0400 |
commit | f31e11d87a5d7601636710195891ba462ad99f11 (patch) | |
tree | 84cabe2eccab1bec8a5302f9a6105ebda1fec492 | |
parent | 94d3d8247de22c5b0624aa00616ceca459498e55 (diff) |
wait_task_inactive(): don't consider task->nivcsw
If wait_task_inactive() returns success the task was deactivated. In that
case schedule() always increments ->nvcsw which alone can be used as a
"generation counter".
If the next call returns the same number, we can be sure that the task was
unscheduled. Otherwise, because we know that .on_rq == 0 again, ->nvcsw
should have been changed in between.
Q: perhaps it is better to do "ncsw = (p->nvcsw << 1) | 1" ? This
decreases the possibility of "was it unscheduled" false positive when
->nvcsw == 0.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | kernel/sched.c | 7 |
1 files changed, 2 insertions, 5 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index da7c5d23cc03..908670aa215a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1921,11 +1921,8 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) | |||
1921 | running = task_running(rq, p); | 1921 | running = task_running(rq, p); |
1922 | on_rq = p->se.on_rq; | 1922 | on_rq = p->se.on_rq; |
1923 | ncsw = 0; | 1923 | ncsw = 0; |
1924 | if (!match_state || p->state == match_state) { | 1924 | if (!match_state || p->state == match_state) |
1925 | ncsw = p->nivcsw + p->nvcsw; | 1925 | ncsw = p->nvcsw ?: 1; |
1926 | if (unlikely(!ncsw)) | ||
1927 | ncsw = 1; | ||
1928 | } | ||
1929 | task_rq_unlock(rq, &flags); | 1926 | task_rq_unlock(rq, &flags); |
1930 | 1927 | ||
1931 | /* | 1928 | /* |