--- linux-2.6.0-test2-mm5-O14/include/linux/sched.h 2003-08-08 22:47:08.000000000 +1000 +++ linux-2.6.0-test2-mm5/include/linux/sched.h 2003-08-10 01:04:41.000000000 +1000 @@ -126,6 +126,7 @@ extern unsigned long nr_iowait(void); #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 +#define SCHED_ISO 4 struct sched_param { int sched_priority; --- linux-2.6.0-test2-mm5-O14/kernel/sched.c 2003-08-10 02:41:23.000000000 +1000 +++ linux-2.6.0-test2-mm5/kernel/sched.c 2003-08-10 02:19:06.000000000 +1000 @@ -88,6 +88,7 @@ #define STARVATION_LIMIT (MAX_SLEEP_AVG) #define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG)) #define NODE_THRESHOLD 125 +#define ISO_TIME 25 /* * If a task is 'interactive' then we reinsert it in the active @@ -144,6 +145,9 @@ ((p)->prio == (rq)->curr->prio && \ (p)->time_slice > (rq)->curr->time_slice * 2)) +#define ISO_REFRACTORY_PERIOD(rq) \ + ((rq)->iso_timespace > ISO_TIME) + /* * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ] * to time slice values. @@ -187,7 +191,7 @@ struct prio_array { struct runqueue { spinlock_t lock; unsigned long nr_running, nr_switches, expired_timestamp, - nr_uninterruptible; + nr_uninterruptible, iso_timespace; task_t *curr, *idle; struct mm_struct *prev_mm; prio_array_t *active, *expired, arrays[2]; @@ -359,6 +363,15 @@ static int effective_prio(task_t *p) return prio; } +static int effective_iso_prio(task_t *p) +{ + int prio = p->static_prio - (MAX_BONUS / 2) - 1; + + if (prio < MAX_RT_PRIO) + prio = MAX_RT_PRIO; + return prio; +} + /* * __activate_task - move a task to the runqueue. */ @@ -372,6 +385,9 @@ static void recalc_task_prio(task_t *p, { unsigned long long __sleep_time = now - p->timestamp; unsigned long sleep_time; + runqueue_t *rq; + + rq = task_rq(p); if (!p->sleep_avg && VARYING_CREDIT(p)) p->interactive_credit--; @@ -448,8 +464,10 @@ static void recalc_task_prio(task_t *p, } } } - - p->prio = effective_prio(p); + if (unlikely(p->policy == SCHED_ISO && !ISO_REFRACTORY_PERIOD(rq))) + p->prio = effective_iso_prio(p); + else + p->prio = effective_prio(p); } /* @@ -1346,6 +1364,10 @@ void scheduler_tick(int user_ticks, int * timeslice. This makes it possible for interactive tasks * to use up their timeslices at their highest priority levels. */ + if (rq->iso_timespace && (p->policy != SCHED_ISO || + (p->policy == SCHED_ISO && ISO_REFRACTORY_PERIOD(rq)))) + rq->iso_timespace--; + if (unlikely(rt_task(p))) { /* * RR tasks need a special form of timeslice management. @@ -1362,6 +1384,16 @@ void scheduler_tick(int user_ticks, int } goto out_unlock; } + + if (unlikely(p->policy == SCHED_ISO && !ISO_REFRACTORY_PERIOD(rq))){ + rq->iso_timespace++; + if (ISO_REFRACTORY_PERIOD(rq)){ + dequeue_task(p, rq->active); + p->prio = effective_prio(p); + enqueue_task(p, rq->active); + } + } + if (!--p->time_slice) { dequeue_task(p, rq->active); set_tsk_need_resched(p); @@ -1958,10 +1990,13 @@ static int setscheduler(pid_t pid, int p else { retval = -EINVAL; if (policy != SCHED_FIFO && policy != SCHED_RR && - policy != SCHED_NORMAL) + policy != SCHED_ISO && policy != SCHED_NORMAL) goto out_unlock; } + if (policy == SCHED_RR && !capable(CAP_SYS_NICE)) + policy = SCHED_ISO; + /* * Valid priorities for SCHED_FIFO and SCHED_RR are * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0. @@ -2290,6 +2325,7 @@ asmlinkage long sys_sched_get_priority_m ret = MAX_USER_RT_PRIO-1; break; case SCHED_NORMAL: + case SCHED_ISO: ret = 0; break; } @@ -2313,6 +2349,7 @@ asmlinkage long sys_sched_get_priority_m ret = 1; break; case SCHED_NORMAL: + case SCHED_ISO: ret = 0; } return ret; @@ -2731,6 +2768,7 @@ void __init sched_init(void) rq = cpu_rq(i); rq->active = rq->arrays; rq->expired = rq->arrays + 1; + rq->iso_timespace = 0; spin_lock_init(&rq->lock); INIT_LIST_HEAD(&rq->migration_queue); atomic_set(&rq->nr_iowait, 0);