diff -Nru linux-2.5.74.vanilla/include/linux/sched.h linux-2.5.74.mod/include/linux/sched.h --- linux-2.5.74.vanilla/include/linux/sched.h Mon Jul 7 16:57:33 2003 +++ linux-2.5.74.mod/include/linux/sched.h Wed Jul 9 17:07:02 2003 @@ -124,6 +124,8 @@ #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 +#define SCHED_SOFTRR 3 + struct sched_param { int sched_priority; @@ -343,6 +345,7 @@ unsigned long policy; unsigned long cpus_allowed; unsigned int time_slice, first_time_slice; + unsigned long ts_timestamp; struct list_head tasks; struct list_head ptrace_children; diff -Nru linux-2.5.74.vanilla/kernel/sched.c linux-2.5.74.mod/kernel/sched.c --- linux-2.5.74.vanilla/kernel/sched.c Mon Jul 7 16:57:33 2003 +++ linux-2.5.74.mod/kernel/sched.c Wed Jul 9 19:13:22 2003 @@ -76,6 +76,7 @@ #define MAX_SLEEP_AVG (10*HZ) #define STARVATION_LIMIT (10*HZ) #define NODE_THRESHOLD 125 +#define SCHED_TS_KSOFTRR 8 /* * If a task is 'interactive' then we reinsert it in the active @@ -1175,6 +1176,7 @@ void scheduler_tick(int user_ticks, int sys_ticks) { int cpu = smp_processor_id(); + unsigned int time_slice; runqueue_t *rq = this_rq(); task_t *p = current; @@ -1219,14 +1221,29 @@ * RR tasks need a special form of timeslice management. * FIFO tasks have no timeslices. */ - if ((p->policy == SCHED_RR) && !--p->time_slice) { - p->time_slice = task_timeslice(p); + if ((p->policy == SCHED_RR || p->policy == SCHED_SOFTRR) && + !--p->time_slice) { + p->time_slice = time_slice = task_timeslice(p); p->first_time_slice = 0; set_tsk_need_resched(p); - /* put it at the end of the queue: */ + /* + * We rotate SCHED_RR like POSIX states. On the + * contrary, SCHED_SOFTRR are real-time tasks without + * attitude and we do not want them to starve other + * tasks while we want them to be able to preempt + * SCHED_NORMAL tasks. The rule is that SCHED_SOFTRR + * will be expired if they require roughly more then + * 1/SCHED_TS_KSOFTRR percent of CPU time. + */ dequeue_task(p, rq->active); - enqueue_task(p, rq->active); + if (p->policy == SCHED_RR || + (jiffies - p->ts_timestamp) > SCHED_TS_KSOFTRR * time_slice) + enqueue_task(p, rq->active); + else + enqueue_task(p, rq->expired); + + p->ts_timestamp = jiffies; } goto out_unlock; } @@ -1243,6 +1260,8 @@ enqueue_task(p, rq->expired); } else enqueue_task(p, rq->active); + + p->ts_timestamp = jiffies; } out_unlock: spin_unlock(&rq->lock); @@ -1740,10 +1759,15 @@ else { retval = -EINVAL; if (policy != SCHED_FIFO && policy != SCHED_RR && - policy != SCHED_NORMAL) + policy != SCHED_NORMAL && policy != SCHED_SOFTRR) goto out_unlock; } +#if 1 + if (policy == SCHED_RR && !capable(CAP_SYS_NICE)) + policy = SCHED_SOFTRR; +#endif + /* * Valid priorities for SCHED_FIFO and SCHED_RR are * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0. @@ -2069,6 +2093,7 @@ switch (policy) { case SCHED_FIFO: case SCHED_RR: + case SCHED_SOFTRR: ret = MAX_USER_RT_PRIO-1; break; case SCHED_NORMAL: @@ -2092,6 +2117,7 @@ switch (policy) { case SCHED_FIFO: case SCHED_RR: + case SCHED_SOFTRR: ret = 1; break; case SCHED_NORMAL: