diff -urN oldtree/include/linux/init_task.h newtree/include/linux/init_task.h --- oldtree/include/linux/init_task.h 2006-09-24 17:03:56.000000000 -0400 +++ newtree/include/linux/init_task.h 2006-09-26 14:22:10.000000000 -0400 @@ -90,7 +90,62 @@ /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) + * + * Multiple functions for the multiple schedulers, same thing: */ +#ifdef CONFIG_INGOSCHED +#define INIT_TASK(tsk) \ +{ \ + .state = 0, \ + .thread_info = &init_thread_info, \ + .usage = ATOMIC_INIT(2), \ + .flags = 0, \ + .lock_depth = -1, \ + .prio = MAX_PRIO-20, \ + .static_prio = MAX_PRIO-20, \ + .normal_prio = MAX_PRIO-20, \ + .policy = SCHED_NORMAL, \ + .cpus_allowed = CPU_MASK_ALL, \ + .mm = NULL, \ + .active_mm = &init_mm, \ + .run_list = LIST_HEAD_INIT(tsk.run_list), \ + .ioprio = 0, \ + .time_slice = HZ, \ + .tasks = LIST_HEAD_INIT(tsk.tasks), \ + .ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children), \ + .ptrace_list = LIST_HEAD_INIT(tsk.ptrace_list), \ + .real_parent = &tsk, \ + .parent = &tsk, \ + .children = LIST_HEAD_INIT(tsk.children), \ + .sibling = LIST_HEAD_INIT(tsk.sibling), \ + .group_leader = &tsk, \ + .group_info = &init_groups, \ + .cap_effective = CAP_INIT_EFF_SET, \ + .cap_inheritable = CAP_INIT_INH_SET, \ + .cap_permitted = CAP_FULL_SET, \ + .keep_capabilities = 0, \ + .user = INIT_USER, \ + .comm = "swapper", \ + .thread = INIT_THREAD, \ + .fs = &init_fs, \ + .files = &init_files, \ + .signal = &init_signals, \ + .sighand = &init_sighand, \ + .nsproxy = &init_nsproxy, \ + .pending = { \ + .list = LIST_HEAD_INIT(tsk.pending.list), \ + .signal = {{0}}}, \ + .blocked = {{0}}, \ + .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock), \ + .journal_info = NULL, \ + .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ + .fs_excl = ATOMIC_INIT(0), \ + .pi_lock = SPIN_LOCK_UNLOCKED, \ + INIT_TRACE_IRQFLAGS \ + INIT_LOCKDEP \ +} +#endif +#ifdef CONFIG_STAIRCASE #define INIT_TASK(tsk) \ { \ .state = 0, \ @@ -98,9 +153,9 @@ .usage = ATOMIC_INIT(2), \ .flags = 0, \ .lock_depth = -1, \ - .prio = MAX_PRIO-20, \ - .static_prio = MAX_PRIO-20, \ - .normal_prio = MAX_PRIO-20, \ + .prio = MAX_PRIO-21, \ + .static_prio = MAX_PRIO-21, \ + .normal_prio = MAX_PRIO-21, \ .policy = SCHED_NORMAL, \ .cpus_allowed = CPU_MASK_ALL, \ .mm = NULL, \ @@ -141,7 +196,7 @@ INIT_TRACE_IRQFLAGS \ INIT_LOCKDEP \ } - +#endif #define INIT_CPU_TIMERS(cpu_timers) \ { \ diff -urN oldtree/include/linux/sched.h newtree/include/linux/sched.h --- oldtree/include/linux/sched.h 2006-09-24 19:25:46.000000000 -0400 +++ newtree/include/linux/sched.h 2006-09-26 14:24:28.000000000 -0400 @@ -36,6 +36,7 @@ #define SCHED_BATCH 3 #ifdef CONFIG_STAIRCASE #define SCHED_ISO 4 +#define SCHED_IDLEPRIO 5 #endif #ifdef __KERNEL__ @@ -44,7 +45,7 @@ #define SCHED_MAX SCHED_BATCH #endif #ifdef CONFIG_STAIRCASE -#define SCHED_MAX SCHED_ISO +#define SCHED_MAX SCHED_IDLEPRIO #endif #define SCHED_RANGE(policy) ((policy) <= SCHED_MAX) #define SCHED_RT(policy) ((policy) == SCHED_FIFO || \ @@ -521,9 +522,13 @@ #define ISO_PRIO (MAX_RT_PRIO - 1) #endif +#ifdef CONFIG_INGOSCHED #define MAX_PRIO (MAX_RT_PRIO + 40) +#endif #ifdef CONFIG_STAIRCASE -#define MIN_USER_PRIO (MAX_PRIO - 1) +#define MAX_PRIO (MAX_RT_PRIO + 41) +#define MIN_USER_PRIO (MAX_PRIO - 2) +#define IDLEPRIO_PRIO (MAX_PRIO - 1) #endif #define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO) @@ -535,7 +540,8 @@ #endif #ifdef CONFIG_STAIRCASE #define has_rt_policy(p) unlikely(is_rt_policy((p)->policy) && SCHED_RT((p)->policy)) -#define iso_task(p) (unlikely((p)->policy == SCHED_ISO)) +#define iso_task(p) (unlikely((p)->policy == SCHED_ISO)) +#define idleprio_task(p) (unlikely((p)->policy == SCHED_IDLEPRIO)) #endif /* Must be high prio: stop_machine expects to yield to it. */ diff -urN oldtree/kernel/sched_staircase.c newtree/kernel/sched_staircase.c --- oldtree/kernel/sched_staircase.c 2006-09-24 19:25:46.000000000 -0400 +++ newtree/kernel/sched_staircase.c 2006-09-26 14:31:14.000000000 -0400 @@ -684,6 +684,12 @@ else #endif p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority); + } else if (idleprio_task(p)) { + /* + * We want idleprio_tasks to have a presence on weighting but + * as small as possible + */ + p->load_weight = 1; } else p->load_weight = TASK_LOAD_WEIGHT(p); } @@ -860,6 +866,17 @@ continue_slice(p); } +static inline int idleprio_suitable(const struct task_struct *p) +{ + return (!p->mutexes_held && + !(p->flags & (PF_FREEZE | PF_NONSLEEP | PF_EXITING))); +} + +static inline int idleprio(const struct task_struct *p) +{ + return (p->prio == IDLEPRIO_PRIO); +} + /* * __normal_prio - dynamic priority dependent on bonus. * The priority normally decreases by one each RR_INTERVAL. @@ -883,6 +900,18 @@ return ISO_PRIO; } + if (idleprio_task(p)) { + if (unlikely(!idleprio_suitable(p))) { + /* + * If idleprio tasks are holding a semaphore, mutex, + * or being frozen, schedule at a normal priority. + */ + p->time_slice = p->slice % RR_INTERVAL ? : RR_INTERVAL; + return MIN_USER_PRIO; + } + return IDLEPRIO_PRIO; + } + full_slice = slice(p); if (full_slice > p->slice) used_slice = full_slice - p->slice; @@ -1519,6 +1548,8 @@ out_running: p->state = TASK_RUNNING; out: + if (idleprio_task(p) && (p->flags & PF_FREEZE) && idleprio(p)) + requeue_task(p, rq, effective_prio(p)); task_rq_unlock(rq, &flags); return success; @@ -2844,7 +2875,7 @@ /* Add user time to cpustat. */ tmp = cputime_to_cputime64(cputime); - if (TASK_NICE(p) > 0) + if (TASK_NICE(p) > 0 || idleprio_task(p)) cpustat->nice = cputime64_add(cpustat->nice, tmp); else cpustat->user = cputime64_add(cpustat->user, tmp); @@ -2971,11 +3002,14 @@ } } else p->flags &= ~PF_ISOREF; - } else - /* SCHED_FIFO tasks never run out of timeslice. */ - if (unlikely(p->policy == SCHED_FIFO)) - goto out_unlock; - + } else { + if (idleprio_task(p) && !idleprio(p) && idleprio_suitable(p)) + set_tsk_need_resched(p); + else + /* SCHED_FIFO tasks never run out of timeslice. */ + if (unlikely(p->policy == SCHED_FIFO)) + goto out_unlock; + } debit = ns_diff(rq->timestamp_last_tick, p->timestamp); p->ns_debit += debit; @@ -3117,11 +3151,23 @@ if ((jiffies % DEF_TIMESLICE) > (sd->per_cpu_gain * DEF_TIMESLICE / 100)) ret = 1; + else if (idleprio(p)) + ret = 1; } else { if (smt_curr->static_prio < p->static_prio && !TASK_PREEMPTS_CURR(p, smt_rq) && smt_slice(smt_curr, sd) > slice(p)) ret = 1; + else if (idleprio(p) && !idleprio_task(smt_curr) && + smt_curr->slice * sd->per_cpu_gain > + slice(smt_curr)) { + /* + * With idleprio tasks they run just the last + * per_cpu_gain percent of the smt task's + * slice. + */ + ret = 1; + } } unlock: spin_unlock(&smt_rq->lock); @@ -3778,8 +3824,9 @@ * If the task increased its priority or is running and * lowered its priority, then reschedule its CPU: */ - if (delta < 0 || (delta > 0 && task_running(rq, p))) - resched_task(rq->curr); + if (delta < 0 || ((delta > 0 || idleprio_task(p)) && + task_running(rq, p))) + resched_task(rq->curr); } out_unlock: task_rq_unlock(rq, &flags); @@ -3832,6 +3879,11 @@ if (increment < 0 && !can_nice(current, nice)) return -EPERM; + if (!(p->mm) && policy == SCHED_IDLEPRIO) { + /* Don't allow kernel threads to be SCHED_IDLEPRIO. */ + return -EINVAL; + } + retval = security_task_setnice(current, nice); if (retval) return retval; @@ -4301,7 +4353,7 @@ schedstat_inc(rq, yld_cnt); current->slice = slice(current); current->time_slice = rr_interval(current); - if (likely(!rt_task(current))) + if (likely(!rt_task(current) && !idleprio(current))) newprio = MIN_USER_PRIO; requeue_task(current, rq, newprio); @@ -4466,6 +4518,7 @@ case SCHED_NORMAL: case SCHED_BATCH: case SCHED_ISO: + case SCHED_IDLEPRIO: ret = 0; break; } @@ -4490,6 +4543,8 @@ break; case SCHED_NORMAL: case SCHED_BATCH: + case SCHED_ISO; + case SCHED_IDLEPRIO; ret = 0; } return ret;