--- kernel/sched.c | 63 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 19 deletions(-) Index: linux-2.6.20-rsdl/kernel/sched.c =================================================================== --- linux-2.6.20-rsdl.orig/kernel/sched.c 2007-03-10 18:38:08.000000000 +1100 +++ linux-2.6.20-rsdl/kernel/sched.c 2007-03-10 18:38:59.000000000 +1100 @@ -17,7 +17,7 @@ * 2003-09-03 Interactivity tuning by Con Kolivas. * 2004-04-02 Scheduler domains code by Nick Piggin * 2007-03-02 Rotating Staircase deadline scheduling policy by Con Kolivas - * RSDL v0.26 + * RSDL v0.28 */ #include @@ -93,7 +93,7 @@ * Set to a minimum of 6ms. */ #define RR_INTERVAL ((6 * HZ / 1001) + 1) -#define DEF_TIMESLICE (RR_INTERVAL * 19) +#define DEF_TIMESLICE (RR_INTERVAL * 20) struct prio_array { struct list_head queue[MAX_PRIO]; @@ -668,6 +668,15 @@ static inline void task_new_array(struct p->rotation = rq->prio_rotation; } +static inline void queue_expired(struct task_struct *p, struct rq *rq) +{ + p->prio = p->normal_prio = p->static_prio; + p->array = rq->expired; + bitmap_zero(p->bitmap, PRIO_RANGE); + p->rotation = rq->prio_rotation; + p->time_slice = p->quota; +} + #define rq_quota(rq, prio) ((rq)->prio_quota[USER_PRIO(prio)]) /* * recalc_task_prio determines what prio a non rt_task will be @@ -685,9 +694,15 @@ static void recalc_task_prio(struct task struct prio_array *array = rq->active; int queue_prio, search_prio; - if (p->rotation == rq->prio_rotation && p->array == array) { - if (p->time_slice && rq_quota(rq, p->prio)) + if (p->rotation == rq->prio_rotation) { + if (p->array == array) { + if (p->time_slice && rq_quota(rq, p->prio)) + return; + } else if (p->array == rq->expired) { + queue_expired(p, rq); return; + } else + task_new_array(p, rq); } else task_new_array(p, rq); search_prio = p->static_prio; @@ -703,11 +718,10 @@ static void recalc_task_prio(struct task queue_prio = SCHED_PRIO(find_next_zero_bit(p->bitmap, PRIO_RANGE, USER_PRIO(search_prio))); if (queue_prio == MAX_PRIO) { - queue_prio = p->static_prio; - array = rq->expired; - bitmap_zero(p->bitmap, PRIO_RANGE); - } else - rq_quota(rq, queue_prio) += p->quota; + queue_expired(p, rq); + return; + } + rq_quota(rq, queue_prio) += p->quota; p->prio = p->normal_prio = queue_prio; p->array = array; set_task_entitlement(p); @@ -1316,12 +1330,23 @@ static inline int wake_idle(int cpu, str } #endif +/* + * We need to have a special definition for an idle runqueue when testing + * for preemption on CONFIG_HOTPLUG_CPU as the idle task may be scheduled as + * a realtime task in sched_idle_next. + */ +#ifdef CONFIG_HOTPLUG_CPU +#define rq_idle(rq) ((rq)->curr == (rq)->idle && !rt_task((rq)->curr)) +#else +#define rq_idle(rq) ((rq)->curr == (rq)->idle) +#endif + static inline int task_preempts_curr(struct task_struct *p, struct rq *rq) { struct task_struct *curr = rq->curr; return ((p->array == task_rq(p)->active && - TASK_PREEMPTS_CURR(p, curr)) || curr == rq->idle); + TASK_PREEMPTS_CURR(p, curr)) || rq_idle(rq)); } static inline void try_preempt(struct task_struct *p, struct rq *rq) @@ -1499,7 +1524,7 @@ int fastcall wake_up_state(struct task_s return try_to_wake_up(p, state, 0); } -static void task_expired_entitlement(struct rq *rq, struct task_struct *p); +static void task_running_tick(struct rq *rq, struct task_struct *p); /* * Perform scheduler related setup for a newly forked process p. * p is forked by current. @@ -1560,10 +1585,8 @@ void fastcall sched_fork(struct task_str * left from its timeslice. Taking the runqueue lock is not * a problem. */ - struct rq *rq = __task_rq_lock(current); - - task_expired_entitlement(rq, current); - __task_rq_unlock(rq); + current->time_slice = 1; + task_running_tick(cpu_rq(cpu), current); } local_irq_enable(); out: @@ -3356,8 +3379,9 @@ static noinline int rq_bitmap_error(stru struct list_head *queue; int idx, test_idx; - if (!bitmap_error++) - printk(KERN_ERR "Scheduler bitmap error - bitmap being reconstructed..\n"); + printk(KERN_ERR + "SCHEDULER BITMAP ERROR %d - attempting to reconstruct...\n", + ++bitmap_error); for (test_idx = MAX_RT_PRIO ; test_idx < MAX_DYN_PRIO ; test_idx++) { if (test_idx < MAX_PRIO) { idx = test_idx; @@ -3374,6 +3398,7 @@ static noinline int rq_bitmap_error(stru } } idx = find_next_bit(rq->dyn_bitmap, MAX_DYN_PRIO, MAX_RT_PRIO); + /* We hit a real bug. There is no way out of this */ BUG_ON(idx == MAX_DYN_PRIO); return idx; } @@ -4902,7 +4927,7 @@ void __cpuinit init_idle(struct task_str bitmap_zero(idle->bitmap, PRIO_RANGE + 1); idle->timestamp = sched_clock(); idle->array = NULL; - idle->prio = idle->normal_prio = MAX_PRIO; + idle->prio = idle->normal_prio = NICE_TO_PRIO(0); idle->state = TASK_RUNNING; idle->cpus_allowed = cpumask_of_cpu(cpu); set_task_cpu(idle, cpu); @@ -5321,7 +5346,7 @@ migration_call(struct notifier_block *nf /* Idle task back to normal (off runqueue, low prio) */ rq = task_rq_lock(rq->idle, &flags); deactivate_task(rq->idle, rq); - rq->idle->static_prio = MAX_PRIO; + rq->idle->static_prio = NICE_TO_PRIO(0); __setscheduler(rq->idle, SCHED_NORMAL, 0); migrate_dead_tasks(cpu); task_rq_unlock(rq, &flags);