commit b1c3a5c25d9b9301ab197a65247c3f495135fd60 Author: Grzegorz Nosek Date: Sat May 17 10:56:19 2008 +0200 Don't loop forever in scheduler diff --git a/kernel/sched.c b/kernel/sched.c index a111b42..218ccdf 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3627,6 +3627,7 @@ asmlinkage void __sched schedule(void) int cpu, idx, new_prio; long *switch_count; struct rq *rq; + int can_progress; /* * Test if we are atomic. Since do_exit() needs to call into @@ -3695,12 +3696,17 @@ need_resched_nonpreemptible: cpu = smp_processor_id(); vx_set_rq_time(rq, jiffies); try_unhold: - vx_try_unhold(rq, cpu); + can_progress = vx_try_unhold(rq, cpu); pick_next: if (unlikely(!rq->nr_running)) { - /* can we skip idle time? */ - if (vx_try_skip(rq, cpu)) + /* + * can we skip idle time? + * + * if there are no held tasks, trying to unhold one + * will never succeed + */ + if (can_progress && vx_try_skip(rq, cpu)) goto try_unhold; idle_balance(cpu, rq); diff --git a/kernel/sched_hard.h b/kernel/sched_hard.h index 0e95990..0710af5 100644 --- a/kernel/sched_hard.h +++ b/kernel/sched_hard.h @@ -171,16 +171,17 @@ int vx_need_resched(struct task_struct *p, int slice, int cpu) static inline -void vx_try_unhold(struct rq *rq, int cpu) +int vx_try_unhold(struct rq *rq, int cpu) { struct vx_info *vxi = NULL; struct list_head *l, *n; int maxidle = HZ; int minskip = 0; + int can_progress = 0; /* nothing to do? what about pause? */ if (list_empty(&rq->hold_queue)) - return; + return 0; list_for_each_safe(l, n, &rq->hold_queue) { int ret, delta_min[2]; @@ -205,6 +206,9 @@ void vx_try_unhold(struct rq *rq, int cpu) &rq->norm_time, &rq->idle_time, delta_min); vxm_tokens_recalc(sched_pc, rq, vxi, cpu); + /* a task will eventually be runnable, maybe even now */ + can_progress = 1; + if (ret > 0) { /* we found a runable context */ vx_unhold_task(p, rq); @@ -216,6 +220,8 @@ void vx_try_unhold(struct rq *rq, int cpu) vx_set_rq_max_idle(rq, maxidle); vx_set_rq_min_skip(rq, minskip); vxm_rq_max_min(rq, cpu); + + return can_progress; }