Index: linux-2.6.30-bfs/include/linux/sched.h =================================================================== --- linux-2.6.30-bfs.orig/include/linux/sched.h 2009-08-29 16:57:09.103278003 +1000 +++ linux-2.6.30-bfs/include/linux/sched.h 2009-08-29 16:57:17.655278461 +1000 @@ -37,7 +37,7 @@ #define SCHED_RR 2 #define SCHED_BATCH 3 /* SCHED_ISO: reserved but not implemented yet */ -#define SCHED_IDLE 5 +#define SCHED_IDLEPRIO 5 #ifdef __KERNEL__ @@ -1301,15 +1301,13 @@ * priority to a value higher than any user task. Note: * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO. */ - +#define PRIO_RANGE (40) #define MAX_USER_RT_PRIO 100 #define MAX_RT_PRIO MAX_USER_RT_PRIO -#define PRIO_RANGE (40) - #define MAX_PRIO (MAX_RT_PRIO + PRIO_RANGE) #define NORMAL_PRIO MAX_RT_PRIO -#define PRIO_LIMIT ((NORMAL_PRIO) + 1) - +#define IDLE_PRIO MAX_RT_PRIO + 1 +#define PRIO_LIMIT ((IDLE_PRIO) + 1) #define DEFAULT_PRIO (MAX_RT_PRIO + 20) static inline int rt_prio(int prio) Index: linux-2.6.30-bfs/kernel/sched_bfs.c =================================================================== --- linux-2.6.30-bfs.orig/kernel/sched_bfs.c 2009-08-29 16:57:06.503278070 +1000 +++ linux-2.6.30-bfs/kernel/sched_bfs.c 2009-08-30 01:34:02.879402657 +1000 @@ -70,25 +70,19 @@ #include -/* - * Priority of a process goes from 0..MAX_PRIO-1, valid RT - * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH - * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority - * values are inverted: lower p->prio value means higher priority. - */ - -#define MAX_USER_RT_PRIO 100 -#define MAX_RT_PRIO MAX_USER_RT_PRIO -#define PRIO_RANGE (40) -#define NORMAL_PRIO MAX_RT_PRIO -#define PRIO_LIMIT ((NORMAL_PRIO) + 1) -#define MAX_PRIO (MAX_RT_PRIO + PRIO_RANGE) - #define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO) #define rt_task(p) rt_prio((p)->prio) #define batch_task(p) (unlikely((p)->policy == SCHED_BATCH)) -#define is_rt_policy(p) ((p) != SCHED_NORMAL && (p) != SCHED_BATCH) +#define is_rt_policy(policy) ((policy) == SCHED_FIFO || \ + (policy) == SCHED_RR) #define has_rt_policy(p) unlikely(is_rt_policy((p)->policy)) +#define idleprio_task(p) unlikely((p)->policy == SCHED_IDLEPRIO) + +#define SCHED_RANGE(policy) ((policy) == SCHED_NORMAL || \ + (policy) == SCHED_BATCH || \ + (policy) == SCHED_IDLEPRIO || \ + (policy) == SCHED_FIFO || \ + (policy) == SCHED_RR) /* * Convert user-nice values [ -20 ... 0 ... 19 ] @@ -498,11 +492,23 @@ p->first_time_slice = 0; } +static int idleprio_suitable(struct task_struct *p) +{ + return (!freezing(p) && !signal_pending(p) && + !(task_contributes_to_load(p)) && !(p->flags & (PF_EXITING))); +} + /* * Adding to the global runqueue. Enter with grq locked. */ static inline void enqueue_task(struct task_struct *p) { + if (idleprio_task(p) && !rt_task(p)) { + if (idleprio_suitable(p)) + p->prio = p->normal_prio; + else + p->prio = NORMAL_PRIO; + } __set_bit(p->prio, grq.prio_bitmap); list_add_tail(&p->run_list, grq.queue + p->prio); sched_info_queued(p); @@ -563,6 +569,8 @@ { if (has_rt_policy(p)) return MAX_RT_PRIO - 1 - p->rt_priority; + if (idleprio_task(p)) + return IDLE_PRIO; return NORMAL_PRIO; } @@ -848,16 +856,22 @@ #define rq_idle(rq) ((rq)->curr == (rq)->idle) #endif +/* + * RT tasks preempt purely on priority. SCHED_NORMAL tasks preempt on the + * basis of earlier deadlines. SCHED_BATCH and SCHED_IDLEPRIO don't preempt, + * they cooperatively multitask. + */ static inline int task_preempts_curr(struct task_struct *p, struct rq *rq) { struct task_struct *curr = rq->curr; int preempts = 0; - if (rt_task(p)) { - if (p->prio < curr->prio) - preempts = 1; - } else if (p->prio == curr->prio && p->deadline < rq->queued_deadline) + + if (p->prio < curr->prio) preempts = 1; + else if (p->policy == SCHED_NORMAL && (p->prio == curr->prio && + p->deadline < rq->queued_deadline)) + preempts = 1; return preempts; } @@ -1732,11 +1746,23 @@ return (prio_ratio(p) * rr_interval * HZ / 1000 / 100) ? : 1; } +static inline int longest_deadline(void) +{ + return (prio_ratios[39] * rr_interval * HZ / 1000 / 100); +} + +/* + * SCHED_IDLEPRIO tasks still have a deadline set, but equal to nice +19 for + * when they're scheduled as SCHED_NORMAL tasks. + */ static inline void time_slice_expired(struct task_struct *p) { reset_first_time_slice(p); p->time_slice = timeslice(); - p->deadline = jiffies + prio_deadline_diff(p); + if (idleprio_task(p)) + p->deadline = jiffies + longest_deadline(); + else + p->deadline = jiffies + prio_deadline_diff(p); } static inline void check_deadline(struct task_struct *p) @@ -1745,11 +1771,6 @@ time_slice_expired(p); } -static inline int longest_deadline(void) -{ - return (prio_ratios[39] * rr_interval * HZ / 1000 / 100) + 1; -} - /* * O(n) lookup of all tasks in the global runqueue. The real brainfuck * of lock contention and O(n). @@ -1793,7 +1814,7 @@ goto out; } - long_deadline = shortest_deadline = longest_deadline(); + long_deadline = shortest_deadline = longest_deadline() + 1; list_for_each_entry(p, queue, run_list) { unsigned long deadline_diff; /* Make sure cpu affinity is ok */ @@ -1812,8 +1833,14 @@ edt = p; } } - if (edt == idle) + if (edt == idle) { + if (idx == NORMAL_PRIO) { + /* Haven't checked for SCHED_IDLEPRIO tasks yet */ + idx++; + goto retry; + } goto out; + } out_take: take_task(rq, edt); out: @@ -2667,8 +2694,7 @@ /* double check policy once rq lock held */ if (policy < 0) policy = oldpolicy = p->policy; - else if (policy != SCHED_FIFO && policy != SCHED_RR && - policy != SCHED_NORMAL && policy != SCHED_BATCH) + else if (!SCHED_RANGE(policy)) return -EINVAL; /* * Valid priorities for SCHED_FIFO and SCHED_RR are @@ -3223,6 +3249,7 @@ break; case SCHED_NORMAL: case SCHED_BATCH: + case SCHED_IDLEPRIO: ret = 0; break; } @@ -3247,6 +3274,7 @@ break; case SCHED_NORMAL: case SCHED_BATCH: + case SCHED_IDLEPRIO: ret = 0; } return ret; Index: linux-2.6.30-bfs/include/linux/ioprio.h =================================================================== --- linux-2.6.30-bfs.orig/include/linux/ioprio.h 2009-08-29 16:59:02.368279061 +1000 +++ linux-2.6.30-bfs/include/linux/ioprio.h 2009-08-29 16:59:16.044278383 +1000 @@ -73,7 +73,7 @@ */ static inline int task_nice_ioclass(struct task_struct *task) { - if (task->policy == SCHED_IDLE) + if (task->policy == SCHED_IDLEPRIO) return IOPRIO_CLASS_IDLE; else if (task->policy == SCHED_FIFO || task->policy == SCHED_RR) return IOPRIO_CLASS_RT;