diff --git a/Makefile b/Makefile index edfc2fd..afca4ad 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 18 -EXTRAVERSION = -NAME=Avast! A bilge rat! +EXTRAVERSION = -dynsched +NAME=Go! Cheops! Go! # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index b574433..3dee792 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -55,6 +55,7 @@ #include "internal.h" #define LOAD_INT(x) ((x) >> FSHIFT) #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) +extern DEFINE_PER_CPU(struct sched_drv*, cpusched); /* * Warning: stuff below (imported functions) assumes that its output will fit * into one page. For some of those functions it may be wrong. Moreover, we diff --git a/include/linux/sched.h b/include/linux/sched.h index cb5a373..4e60bb3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -757,6 +757,12 @@ struct audit_context; /* See audit.c */ struct mempolicy; struct pipe_inode_info; +struct sched_change{ + struct sched_drv* new_scheduler; +}; + +struct task_struct* new_scheduler(struct sched_drv* t, int cpu); + #include struct prio_array; @@ -778,7 +784,7 @@ #endif int load_weight; /* for niceness load balancing purposes */ int prio, static_prio, normal_prio; struct list_head run_list; - union sched_drv_task sdu; + struct sched_drv_task sdu; unsigned short ioprio; unsigned int btrace_seq; diff --git a/include/linux/sched_drv.h b/include/linux/sched_drv.h index 300f5bf..b91ca15 100644 --- a/include/linux/sched_drv.h +++ b/include/linux/sched_drv.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include /* * This is the main scheduler driver struct. @@ -17,7 +19,7 @@ #include struct sched_drv { const char *name; const unsigned int idle_prio; - void (*init_runqueue_queue)(union runqueue_queue *); + void (*init_runqueue_queue)(struct runqueue_queue *); #ifdef CONFIG_RT_MUTEXES void (*rt_mutex_setprio)(struct task_struct *, int); #endif @@ -58,11 +60,35 @@ #endif #ifdef CONFIG_MAGIC_SYSRQ void (*normalize_rt_task)(struct task_struct *); #endif + /*dyn-sched stuff*/ + struct list_head schedulers; + void (*activate_task)(struct task_struct *, struct rq *, int); + void (*deactivate_task)(struct task_struct *, struct rq *); + int (*nice_to_prio) (int); + int (*prio_to_nice) (struct task_struct *); struct attribute **attrs; + void (*dequeue_task_rq)(struct task_struct *, struct rq *); }; -extern const struct sched_drv *sched_drvp; +extern void __init sched_drv_setuplist(void); +extern void __init dynsched_init(void); +extern struct sched_drv *sched_drvp_def; extern void sched_drv_sysfs_init(void); +#ifdef CONFIG_SMP + +extern DEFINE_PER_CPU(struct sched_drv*, cpusched); + +#define sched_drvp ((struct sched_drv*)(cpu_sched(smp_processor_id()))) +#define cpu_sched(cpu) (per_cpu(cpusched, (cpu))) +#define this_sched() (__get_cpu_var(cpusched)) +#define task_sched(task) (cpu_sched(task_cpu(task))) +#else /* XXX no comment */ +#define sched_drvp sched_drvp_def +#define cpu_sched(cpu) sched_drvp_def +#define this_sched() sched_drvp_def +#define task_sched(task) sched_drvp_def +#endif /* CONFIG_SMP */ + #endif diff --git a/include/linux/sched_pvt.h b/include/linux/sched_pvt.h index 88748e2..ebaa459 100644 --- a/include/linux/sched_pvt.h +++ b/include/linux/sched_pvt.h @@ -12,6 +12,7 @@ #include #include extern DEFINE_PER_CPU(struct rq, runqueues); +extern DEFINE_PER_CPU(struct sched_drv*, cpusched); #define TASK_PREEMPTS_CURR(p, rq) \ ((p)->prio < (rq)->curr->prio) @@ -23,6 +24,7 @@ #define this_rq() (&__get_cpu_var(runqu #define task_rq(p) cpu_rq(task_cpu(p)) #define cpu_curr(cpu) (cpu_rq(cpu)->curr) + /* * __task_rq_lock - lock the runqueue a given task resides on. * Must be called interrupts disabled. @@ -426,4 +428,21 @@ #define SCHED_DRV_SYSFS_ATTR(aname) (ana #define SCHED_DRV_DECLARE_SYSFS_ENTRY(aname) \ extern struct sched_drv_sysfs_entry aname ## _sdse +#define SCHED_DRV_SYSFS_SCHEDUNIT(aname) \ + if (!(aname ## _sched_drv.attrs == NULL)) { \ + sched_drv_ ## aname ## _ktype.default_attrs = aname ## _sched_drv.attrs; \ + strncpy(sched_drv_ ## aname ## _kobj.name, aname ## _sched_drv.name, KOBJ_NAME_LEN); \ + sched_drv_ ## aname ## _kobj.kset = &cpusched_subsys.kset; \ + (void)kobject_register(&sched_drv_ ## aname ## _kobj); \ + } + +#define SCHED_DRV_SYSFS_SCHEDUNITDEC(aname) \ + static struct kobj_type sched_drv_ ## aname ## _ktype = { \ + .sysfs_ops = &sched_drv_sysfs_ops, \ + .default_attrs = NULL, \ + }; \ + static struct kobject sched_drv_ ## aname ## _kobj = { \ + .ktype = &sched_drv_ ## aname ## _ktype \ + }; + #endif diff --git a/include/linux/sched_runq.h b/include/linux/sched_runq.h index 91177db..55a1da7 100644 --- a/include/linux/sched_runq.h +++ b/include/linux/sched_runq.h @@ -82,7 +82,7 @@ struct nick_runqueue_queue { }; #endif -union runqueue_queue { +struct runqueue_queue { #ifdef CONFIG_CPUSCHED_INGO struct ingo_runqueue_queue ingosched; #endif @@ -126,7 +126,7 @@ #endif */ unsigned long nr_uninterruptible; - union runqueue_queue qu; + struct runqueue_queue qu; unsigned long long timestamp_last_tick; struct task_struct *curr, *idle; @@ -166,4 +166,6 @@ #endif struct lock_class_key rq_lock_key; }; +typedef struct runqueue runqueue_t; + #endif diff --git a/include/linux/sched_spa.h b/include/linux/sched_spa.h index 6a19bfe..c3af6fa 100644 --- a/include/linux/sched_spa.h +++ b/include/linux/sched_spa.h @@ -78,7 +78,7 @@ #ifdef CONFIG_RT_MUTEXES void spa_rt_mutex_setprio(struct task_struct *p, int prio); #endif void spa_sched_init(void); -void spa_init_runqueue_queue(union runqueue_queue *); +void spa_init_runqueue_queue(struct runqueue_queue *); void spa_set_oom_time_slice(struct task_struct *, unsigned long); void spa_set_load_weight(struct task_struct *); unsigned int spa_task_timeslice(const struct task_struct *); @@ -96,6 +96,7 @@ long spa_sys_yield(void); void spa_yield(void); void spa_init_idle(struct task_struct *, int); void spa_init_batch_task(struct task_struct *); +void spa_activate_task(struct task_struct *p, struct rq *rq, int local); #ifdef CONFIG_SMP int spa_move_tasks(struct rq *, int, struct rq *, unsigned long, unsigned long, struct sched_domain *, enum idle_type, int *); diff --git a/include/linux/sched_task.h b/include/linux/sched_task.h index 2a680dd..239d3c1 100644 --- a/include/linux/sched_task.h +++ b/include/linux/sched_task.h @@ -87,7 +87,7 @@ struct nick_sched_drv_task { }; #endif -union sched_drv_task { +struct sched_drv_task { #ifdef CONFIG_CPUSCHED_INGO struct ingo_sched_drv_task ingosched; #endif diff --git a/init/main.c b/init/main.c index 87ae4fa..6762d62 100644 --- a/init/main.c +++ b/init/main.c @@ -52,6 +52,7 @@ #include #include #include #include +#include #include #include @@ -587,8 +588,10 @@ #endif check_bugs(); acpi_early_init(); /* before LAPIC and SMP init */ +#ifdef CONFIG_CPUSCHED_DYNSCHED + dynsched_init(); +#endif - printk("Running with \"%s\" cpu scheduler.\n", sched_drvp->name); /* Do the rest non-__init'ed, we're now alive */ rest_init(); } @@ -666,7 +669,6 @@ static void __init do_basic_setup(void) #ifdef CONFIG_SYSCTL sysctl_init(); #endif - sched_drv_sysfs_init(); do_initcalls(); } diff --git a/kernel/Kconfig.cpusched b/kernel/Kconfig.cpusched index c75b16e..57e1259 100644 --- a/kernel/Kconfig.cpusched +++ b/kernel/Kconfig.cpusched @@ -1,4 +1,3 @@ - menu "CPU schedulers" config CPUSCHED_SPA @@ -22,6 +21,14 @@ config CPUSCHED_CHOICE If you say n here the single scheduler to be built into the kernel may be selected at "Default CPU scheduler". +config CPUSCHED_DYNSCHED + bool "Switch CPU schedulers at runtime" if CPUSCHED_CHOICE + depends on EXPERIMENTAL + default n + ---help--- + Say y here if you want to be able to switch the cpu scheduler at + runtime. + config CPUSCHED_CHOOSE_BUILTINS bool "Select which CPU schedulers to build in" if CPUSCHED_CHOICE default n diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 4ea6f0d..a8f5a13 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -29,6 +29,7 @@ #include #include #include #include +#include #include #include #include @@ -39,6 +40,8 @@ #include #include #include #include +#include +#include #include #include #include @@ -54,6 +57,7 @@ #include #include #include + #define CPUSET_SUPER_MAGIC 0x27e0eb /* @@ -1255,6 +1259,59 @@ static int attach_task(struct cpuset *cs return 0; } + +#ifdef CONFIG_CPUSCHED_DYNSCHED +extern struct list_head *scheduler_listp; +/* invoke sched change for each cpu in cs->cpus_allowed */ +static int start_sched_switch(struct cpuset *cs, char *schedbuf) +{ + int cpu; + int retval; + struct list_head *p, *n; + struct sched_drv* sd = NULL; + struct task_struct *t; + cpumask_t mask; + mutex_lock(&callback_mutex); + mask = cs->cpus_allowed; + mutex_unlock(&callback_mutex); + + list_for_each_safe(p,n, scheduler_listp) { + sd = list_entry(p, struct sched_drv, schedulers); + if(0 == strncmp(sd->name, schedbuf, strlen(sd->name))) { + goto found; + } + } + retval = -1; + goto out; + +found: + for_each_cpu_mask(cpu,mask) { + t = new_scheduler(sd,cpu); + wake_up_process(t); + } + /* XXX */ + retval = 0; +out: + return retval; +} + +static int sched_of_set(char *page, struct cpuset *cs) +{ + int cpu; + char* p = page; + cpumask_t mask; + + mutex_lock(&callback_mutex); + mask = cs->cpus_allowed; + mutex_unlock(&callback_mutex); + for_each_cpu_mask(cpu,mask) { + p += sprintf(p,"CPU %d: %s\n",cpu,(cpu_sched(cpu))->name); + } + + return (strlen(page)-1); +} +#endif + /* The various types of files and directories in a cpuset file system */ typedef enum { @@ -1271,6 +1328,9 @@ typedef enum { FILE_SPREAD_PAGE, FILE_SPREAD_SLAB, FILE_TASKLIST, +#ifdef CONFIG_CPUSCHED_DYNSCHED + FILE_DYNSCHED, +#endif } cpuset_filetype_t; static ssize_t cpuset_common_file_write(struct file *file, const char __user *userbuf, @@ -1340,6 +1400,11 @@ static ssize_t cpuset_common_file_write( case FILE_TASKLIST: retval = attach_task(cs, buffer, &pathbuf); break; +#ifdef CONFIG_CPUSCHED_DYNSCHED + case FILE_DYNSCHED: + retval = start_sched_switch(cs,buffer); + break; +#endif default: retval = -EINVAL; goto out2; @@ -1452,6 +1517,11 @@ static ssize_t cpuset_common_file_read(s case FILE_SPREAD_SLAB: *s++ = is_spread_slab(cs) ? '1' : '0'; break; +#ifdef CONFIG_CPUSCHED_DYNSCHED + case FILE_DYNSCHED: + s += sched_of_set(s, cs); + break; +#endif default: retval = -EINVAL; goto out; @@ -1825,6 +1895,13 @@ static struct cftype cft_spread_slab = { .private = FILE_SPREAD_SLAB, }; +#ifdef CONFIG_CPUSCHED_DYNSCHED +static struct cftype cft_dynsched = { + .name = "dynsched", + .private = FILE_DYNSCHED, +}; +#endif + static int cpuset_populate_dir(struct dentry *cs_dentry) { int err; @@ -1849,6 +1926,10 @@ static int cpuset_populate_dir(struct de return err; if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0) return err; +#ifdef CONFIG_CPUSCHED_DYNSCHED + if ((err = cpuset_add_file(cs_dentry, &cft_dynsched)) < 0) + return err; +#endif return 0; } diff --git a/kernel/ingo_ll.c b/kernel/ingo_ll.c index 4b1b205..5cc3f30 100644 --- a/kernel/ingo_ll.c +++ b/kernel/ingo_ll.c @@ -18,7 +18,8 @@ #include #include #include -static void ingo_init_runqueue_queue(union runqueue_queue *rqq) + +static void ingo_init_runqueue_queue(struct runqueue_queue *rqq) { int j; @@ -260,6 +261,11 @@ static void dequeue_task(struct task_str __clear_bit(p->prio, array->bitmap); } +static void ingo_ll_dequeue_task_rq(struct task_struct *p, runqueue_t *rq) +{ + dequeue_task(p,p->sdu.ingo_ll.array); +} + static void enqueue_task(struct task_struct *p, struct prio_array *array) { sched_info_queued(p); @@ -267,6 +273,7 @@ static void enqueue_task(struct task_str __set_bit(p->prio, array->bitmap); array->nr_active++; p->sdu.ingo_ll.array = array; + p->sdu.ingosched.array = array; } /* @@ -376,12 +383,12 @@ static inline void __activate_idle_task( } /* - * activate_task - move a task to the runqueue and do priority recalculation + * ingo_ll_activate_task - move a task to the runqueue and do priority recalculation * * Update all the scheduling statistics stuff. (sleep average * calculation, priority modifiers, etc.) */ -static void activate_task(struct task_struct *p, struct rq *rq, int local) +static void ingo_ll_activate_task(struct task_struct *p, struct rq *rq, int local) { unsigned long long now; @@ -404,9 +411,9 @@ #endif } /* - * deactivate_task - remove a task from the runqueue. + * ingo_ll_deactivate_task - remove a task from the runqueue. */ -static void deactivate_task(struct task_struct *p, struct rq *rq) +static void ingo_ll_deactivate_task(struct task_struct *p, struct rq *rq) { dec_nr_running(p, rq); dequeue_task(p, p->sdu.ingo_ll.array); @@ -439,7 +446,7 @@ static void ingo_wake_up_task(struct tas p->sdu.ingo_ll.flags |= ILLF_JUST_WOKEN; - activate_task(p, rq, same_cpu); + ingo_ll_activate_task(p, rq, same_cpu); /* * Sync wakeups (i.e. those types of wakeups where the waker * has indicated that it will leave the CPU in short order) @@ -614,8 +621,14 @@ static void pull_task(struct rq *src_rq, struct task_struct *p, struct rq *this_rq, struct prio_array *this_array, int this_cpu) { + dequeue_task(p, src_array); dec_nr_running(p, src_rq); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } set_task_cpu(p, this_cpu); inc_nr_running(p, this_rq); enqueue_task(p, this_array); @@ -904,7 +917,7 @@ static void ingo_schedule(void) else { if (prev->state == TASK_UNINTERRUPTIBLE) rq->nr_uninterruptible++; - deactivate_task(prev, rq); + ingo_ll_deactivate_task(prev, rq); } } @@ -1070,7 +1083,7 @@ static void ingo_setscheduler(struct tas array = p->sdu.ingo_ll.array; if (array) - deactivate_task(p, rq); + ingo_ll_deactivate_task(p, rq); oldprio = p->prio; __setscheduler(p, policy, prio); if (array) { @@ -1173,9 +1186,14 @@ static void ingo_migrate_queued_task(str */ p->timestamp = p->timestamp - rq_src->timestamp_last_tick + rq_dest->timestamp_last_tick; - deactivate_task(p, rq_src); + task_sched(p)->deactivate_task(p, rq_src); set_task_cpu(p, dest_cpu); - __activate_task(p, rq_dest); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } + task_sched(p)->activate_task(p, rq_dest, 1); if (TASK_PREEMPTS_CURR(p, rq_dest)) resched_task(rq_dest->curr); } @@ -1194,7 +1212,7 @@ static void ingo_set_select_idle_last(st { struct task_struct *p = rq->idle; - deactivate_task(p, rq); + ingo_ll_deactivate_task(p, rq); p->static_prio = INGO_MAX_PRIO; __setscheduler(p, SCHED_NORMAL, 0); } @@ -1233,7 +1251,7 @@ static void ingo_normalize_rt_task(struc array = p->sdu.ingo_ll.array; if (array) - deactivate_task(p, rq); + ingo_ll_deactivate_task(p, rq); __setscheduler(p, SCHED_NORMAL, 0); if (array) { __activate_task(p, rq); @@ -1250,6 +1268,17 @@ static struct attribute *ingo_ll_attrs[] NULL, }; +int ingo_ll_prio_to_nice(struct task_struct *p) +{ + return PRIO_TO_NICE(p->static_prio); +} + +int ingo_ll_nice_to_prio(int nice) +{ + return NICE_TO_PRIO(nice); +} + + const struct sched_drv ingo_ll_sched_drv = { .name = "ingo_ll", .idle_prio = INGO_MAX_PRIO, @@ -1293,4 +1322,9 @@ #ifdef CONFIG_MAGIC_SYSRQ .normalize_rt_task = ingo_normalize_rt_task, #endif .attrs = ingo_ll_attrs, + .activate_task = ingo_ll_activate_task, + .deactivate_task = ingo_ll_deactivate_task, + .prio_to_nice = ingo_ll_prio_to_nice, + .nice_to_prio = ingo_ll_nice_to_prio, + .dequeue_task_rq = (void*)ingo_ll_dequeue_task_rq }; diff --git a/kernel/ingosched.c b/kernel/ingosched.c index d951233..c22a511 100644 --- a/kernel/ingosched.c +++ b/kernel/ingosched.c @@ -17,8 +17,10 @@ #include #include #include #include +#include -static void ingo_init_runqueue_queue(union runqueue_queue *rqq) + +static void ingo_init_runqueue_queue(struct runqueue_queue *rqq) { int j; @@ -171,6 +173,11 @@ static void dequeue_task(struct task_str __clear_bit(p->prio, array->bitmap); } +static inline void ingo_dequeue_task_rq(struct task_struct *p, runqueue_t *rq) +{ + dequeue_task(p,p->sdu.ingosched.array); +} + static void enqueue_task(struct task_struct *p, struct prio_array *array) { sched_info_queued(p); @@ -178,6 +185,7 @@ static void enqueue_task(struct task_str __set_bit(p->prio, array->bitmap); array->nr_active++; p->sdu.ingosched.array = array; + p->sdu.ingo_ll.array = array; } /* @@ -360,12 +368,12 @@ static int recalc_task_prio(struct task_ } /* - * activate_task - move a task to the runqueue and do priority recalculation + * ingo_activate_task - move a task to the runqueue and do priority recalculation * * Update all the scheduling statistics stuff. (sleep average * calculation, priority modifiers, etc.) */ -static void activate_task(struct task_struct *p, struct rq *rq, int local) +static void ingo_activate_task(struct task_struct *p, struct rq *rq, int local) { unsigned long long now; @@ -410,13 +418,14 @@ #endif } /* - * deactivate_task - remove a task from the runqueue. + * ingo_deactivate_task - remove a task from the runqueue. */ -static void deactivate_task(struct task_struct *p, struct rq *rq) +static void ingo_deactivate_task(struct task_struct *p, struct rq *rq) { dec_nr_running(p, rq); dequeue_task(p, p->sdu.ingosched.array); p->sdu.ingosched.array = NULL; + p->sdu.ingo_ll.array = NULL; } /*** @@ -448,7 +457,7 @@ static void ingo_wake_up_task(struct tas p->sdu.ingosched.sleep_type = SLEEP_NONINTERACTIVE; - activate_task(p, rq, same_cpu); + ingo_activate_task(p, rq, same_cpu); /* * Sync wakeups (i.e. those types of wakeups where the waker * has indicated that it will leave the CPU in short order) @@ -641,8 +650,13 @@ static void pull_task(struct rq *src_rq, struct task_struct *p, struct rq *this_rq, struct prio_array *this_array, int this_cpu) { - dequeue_task(p, src_array); + task_sched(p)->dequeue_task_rq(p, src_rq); dec_nr_running(p, src_rq); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } set_task_cpu(p, this_cpu); inc_nr_running(p, this_rq); enqueue_task(p, this_array); @@ -944,7 +958,7 @@ static void ingo_schedule(void) else { if (prev->state == TASK_UNINTERRUPTIBLE) rq->nr_uninterruptible++; - deactivate_task(prev, rq); + ingo_deactivate_task(prev, rq); } } @@ -1128,7 +1142,7 @@ static void ingo_setscheduler(struct tas array = p->sdu.ingosched.array; if (array) - deactivate_task(p, rq); + ingo_deactivate_task(p, rq); oldprio = p->prio; __setscheduler(p, policy, prio); if (array) { @@ -1228,9 +1242,14 @@ static void ingo_migrate_queued_task(str */ p->timestamp = p->timestamp - rq_src->timestamp_last_tick + rq_dest->timestamp_last_tick; - deactivate_task(p, rq_src); - set_task_cpu(p, dest_cpu); - __activate_task(p, rq_dest); + task_sched(p)->deactivate_task(p, rq_src); + set_task_cpu(p, dest_cpu); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } + cpu_sched(dest_cpu)->activate_task(p, rq_dest, 0); if (TASK_PREEMPTS_CURR(p, rq_dest)) resched_task(rq_dest->curr); } @@ -1249,7 +1268,7 @@ static void ingo_set_select_idle_last(st { struct task_struct *p = rq->idle; - deactivate_task(p, rq); + ingo_deactivate_task(p, rq); p->static_prio = INGO_MAX_PRIO; __setscheduler(p, SCHED_NORMAL, 0); } @@ -1288,15 +1307,25 @@ static void ingo_normalize_rt_task(struc array = p->sdu.ingosched.array; if (array) - deactivate_task(p, rq); + ingo_deactivate_task(p, rq); __setscheduler(p, SCHED_NORMAL, 0); if (array) { - __activate_task(p, rq); + __ingo_activate_task(p, rq); resched_task(rq->curr); } } #endif +int ingo_prio_to_nice(struct task_struct *p) +{ + return PRIO_TO_NICE(p->static_prio); +} + +int ingo_nice_to_prio(int nice) +{ + return NICE_TO_PRIO(nice); +} + const struct sched_drv ingo_sched_drv = { .name = "ingosched", .idle_prio = INGO_MAX_PRIO, @@ -1340,4 +1369,9 @@ #ifdef CONFIG_MAGIC_SYSRQ .normalize_rt_task = ingo_normalize_rt_task, #endif .attrs = NULL, + .activate_task = ingo_activate_task, + .deactivate_task = ingo_deactivate_task, + .prio_to_nice = ingo_prio_to_nice, + .nice_to_prio = ingo_nice_to_prio, + .dequeue_task_rq = (void*)ingo_dequeue_task_rq, }; diff --git a/kernel/nicksched.c b/kernel/nicksched.c index 5db8450..ab64f4f 100644 --- a/kernel/nicksched.c +++ b/kernel/nicksched.c @@ -17,7 +17,7 @@ #include #include #include -static void nick_init_runqueue_queue(union runqueue_queue *rqq) +static void nick_init_runqueue_queue(struct runqueue_queue *rqq) { int j; @@ -107,6 +107,7 @@ #define TASK_PREEMPTS_CURR(p, rq) \ /* * Adding/removing a task to/from a priority array: */ + static void dequeue_task(struct task_struct *p, struct nick_prio_array *array) { array->nr_active--; @@ -115,6 +116,11 @@ static void dequeue_task(struct task_str __clear_bit(p->prio, array->bitmap); } +static void nick_dequeue_task_rq(struct task_struct *p, runqueue_t *rq) +{ + dequeue_task(p,p->sdu.nicksched.array); +} + static void enqueue_task(struct task_struct *p, struct nick_prio_array *array) { struct list_head *entry = array->queue + p->prio; @@ -293,12 +299,12 @@ static inline void __activate_task(struc } /* - * activate_task - move a task to the runqueue and do priority recalculation + * nick_activate_task - move a task to the runqueue and do priority recalculation * * Update all the scheduling statistics stuff. (sleep average * calculation, priority modifiers, etc.) */ -static void activate_task(struct task_struct *p, struct rq *rq, int local) +static void nick_activate_task(struct task_struct *p, struct rq *rq, int local) { unsigned long long now, sleep; struct nick_prio_array *array; @@ -343,9 +349,9 @@ static inline void __activate_idle_task( } /* - * deactivate_task - remove a task from the runqueue. + * nick_deactivate_task - remove a task from the runqueue. */ -static inline void deactivate_task(struct task_struct *p, struct rq *rq) +static inline void nick_deactivate_task(struct task_struct *p, struct rq *rq) { p->sdu.nicksched.array_sequence = rq->qu.nicksched.array_sequence; dec_nr_running(p, rq); @@ -375,7 +381,7 @@ static void nick_wake_up_task(struct tas * the waker guarantees that the freshly woken up task is going * to be considered on this CPU.) */ - activate_task(p, rq, same_cpu); + nick_activate_task(p, rq, same_cpu); if (!sync || !same_cpu) { if (TASK_PREEMPTS_CURR(p, rq)) resched_task(rq->curr); @@ -525,13 +531,19 @@ static inline void pull_task(struct rq *src_rq, struct nick_prio_array *src_array, struct task_struct *p, struct rq *this_rq, struct nick_prio_array *this_array, int this_cpu) { - dequeue_task(p, src_array); + + task_sched(p)->dequeue_task_rq(p, src_rq); dec_nr_running(p, src_rq); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } set_task_cpu(p, this_cpu); inc_nr_running(p, this_rq); enqueue_task(p, this_array); - p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) - + this_rq->timestamp_last_tick; + p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) + this_rq->timestamp_last_tick; + /* * Note that idle threads have a prio of NICK_MAX_PRIO, for this test * to be always true for them. @@ -621,6 +633,7 @@ #ifdef CONFIG_SCHEDSTATS schedstat_inc(sd, lb_hot_gained[idle]); #endif + pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu); pulled++; rem_load_move -= tmp->load_weight; @@ -726,7 +739,7 @@ static void nick_schedule(void) else { if (prev->state == TASK_UNINTERRUPTIBLE) rq->nr_uninterruptible++; - deactivate_task(prev, rq); + nick_deactivate_task(prev, rq); goto no_check_expired; } } @@ -775,7 +788,6 @@ no_check_expired: idx = sched_find_first_bit(array->bitmap); queue = array->queue + idx; next = list_entry(queue->next, struct task_struct, run_list); - switch_tasks: if (next == rq->idle) schedstat_inc(rq, sched_goidle); @@ -901,7 +913,7 @@ static void nick_setscheduler(struct tas array = p->sdu.nicksched.array; if (array) - deactivate_task(p, rq); + nick_deactivate_task(p, rq); oldprio = p->prio; __setscheduler(p, policy, prio); if (policy == SCHED_FIFO || policy == SCHED_RR) @@ -977,9 +989,14 @@ static void nick_migrate_queued_task(str */ p->timestamp = p->timestamp - rq_src->timestamp_last_tick + rq_dest->timestamp_last_tick; - deactivate_task(p, rq_src); - set_task_cpu(p, dest_cpu); - __activate_task(p, rq_dest, rq_dest->qu.nicksched.active); + task_sched(p)->deactivate_task(p, rq_src); + set_task_cpu(p, dest_cpu); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } + cpu_sched(dest_cpu)->activate_task(p, rq_dest, 0); if (TASK_PREEMPTS_CURR(p, rq_dest)) resched_task(rq_dest->curr); } @@ -994,7 +1011,7 @@ static void nick_set_select_idle_first(s static void nick_set_select_idle_last(struct rq *rq) { - deactivate_task(rq->idle, rq); + nick_deactivate_task(rq->idle, rq); rq->idle->static_prio = NICK_MAX_PRIO; __setscheduler(rq->idle, SCHED_NORMAL, 0); } @@ -1031,7 +1048,7 @@ static void nick_normalize_rt_task(struc array = p->sdu.nicksched.array; if (array) - deactivate_task(p, rq); + nick_deactivate_task(p, rq); __setscheduler(p, SCHED_NORMAL, 0); if (array) { __activate_task(p, rq, array); @@ -1055,6 +1072,29 @@ static struct attribute *nick_attrs[] = }; #endif +/** + * callculates prio to nice + * from 100 ... 159 to -20 .. 0 .. 19 + */ +int nick_prio_to_nice(struct task_struct *p) +{ + return ((((p->static_prio)-MAX_RT_PRIO)*39)/59)-20; +} + +/** + * + */ +int nick_nice_to_prio(int nice) +{ + return NICE_TO_PRIO(nice); +} + +/* get the nicksched array from rq - needed for pull_task */ +void* nick_rqq_from_rq(struct rq *rq) +{ + return &rq->qu.nicksched.active; +} + const struct sched_drv nick_sched_drv = { .name = "nicksched", .idle_prio = NICK_MAX_PRIO, @@ -1098,4 +1138,9 @@ #ifdef CONFIG_MAGIC_SYSRQ .normalize_rt_task = nick_normalize_rt_task, #endif .attrs = nick_attrs, + .activate_task = nick_activate_task, + .deactivate_task = nick_deactivate_task, + .prio_to_nice = nick_prio_to_nice, + .nice_to_prio = nick_nice_to_prio, + .dequeue_task_rq = (void*)nick_dequeue_task_rq }; diff --git a/kernel/sched.c b/kernel/sched.c index 688ce92..83f682b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3572,7 +3572,7 @@ static int __migrate_task(struct task_st if (!cpu_isset(dest_cpu, p->cpus_allowed)) goto out; - if (task_is_queued(p)) + if (task_is_queued(p)) sched_drvp->migrate_queued_task(p, dest_cpu); else set_task_cpu(p, dest_cpu); @@ -5378,14 +5378,15 @@ void __init sched_init(void) { int i; - sched_drvp->sched_init(); + sched_drvp_def->sched_init(); for_each_possible_cpu(i) { struct rq *rq; #ifdef CONFIG_SMP int j; #endif - + cpu_sched(i) = (struct sched_drv*)sched_drvp_def; + printk("CPU %d scheduler: %s\n",i,cpu_sched(i)->name); rq = cpu_rq(i); spin_lock_init(&rq->lock); lockdep_set_class(&rq->lock, &rq->rq_lock_key); @@ -5402,7 +5403,7 @@ #ifdef CONFIG_SMP #endif atomic_set(&rq->nr_iowait, 0); - sched_drvp->init_runqueue_queue(&rq->qu); + sched_drvp_def->init_runqueue_queue(&rq->qu); } set_load_weight(&init_task); @@ -5473,6 +5474,113 @@ void normalize_rt_tasks(void) #endif /* CONFIG_MAGIC_SYSRQ */ + +#ifdef CONFIG_CPUSCHED_DYNSCHED + /** + * scheduler_switch - switching the scheduler + * @data_arg: struct holding the data + * + * This function switches between the running and the new + * scheduler. It is running inside of an kernel thread. + */ +extern struct list_head *scheduler_listp; +int scheduler_switch(void* data_arg) { + + + int nice; + unsigned int cpu = 0; + + struct task_struct *p; + struct rq* rq; + struct list_head *t, *n; + struct sched_drv* sd = NULL; + cpumask_t thismask; + struct sched_change* data = (struct sched_change*)data_arg; + + const struct sched_drv *oldsched = sched_drvp; + struct sched_drv *newsched = data->new_scheduler; + cpus_clear(thismask); + preempt_disable(); + +#ifdef CONFIG_SMP + cpu = smp_processor_id(); + while(!(list_empty(&(cpu_rq(cpu)->migration_queue)))); +#endif + rq = this_rq_lock(); + + list_for_each_safe(t,n, scheduler_listp) { + sd = list_entry(t, struct sched_drv, schedulers); + sd->init_runqueue_queue(&rq->qu); + } + newsched->init_runqueue_queue(&rq->qu); + rq->nr_running = 0; + + cpu_set(cpu,thismask); + + for_each_process(p) { + task_lock(p); +#ifdef CONFIG_SMP + if (task_cpu(p) == cpu ) { + if (cpus_equal(thismask,p->cpus_allowed)) { +#endif + nice = oldsched->prio_to_nice(p); + p->static_prio = newsched->nice_to_prio(nice); + p->prio = p->static_prio; +#ifdef CONFIG_SMP + if(((p->state == TASK_RUNNING) && (p == current)) || + (p == rq->migration_thread)) { newsched->activate_task(p,rq, 1); + } + } else { + set_tsk_need_resched(p); + } + } +#endif +#ifndef CONFIG_SMP + if(p->state == TASK_RUNNING) { + newsched->activate_task(p,rq, 1); + } +#endif + task_unlock(p); + } + + kfree(data); + + /* on fire */ + cpu_sched(cpu) = newsched; + /* both done in this_rq_lock */ + spin_unlock(&rq->lock); + local_irq_enable(); + preempt_enable(); + return 0; + } + + /** + * new_scheduler - kernel this is the entrypoint for switching the scheduler + * @sched_drv: driver struct of new scheduler + * @cpu: to change the sched + * + * This function starts the kernel-thread which switches the scheduler at inside + * a "save" point. + */ +struct task_struct* new_scheduler(struct sched_drv* t, int cpu) +{ + + struct task_struct* kt; + struct task_struct *mt; + struct sched_change* sched_change_data = kmalloc(sizeof(struct sched_change),GFP_ATOMIC); + sched_change_data->new_scheduler = t; + kt = kthread_create(scheduler_switch,sched_change_data,"dynsched/%d",cpu); +#ifdef CONFIG_SMP + kthread_bind(kt, cpu); + mt = cpu_rq(smp_processor_id())->migration_thread; + wake_up_process(mt); +#endif + return kt; + } + +EXPORT_SYMBOL(new_scheduler); +#endif + #ifdef CONFIG_IA64 /* * These functions are only useful for the IA64 MCA handling. diff --git a/kernel/sched_drv.c b/kernel/sched_drv.c index b5b8264..cb20879 100644 --- a/kernel/sched_drv.c +++ b/kernel/sched_drv.c @@ -10,7 +10,10 @@ #include #include #include #include +#include +#include +DEFINE_PER_CPU(struct sched_drv*, cpusched); /* * All private per scheduler entries in task_struct are defined as * separate structs and placed into the cpusched union in task_struct. @@ -18,42 +21,42 @@ #include /* Ingosched */ #ifdef CONFIG_CPUSCHED_INGO -extern const struct sched_drv ingo_sched_drv; +extern struct sched_drv ingo_sched_drv; #endif /* Ingo Low Latency */ #ifdef CONFIG_CPUSCHED_INGO_LL -extern const struct sched_drv ingo_ll_sched_drv; +extern struct sched_drv ingo_ll_sched_drv; #endif /* Staircase */ #ifdef CONFIG_CPUSCHED_STAIRCASE -extern const struct sched_drv staircase_sched_drv; +extern struct sched_drv staircase_sched_drv; #endif /* Single priority array (SPA) schedulers */ #ifdef CONFIG_CPUSCHED_SPA_NF -extern const struct sched_drv spa_nf_sched_drv; +extern struct sched_drv spa_nf_sched_drv; #endif #ifdef CONFIG_CPUSCHED_SPA_WS -extern const struct sched_drv spa_ws_sched_drv; +extern struct sched_drv spa_ws_sched_drv; #endif #ifdef CONFIG_CPUSCHED_SPA_SVR -extern const struct sched_drv spa_svr_sched_drv; +extern struct sched_drv spa_svr_sched_drv; #endif #ifdef CONFIG_CPUSCHED_SPA_EBS -extern const struct sched_drv spa_ebs_sched_drv; +extern struct sched_drv spa_ebs_sched_drv; #endif #ifdef CONFIG_CPUSCHED_ZAPHOD -extern const struct sched_drv zaphod_sched_drv; +extern struct sched_drv zaphod_sched_drv; #endif /* Nicksched */ #ifdef CONFIG_CPUSCHED_NICK -extern const struct sched_drv nick_sched_drv; +extern struct sched_drv nick_sched_drv; #endif -const struct sched_drv *sched_drvp = +struct sched_drv* sched_drvp_def = #if defined(CONFIG_CPUSCHED_DEFAULT_INGO) &ingo_sched_drv; #elif defined(CONFIG_CPUSCHED_DEFAULT_INGO_LL) @@ -77,18 +80,21 @@ #else #error "You must have at least 1 cpu scheduler selected" #endif +struct list_head *scheduler_listp; + extern struct task_struct base_init_task; #define CPUSCHED_CHECK_SELECT(drv) \ do { \ if (!strcmp(str, (drv).name)) { \ - sched_drvp = &(drv); \ + sched_drvp_def = &(drv); \ return 1; \ } \ } while (0) static int __init sched_drv_setup(char *str) { + #if defined(CONFIG_CPUSCHED_INGO) CPUSCHED_CHECK_SELECT(ingo_sched_drv); #endif @@ -119,6 +125,8 @@ #endif return 1; } +decl_subsys(cpusched, NULL, NULL); + __setup ("cpusched=", sched_drv_setup); static ssize_t show_attribute(struct kobject *kobj, struct attribute *attr, char *page) @@ -146,26 +154,143 @@ struct sysfs_ops sched_drv_sysfs_ops = { .store = store_attribute, }; -static struct kobj_type sched_drv_ktype = { - .sysfs_ops = &sched_drv_sysfs_ops, - .default_attrs = NULL, + + +#ifdef CONFIG_CPUSCHED_DYNSCHED +void sched_drv_setup_scheds(void) +{ + +#if defined(CONFIG_CPUSCHED_INGO) + SCHED_DRV_SYSFS_SCHEDUNITDEC(ingo) +#endif +#if defined(CONFIG_CPUSCHED_INGO_LL) + SCHED_DRV_SYSFS_SCHEDUNITDEC(ingo_ll) +#endif +#if defined(CONFIG_CPUSCHED_STAIRCASE) + SCHED_DRV_SYSFS_SCHEDUNITDEC(staircase) +#endif +#if defined(CONFIG_CPUSCHED_SPA_NF) + SCHED_DRV_SYSFS_SCHEDUNITDEC(spa_nf) +#endif +#if defined(CONFIG_CPUSCHED_SPA_WS) + SCHED_DRV_SYSFS_SCHEDUNITDEC(spa_ws) +#endif +#if defined(CONFIG_CPUSCHED_ZAPHOD) + SCHED_DRV_SYSFS_SCHEDUNITDEC(zaphod) +#endif +#if defined(CONFIG_CPUSCHED_NICK) + SCHED_DRV_SYSFS_SCHEDUNITDEC(nick) +#endif + + scheduler_listp = kmalloc(sizeof(struct list_head),GFP_KERNEL); + INIT_LIST_HEAD(scheduler_listp); + +#if defined(CONFIG_CPUSCHED_INGO) + list_add(&ingo_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(ingo) +#endif +#if defined(CONFIG_CPUSCHED_INGO_LL) + list_add(&ingo_ll_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(ingo_ll) +#endif +#if defined(CONFIG_CPUSCHED_STAIRCASE) + list_add(&staircase_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(staircase) +#endif +#if defined(CONFIG_CPUSCHED_SPA_NF) + list_add(&spa_nf_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(spa_nf) +#endif +#if defined(CONFIG_CPUSCHED_SPA_WS) + list_add(&spa_ws_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(spa_ws) +#endif +#if defined(CONFIG_CPUSCHED_ZAPHOD) + list_add(&zaphod_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(zaphod) +#endif +#if defined(CONFIG_CPUSCHED_NICK) + list_add(&nick_sched_drv.schedulers,scheduler_listp); + SCHED_DRV_SYSFS_SCHEDUNIT(nick) +#endif +} + +/* create sysfs entry beside cpuset usage */ +#ifndef CONFIG_SMP +static ssize_t sys_dynsched_read(struct kobject *obj, struct attribute *attr, char *buf) +{ + ssize_t b = 0; + b = sprintf(buf,"%s\n",sched_drvp->name); + return(b); +} + +static ssize_t sys_dynsched_write(struct kobject *obj,struct attribute *attr,const char * buf, size_t size) +{ + int retval = 0; + struct list_head *p, *n; + struct sched_drv* sd = NULL; + struct task_struct *t; + + list_for_each_safe(p,n, scheduler_listp) { + sd = list_entry(p, struct sched_drv, schedulers); + if(0 == strncmp(sd->name, buf, strlen(sd->name))) { + goto found; + } + } + retval = -1; + goto out; + +found: + t = new_scheduler(sd,0); + wake_up_process(t); + /* XXX */ + retval = 0; +out: + return strlen(buf)+1; +} +struct sysfs_ops dynsched_sysfs_ops = { + .show = &sys_dynsched_read, + .store = &sys_dynsched_write, }; -static struct kobject sched_drv_kobj = { - .ktype = &sched_drv_ktype +static struct attribute dynsched_at = { + .name = "dynsched", + .owner = NULL, + .mode = S_IRUGO|S_IWUGO, }; -decl_subsys(cpusched, NULL, NULL); +static struct kobj_type dynsched_ktype = { + .sysfs_ops = &dynsched_sysfs_ops, + .default_attrs = NULL +}; +static struct kobject dynsched_kobj = { + .ktype = &dynsched_ktype +}; +#endif -void __init sched_drv_sysfs_init(void) +void __init dynsched_init() { - if (subsystem_register(&cpusched_subsys) == 0) { - if (sched_drvp->attrs == NULL) - return; - - sched_drv_ktype.default_attrs = sched_drvp->attrs; - strncpy(sched_drv_kobj.name, sched_drvp->name, KOBJ_NAME_LEN); - sched_drv_kobj.kset = &cpusched_subsys.kset; - (void)kobject_register(&sched_drv_kobj); - } + struct list_head *p; + struct sched_drv *drv; + + subsystem_register(&cpusched_subsys); + sched_drv_setup_scheds(); + +#ifndef CONFIG_SMP /* otherwise we have cpuset integration */ + strncpy(dynsched_kobj.name,"dynsched", KOBJ_NAME_LEN); + dynsched_kobj.kset = &cpusched_subsys.kset; + (void)kobject_register(&dynsched_kobj); + sysfs_create_file(&dynsched_kobj, &dynsched_at); +#endif /* CONFIG_SMP */ + + + printk("Dynsched scheduler:"); + list_for_each(p,scheduler_listp) { + drv = list_entry(p, struct sched_drv, schedulers); + printk(" %s",drv->name); + } + printk("\n"); + return; } + +#endif /* CONFIG_CPUSCHED_DYNSCHED */ diff --git a/kernel/sched_spa.c b/kernel/sched_spa.c index 1b5b8d4..0ce6361 100644 --- a/kernel/sched_spa.c +++ b/kernel/sched_spa.c @@ -185,7 +185,7 @@ struct sched_spa_child *spa_sched_child */ static int spa_in_charge = 0; -void spa_init_runqueue_queue(union runqueue_queue *qup) +void spa_init_runqueue_queue(struct runqueue_queue *qup) { int k; @@ -439,7 +439,10 @@ static void activate_task(struct task_st } __activate_task(p, rq); } - +void spa_activate_task(struct task_struct *p, struct rq *rq, int local) +{ + activate_task(p, rq); +} /* * deactivate_task - remove a task from the runqueue. */ @@ -451,6 +454,10 @@ static inline void deactivate_task(struc dequeue_task(p, rqq); } +void spa_deactivate_task(struct task_struct *p, struct rq *rq) +{ + deactivate_task(p, rq); +} /* * Check to see if p preempts rq->curr and resched if it does. In compute * mode we do not preempt for at least cache_delay and set rq->preempted. @@ -1263,5 +1270,6 @@ #ifdef CONFIG_MAGIC_SYSRQ .normalize_rt_task = spa_normalize_rt_task, #endif .attrs = spa_nf_attrs, + .activate_task = spa_activate_task, }; #endif diff --git a/kernel/sched_spa_ws.c b/kernel/sched_spa_ws.c index b0ef431..b399530 100644 --- a/kernel/sched_spa_ws.c +++ b/kernel/sched_spa_ws.c @@ -329,4 +329,5 @@ #ifdef CONFIG_MAGIC_SYSRQ .normalize_rt_task = spa_normalize_rt_task, #endif .attrs = spa_ws_attrs, + .activate_task = spa_activate_task }; diff --git a/kernel/sched_zaphod.c b/kernel/sched_zaphod.c index 4573dd7..0e530b3 100644 --- a/kernel/sched_zaphod.c +++ b/kernel/sched_zaphod.c @@ -588,4 +588,5 @@ #ifdef CONFIG_MAGIC_SYSRQ .normalize_rt_task = spa_normalize_rt_task, #endif .attrs = zaphod_attrs, + .activate_task = spa_activate_task, }; diff --git a/kernel/staircase.c b/kernel/staircase.c index 8f79378..2f13d31 100644 --- a/kernel/staircase.c +++ b/kernel/staircase.c @@ -19,7 +19,7 @@ #include */ #define SF_NONSLEEP 0x00000001 /* Waiting on in kernel activity */ -static void staircase_init_runqueue_queue(union runqueue_queue *qup) +static void staircase_init_runqueue_queue(struct runqueue_queue *qup) { int k; @@ -107,6 +107,13 @@ static inline void dequeue_task(struct t __clear_bit(p->prio, rqq->bitmap); sp->ns_debit = 0; } +/* + * Wrapper for pre pull task dequeue + */ +static inline void staircase_dequeue_task_rq(struct task_struct *p, runqueue_t *rq) +{ + //staircase_dequeue_task(p,&(rq->qu.staircase)); +} static void enqueue_task(struct task_struct *p, struct staircase_runqueue_queue *rqq) @@ -365,12 +372,12 @@ static inline void recalc_task_prio(stru } /* - * activate_task - move a task to the runqueue and do priority recalculation + * staircase_activate_task - move a task to the runqueue and do priority recalculation * * Update all the scheduling statistics stuff. (sleep average * calculation, priority modifiers, etc.) */ -static void activate_task(struct task_struct *p, struct rq *rq, const int local) +static void staircase_activate_task(struct task_struct *p, struct rq *rq, const int local) { struct staircase_sched_drv_task *sp = &p->sdu.staircase; unsigned long long now = sched_clock(); @@ -397,9 +404,9 @@ #endif } /* - * deactivate_task - remove a task from the runqueue. + * staircase_deactivate_task - remove a task from the runqueue. */ -static void fastcall deactivate_task(struct task_struct *p, struct rq *rq) +static void fastcall staircase_deactivate_task(struct task_struct *p, struct rq *rq) { dec_nr_running(p, rq); dequeue_task(p, &rq->qu.staircase); @@ -453,7 +460,7 @@ static void staircase_wake_up_task(struc * the waker guarantees that the freshly woken up task is going * to be considered on this CPU.) */ - activate_task(p, rq, same_cpu); + staircase_activate_task(p, rq, same_cpu); if (!sync || !same_cpu) preempt(p, rq); } @@ -492,7 +499,7 @@ static void staircase_wake_up_new_task(s scurr->sflags |= SF_NONSLEEP; if (likely(cpu == this_cpu)) { - activate_task(p, rq, 1); + staircase_activate_task(p, rq, 1); if (!(clone_flags & CLONE_VM)) { /* * The VM isn't cloned, so we're in a good position to @@ -517,7 +524,7 @@ static void staircase_wake_up_new_task(s */ p->timestamp = (p->timestamp - this_rq->timestamp_last_tick) + rq->timestamp_last_tick; - activate_task(p, rq, 0); + staircase_activate_task(p, rq, 0); preempt(p, rq); /* @@ -546,8 +553,13 @@ #ifdef CONFIG_SMP static void pull_task(struct rq *src_rq, struct task_struct *p, struct rq *this_rq, const int this_cpu) { - dequeue_task(p, &src_rq->qu.staircase); + cpu_sched(task_cpu(p))->dequeue_task_rq(p,src_rq); dec_nr_running(p, src_rq); + if(task_sched(p) != sched_drvp) { + int nice = task_sched(p)->prio_to_nice(p); + p->static_prio = sched_drvp->nice_to_prio(nice); + p->prio = p->static_prio; + } set_task_cpu(p, this_cpu); inc_nr_running(p, this_rq); enqueue_task(p, &this_rq->qu.staircase); @@ -755,7 +767,6 @@ static void staircase_schedule(void) unsigned long long now = sched_clock(); unsigned long debit; struct list_head *queue; - spin_lock_irq(&rq->lock); prev->sdu.staircase.runtime = ns_diff(now, prev->timestamp); @@ -779,7 +790,7 @@ static void staircase_schedule(void) rq->nr_uninterruptible++; prev->sdu.staircase.sflags |= SF_NONSLEEP; } - deactivate_task(prev, rq); + staircase_deactivate_task(prev, rq); } } @@ -924,7 +935,7 @@ static void staircase_setscheduler(struc queued = task_is_queued(p); if (queued) - deactivate_task(p, rq); + staircase_deactivate_task(p, rq); oldprio = p->prio; __setscheduler(p, policy, prio); if (queued) { @@ -1004,9 +1015,9 @@ static void staircase_migrate_queued_tas */ p->timestamp = p->timestamp - rq_src->timestamp_last_tick + rq_dest->timestamp_last_tick; - deactivate_task(p, rq_src); - set_task_cpu(p, dest_cpu); - __activate_task(p, rq_dest); + task_sched(p)->deactivate_task(p, rq_src); + set_task_cpu(p, dest_cpu); + cpu_sched(dest_cpu)->activate_task(p, rq_dest, 0); preempt(p, rq_dest); } @@ -1020,7 +1031,7 @@ static void staircase_set_select_idle_fi static void staircase_set_select_idle_last(struct rq *rq) { - deactivate_task(rq->idle, rq); + staircase_deactivate_task(rq->idle, rq); rq->idle->static_prio = STAIRCASE_MAX_PRIO; __setscheduler(rq->idle, SCHED_NORMAL, 0); } @@ -1055,7 +1066,7 @@ static void staircase_normalize_rt_task( queued = task_is_queued(p); if (queued) - deactivate_task(p, rq); + staircase_deactivate_task(p, rq); __setscheduler(p, SCHED_NORMAL, 0); if (queued) { __activate_task(p, rq); @@ -1076,6 +1087,22 @@ static struct attribute *staircase_attrs }; #endif +int staircase_prio_to_nice(struct task_struct *p) +{ + return PRIO_TO_NICE(p->static_prio); +} + +int staircase_nice_to_prio(int nice) +{ + return NICE_TO_PRIO(nice); +} + +/* get the staircase array from rq - needed for pull_task */ +void* staircase_rqq_from_rq(struct rq *rq) +{ + return &((rq->qu).staircase); +} + const struct sched_drv staircase_sched_drv = { .name = "staircase", .idle_prio = STAIRCASE_MAX_PRIO, @@ -1121,4 +1148,10 @@ #endif #ifdef CONFIG_SYSFS .attrs = staircase_attrs, #endif + .activate_task = staircase_activate_task, + .deactivate_task = staircase_deactivate_task, + .prio_to_nice = staircase_prio_to_nice, + .nice_to_prio = staircase_nice_to_prio, + .dequeue_task_rq = (void*)staircase_dequeue_task_rq }; +