- Made fixes suggested by Peter Williams such as: - Fixed up zaphod table gene_param table. - Made base_prom_interval be a ratio of time_slice. - Fitness routine uses total_delay. --- diff -puN include/linux/sched.h~genetic-zaphod-cpu-sched include/linux/sched.h --- linux-2.6.10/include/linux/sched.h~genetic-zaphod-cpu-sched Mon Jan 10 15:40:22 2005 +++ linux-2.6.10-moilanen/include/linux/sched.h Mon Jan 10 15:40:22 2005 @@ -139,6 +139,19 @@ struct sched_param { #include /* + * These are the 'tuning knobs' of the scheduler: + * + * Default configurable timeslice is 100 msecs, maximum configurable + * timeslice is 1000 msecs and minumum configurable timeslice is 1 jiffy. + * Timeslices get renewed on task creation, on wake up and after they expire. + */ +#define MIN_TIMESLICE 1 +#define DEF_TIMESLICE (100 * HZ / 1000) +#define MAX_TIMESLICE (1000 * HZ / 1000) + +#define DEFAULT_UNPRIV_RT_THRESHOLD 10 + +/* * This serializes "schedule()" and also protects * the run-queue from deletions/modifications (but * _adding_ to the beginning of the run-queue has @@ -394,6 +407,13 @@ struct sched_info { /* timestamps */ unsigned long last_arrival, /* when we last ran on a cpu */ last_queued; /* when we were last queued to run */ + +#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED + unsigned long cpu_time_snapshot; + unsigned long run_delay_snapshot; + unsigned long pcnt_snapshot; + unsigned long total_delay_snapshot; +#endif }; extern struct file_operations proc_schedstat_operations; @@ -766,6 +786,8 @@ extern int task_nice(const task_t *p); extern int task_curr(const task_t *p); extern int idle_cpu(int cpu); +extern void genetic_cpu_sched_init(void); + void yield(void); /* @@ -1137,8 +1159,35 @@ static inline void arch_pick_mmap_layout } #endif +enum zaphod_mode_enum { + ZAPHOD_MODE_PRIORITY_BASED, + ZAPHOD_MODE_ENTITLEMENT_BASED +}; + +#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED extern long sched_setaffinity(pid_t pid, cpumask_t new_mask); extern long sched_getaffinity(pid_t pid, cpumask_t *mask); + + +#define ZAPHOD_SCHED_NUM_GENES 9 +#define ZAPHOD_SCHED_NUM_CHILDREN 8 +//#define ZAPHOD_SCHED_CHILD_LIFESPAN (9 * (HZ / 2)) +#define ZAPHOD_SCHED_CHILD_LIFESPAN (4 * HZ) + +struct zaphod_sched_genes { + unsigned long time_slice; + unsigned long sched_rr_time_slice; +// unsigned long base_prom_interval; + unsigned long max_ia_bonus; + unsigned long initial_ia_bonus; + unsigned long ia_threshold; + unsigned long cpu_hog_threshold; + unsigned long max_tpt_bonus; +// unsigned long unpriv_rt_threshold; + unsigned long bgnd_time_slice_multiplier; + unsigned long zaphod_mode; +}; +#endif /* CONFIG_GENETIC_ZAPHOD_CPU_SCHED */ #ifdef CONFIG_MAGIC_SYSRQ diff -puN kernel/sched.c~genetic-zaphod-cpu-sched kernel/sched.c --- linux-2.6.10/kernel/sched.c~genetic-zaphod-cpu-sched Mon Jan 10 15:40:22 2005 +++ linux-2.6.10-moilanen/kernel/sched.c Mon Jan 10 15:46:52 2005 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -58,25 +59,13 @@ #define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio) /* - * These are the 'tuning knobs' of the scheduler: - * - * Default configurable timeslice is 100 msecs, maximum configurable - * timeslice is 1000 msecs and minumum configurable timeslice is 1 jiffy. - * Timeslices get renewed on task creation, on wake up and after they expire. - */ -#define MIN_TIMESLICE 1 -#define DEF_TIMESLICE (100 * HZ / 1000) -#define MAX_TIMESLICE (1000 * HZ / 1000) - -/* * UNPRIV_RT tasks that have a CPU usage rate less than this threshold * (in parts per thousand) are treated as psuedo RT tasks */ -#define DEFAULT_UNPRIV_RT_THRESHOLD 10 unsigned long unpriv_rt_threshold = PROP_FM_PPT(DEFAULT_UNPRIV_RT_THRESHOLD); unsigned long time_slice = DEF_TIMESLICE; -static unsigned long sched_rr_time_slice = (100 * HZ / 1000); +unsigned long sched_rr_time_slice = (100 * HZ / 1000); /* * Background tasks may have longer time slices as compensation @@ -115,6 +104,11 @@ struct prio_slot { struct list_head queue; }; +#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) +#define this_rq() (&__get_cpu_var(runqueues)) +#define task_rq(p) ((p)->rq) +#define cpu_curr(cpu) (cpu_rq(cpu)->curr) + /* * This is the main, per-CPU runqueue data structure. * @@ -210,11 +204,6 @@ static DEFINE_PER_CPU(struct runqueue, r #define for_each_domain(cpu, domain) \ for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent) -#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) -#define this_rq() (&__get_cpu_var(runqueues)) -#define task_rq(p) ((p)->rq) -#define cpu_curr(cpu) (cpu_rq(cpu)->curr) - #ifdef CONFIG_SMP void fastcall set_task_cpu(struct task_struct *p, unsigned int cpu) { @@ -1210,7 +1199,7 @@ void fastcall wake_up_new_task(task_t * * No more timeslice fiddling on exit * (Optionally) log scheduler statistics at exit. */ -static int log_at_exit = 0; +int log_at_exit = 0; void fastcall sched_exit(task_t * p) { struct task_cpustats stats; @@ -4771,3 +4760,93 @@ ctl_table cpu_sched_table[] = { { .ctl_name = CPU_SCHED_END_OF_LIST } }; #endif + +#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED + +extern unsigned int max_ia_bonus; +extern unsigned long ia_threshold; +extern unsigned long cpu_hog_threshold; +extern unsigned int initial_ia_bonus; +extern unsigned int max_tpt_bonus; +extern enum zaphod_mode_enum zaphod_mode; + +void zaphod_sched_set_child_genes(void * in_genes) +{ + struct zaphod_sched_genes * genes = (struct zaphod_sched_genes *)in_genes; + int cpu; + runqueue_t * rq; +// struct runq_cpustats *csrq; + + time_slice = genes->time_slice; + /* maintain same ratio between time_slice and bpi */ + base_prom_interval = ((time_slice * 15) / 10); + + sched_rr_time_slice = genes->sched_rr_time_slice; +// base_prom_interval = genes->base_prom_interval; + max_ia_bonus = genes->max_ia_bonus; + initial_ia_bonus = genes->initial_ia_bonus; + ia_threshold = ppt_to_proportion(genes->ia_threshold); + cpu_hog_threshold = ppt_to_proportion(genes->cpu_hog_threshold); + max_tpt_bonus = genes->max_tpt_bonus; +// unpriv_rt_threshold = ppt_to_proportion(genes->unpriv_rt_threshold); + bgnd_time_slice_multiplier = genes->bgnd_time_slice_multiplier; + zaphod_mode = genes->zaphod_mode; + +#if 0 + /* Get snapshot for this child */ + for_each_online_cpu(cpu) { + csrq = cpu_runq_cpustats(cpu); + + csrq->total_delay_snapshot = csrq->total_delay; + } +#endif + +#if 1 + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); + + rq->rq_sched_info.cpu_time_snapshot = rq->rq_sched_info.cpu_time; + rq->rq_sched_info.run_delay_snapshot = rq->rq_sched_info.run_delay; + rq->rq_sched_info.pcnt_snapshot = rq->rq_sched_info.pcnt; + } +#endif +} + +void zaphod_sched_calc_fitness(genetic_child_t * child) +{ + int cpu; + +#if 1 + runqueue_t * rq; + long cpu_time = 0; + long run_delay = 0; + long pcnt = 0; + + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); + + cpu_time += rq->rq_sched_info.cpu_time - rq->rq_sched_info.cpu_time_snapshot; + run_delay += rq->rq_sched_info.run_delay - rq->rq_sched_info.run_delay_snapshot; + pcnt += rq->rq_sched_info.pcnt - rq->rq_sched_info.pcnt_snapshot; + } + + child->fitness = cpu_time - run_delay; +#endif + +#if 0 + struct runq_cpustats *csrq; + long total_delay = 0; + + for_each_online_cpu(cpu) { + csrq = cpu_runq_cpustats(cpu); + + total_delay -= csrq->total_delay - csrq->total_delay_snapshot; + } + + + child->fitness = total_delay; +#endif +} + +#endif /* CONFIG_GENETIC_ZAPHOD_CPU_SCHED */ + diff -puN kernel/sched_zaphod.c~genetic-zaphod-cpu-sched kernel/sched_zaphod.c --- linux-2.6.10/kernel/sched_zaphod.c~genetic-zaphod-cpu-sched Mon Jan 10 15:40:22 2005 +++ linux-2.6.10-moilanen/kernel/sched_zaphod.c Mon Jan 10 15:40:22 2005 @@ -21,9 +21,13 @@ */ #include #include +#include +#include #include +enum zaphod_mode_enum zaphod_mode = ZAPHOD_MODE_PRIORITY_BASED; + #ifdef CONFIG_CPUSCHED_ZAPHOD #define MAX_PRIO ZAPHOD_MAX_PRIO #define MIN_NORMAL_PRIO ZAPHOD_MIN_NORMAL_PRIO @@ -42,13 +46,6 @@ #define EB_YARDSTICK_DECAY_INTERVAL 100 -enum zaphod_mode_enum { - ZAPHOD_MODE_PRIORITY_BASED, - ZAPHOD_MODE_ENTITLEMENT_BASED -}; - -static enum zaphod_mode_enum zaphod_mode = ZAPHOD_MODE_PRIORITY_BASED; - #ifdef CONFIG_SYSCTL static const char *zaphod_mode_names[] = { "pb", /* ZAPHOD_MODE_PRIORITY_BASED */ @@ -445,6 +442,83 @@ void zaphod_reassess_at_renice(struct ta if (!rt_task(p)) calculate_pre_bonus_priority(p); } + +#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED + +extern unsigned long sched_rr_time_slice; +extern unsigned long base_prom_interval; +static void zaphod_sched_create_child(genetic_child_t *); +static void genetic_mutate_proportion(genetic_child_t *, unsigned long); +void zaphod_sched_set_child_genes(void *); +void zaphod_sched_calc_fitness(genetic_child_t *); + +struct genetic_ops zaphod_sched_genetic_ops = { + .create_child = zaphod_sched_create_child, + .set_child_genes = zaphod_sched_set_child_genes, + .calc_fitness = zaphod_sched_calc_fitness, + .combine_genes = genetic_generic_combine_genes, + .mutate_child = genetic_generic_mutate_child, +}; + +/* Each gene and their attributes */ +gene_param_t zaphod_sched_gene_param[ZAPHOD_SCHED_NUM_GENES] = { + { MIN_TIMESLICE, MAX_TIMESLICE, DEF_TIMESLICE, 0 }, /* time_slice */ + { MIN_TIMESLICE, MAX_TIMESLICE, (100 * HZ / 1000), 0 }, /* sched_rr_time_slice */ +// { MIN_TIMESLICE, MAX_TIMESLICE, ((DEF_TIMESLICE * 15) / 10), 0 }, /* base_prom_interval */ + { 0, MAX_MAX_IA_BONUS, DEFAULT_MAX_IA_BONUS, 0 }, /* max_ia_bonus */ + { 0, MAX_MAX_IA_BONUS, 1, 0 }, /* initial_ia_bonus */ + { 0, 1000, DEFAULT_IA_THRESHOLD, 0 }, /* ia_threshold */ + { 0, 1000, DEFAULT_CPU_HOG_THRESHOLD, 0 }, /* cpu_hog_threshold */ + { 0, MAX_MAX_TPT_BONUS, DEFAULT_MAX_TPT_BONUS, 0 }, /* max_tpt_bonus */ +// { 1, 1000, DEFAULT_UNPRIV_RT_THRESHOLD, 0 }, /* unpriv_rt_threshold */ + { 1, 100, 1, 0 }, /* bgnd_time_slice_multiplier */ + { 0, 1, 0, 0 }, /* zaphod_mode */ +}; + +void __init genetic_cpu_sched_init() +{ + if(genetic_init(0, &zaphod_sched_genetic_ops, ZAPHOD_SCHED_NUM_CHILDREN, + ZAPHOD_SCHED_CHILD_LIFESPAN, "zaphod-sched", ZAPHOD_SCHED_NUM_GENES)) + panic("zaphod sched: failed to init genetic lib"); +} + +void zaphod_sched_create_child(genetic_child_t * child) +{ + int i; + static int child_num = 0; + unsigned long range; + int range_incr; + unsigned long * genes; + + BUG_ON(!child); + + child->genes = (void *)kmalloc(sizeof(struct zaphod_sched_genes), GFP_KERNEL); + if (!child->genes) + panic("zaphod_sched_create_child: error kmalloc'n space"); + + child->gene_param = zaphod_sched_gene_param; + + genes = (unsigned long *)child->genes; + + for (i = 0; i < ZAPHOD_SCHED_NUM_GENES; i++) { + range = child->gene_param[i].max - child->gene_param[i].min + 1; + range_incr = range / ZAPHOD_SCHED_NUM_CHILDREN; + if (range_incr) + genes[i] = child->gene_param[i].min + + (range_incr * child_num); + else + genes[i] = child->gene_param[i].min + + (child_num / (ZAPHOD_SCHED_NUM_CHILDREN / range)); + } + + child->num_genes = ZAPHOD_SCHED_NUM_GENES; + + child_num++; +} + +core_initcall(genetic_cpu_sched_init); + +#endif /* CONFIG_GENETIC_ZAPHOD_CPU_SCHED */ #if defined(CONFIG_SYSCTL) static const unsigned int zero = 0; diff -puN lib/Kconfig~genetic-zaphod-cpu-sched lib/Kconfig --- linux-2.6.10/lib/Kconfig~genetic-zaphod-cpu-sched Mon Jan 10 15:40:22 2005 +++ linux-2.6.10-moilanen/lib/Kconfig Mon Jan 10 15:47:12 2005 @@ -36,6 +36,13 @@ config GENETIC_LIB This option will build in a genetic library that will tweak kernel parameters autonomically to improve performance. +config GENETIC_ZAPHOD_CPU_SCHED + bool "Genetic Library - Zaphod CPU scheduler" + depends on GENETIC_LIB && EXPERIMENTAL && SCHEDSTATS + help + This option will enable the genetic library on the zaphod + CPU scheduler. + # # compression support is select'ed if needed # diff -puN include/linux/sched_cpustats.h~genetic-zaphod-cpu-sched include/linux/sched_cpustats.h --- linux-2.6.10/include/linux/sched_cpustats.h~genetic-zaphod-cpu-sched Mon Jan 10 15:40:22 2005 +++ linux-2.6.10-moilanen/include/linux/sched_cpustats.h Mon Jan 10 15:40:22 2005 @@ -24,6 +24,9 @@ struct runq_cpustats { #endif unsigned long long total_delay; unsigned long long total_sinbin; +#ifdef CONFIG_GENETIC_ZAPHOD_CPU_SCHED + unsigned long long total_delay_snapshot; +#endif }; /* _