aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@tv-sign.ru>2008-08-20 19:54:44 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-22 09:17:29 -0400
commitf31e11d87a5d7601636710195891ba462ad99f11 (patch)
tree84cabe2eccab1bec8a5302f9a6105ebda1fec492
parent94d3d8247de22c5b0624aa00616ceca459498e55 (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.c7
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 /*