Index: Linux-2.6.12/include/linux/sched_cpustats.h =================================================================== --- Linux-2.6.12.orig/include/linux/sched_cpustats.h 2005-08-15 11:09:09.000000000 +1000 +++ Linux-2.6.12/include/linux/sched_cpustats.h 2005-08-15 11:13:52.000000000 +1000 @@ -25,6 +25,7 @@ unsigned long long total_rt_intr_delay; unsigned long long total_fork_delay; unsigned long long total_sinbin; + unsigned long long total_latency; }; extern DEFINE_PER_CPU(struct runq_cpustats, cpustats_runqs); @@ -41,14 +42,18 @@ unsigned long long avg_cpu_per_cycle; unsigned long long total_delay; unsigned long long avg_delay_per_cycle; + unsigned long long total_latency; + unsigned long long avg_latency; unsigned long long total_sinbin; unsigned long long avg_cycle_length; unsigned long cpu_usage_rate; + unsigned long sleepiness; unsigned int flags; }; #define CPUSTATS_WOKEN_FOR_INTR_FL (1 << 0) -#define CPUSTATS_JUST_FORKED_FL (1 << 1) +#define CPUSTATS_JUST_WOKEN_FL (1 << 1) +#define CPUSTATS_JUST_FORKED_FL (1 << 2) #define INIT_CPUSTATS \ .cpustats = { 0, }, \ @@ -99,6 +104,7 @@ unsigned long long total_intr_delay; unsigned long long total_rt_intr_delay; unsigned long long total_fork_delay; + unsigned long long total_latency; unsigned long long total_sinbin; unsigned long long nr_switches; }; Index: Linux-2.6.12/kernel/sched_zaphod.c =================================================================== --- Linux-2.6.12.orig/kernel/sched_zaphod.c 2005-08-15 11:13:08.000000000 +1000 +++ Linux-2.6.12/kernel/sched_zaphod.c 2005-08-15 11:16:47.000000000 +1000 @@ -79,7 +79,7 @@ #define MAX_TOTAL_BONUS (BGND_PRIO - ZAPHOD_MAX_PRIO - 1) #define MAX_MAX_IA_BONUS ((MAX_TOTAL_BONUS + 1) / 2) #define MAX_MAX_TPT_BONUS (MAX_TOTAL_BONUS - MAX_MAX_IA_BONUS) -#define DEFAULT_MAX_IA_BONUS ((MAX_MAX_IA_BONUS < 7) ? MAX_MAX_IA_BONUS : 7) +#define DEFAULT_MAX_IA_BONUS ((MAX_MAX_IA_BONUS < 9) ? MAX_MAX_IA_BONUS : 9) #define DEFAULT_MAX_TPT_BONUS ((DEFAULT_MAX_IA_BONUS - 2) ? : 1) @@ -94,7 +94,7 @@ unsigned int max_ia_bonus = DEFAULT_MAX_IA_BONUS; unsigned int max_max_ia_bonus = MAX_MAX_IA_BONUS; -unsigned int initial_ia_bonus = 1; +unsigned int initial_ia_bonus = 5; unsigned int max_tpt_bonus = DEFAULT_MAX_TPT_BONUS; unsigned int max_max_tpt_bonus = MAX_MAX_TPT_BONUS; @@ -145,29 +145,11 @@ * provided that their average sleep duration per scheduling cycle isn't too * long */ -#define DEFAULT_IA_THRESHOLD 500 +#define DEFAULT_IA_THRESHOLD 900 unsigned long ia_threshold = PROP_FM_PPT(DEFAULT_IA_THRESHOLD); #define LOWER_MAX_IA_SLEEP SCHED_AVG_REAL(15 * 60LL * NSEC_PER_SEC) #define UPPER_MAX_IA_SLEEP SCHED_AVG_REAL(2 * 60 * 60LL * NSEC_PER_SEC) -/* - * Calculate CPU usage rate and sleepiness. - * This never gets called on real time tasks - */ -static unsigned long calc_sleepiness(task_t *p) -{ - unsigned long long bl; - - bl = TASK_CPUSTATS(p).avg_sleep_per_cycle + TASK_CPUSTATS(p).avg_cpu_per_cycle; - /* - * Take a shortcut and avoid possible divide by zero - */ - if (unlikely(bl == 0)) - return PROPORTION_ONE; - else - return calc_proportion(TASK_CPUSTATS(p).avg_sleep_per_cycle, bl); -} - static inline void decay_sched_ia_bonus(struct task_struct *p) { TASK_ZD(p).interactive_bonus *= SCHED_IA_BONUS_ALPHA; @@ -185,14 +167,16 @@ TASK_ZD(p).interactive_bonus = 0; return; } - /* - * No point going any further if there's no bonus to lose - */ - if (TASK_ZD(p).interactive_bonus == 0) - return; if (TASK_CPUSTATS(p).cpu_usage_rate > cpu_hog_threshold) decay_sched_ia_bonus(p); + else { + if (TASK_CPUSTATS(p).sleepiness < (PROPORTION_ONE - cpu_hog_threshold)) { + decay_sched_ia_bonus(p); + TASK_ZD(p).interactive_bonus += map_proportion_rnd(TASK_CPUSTATS(p).sleepiness, + max_ia_bonus); + } + } } /* @@ -202,8 +186,6 @@ */ static void reassess_interactiveness(task_t *p) { - unsigned long sleepiness; - if (max_ia_bonus == 0) { TASK_ZD(p).interactive_bonus = 0; return; @@ -220,10 +202,9 @@ return; } - sleepiness = calc_sleepiness(p); - if (sleepiness > ia_threshold) { + if (TASK_CPUSTATS(p).sleepiness > ia_threshold) { decay_sched_ia_bonus(p); - TASK_ZD(p).interactive_bonus += map_proportion_rnd(sleepiness, max_ia_bonus); + TASK_ZD(p).interactive_bonus += max_ia_bonus; } } @@ -388,6 +369,7 @@ { TASK_ZD(p).interactive_bonus = (max_ia_bonus >= initial_ia_bonus) ? initial_ia_bonus : max_ia_bonus; + TASK_ZD(p).interactive_bonus <<= SCHED_IA_BONUS_OFFSET; TASK_ZD(p).throughput_bonus = 0; } Index: Linux-2.6.12/kernel/sched_cpustats.c =================================================================== --- Linux-2.6.12.orig/kernel/sched_cpustats.c 2005-08-15 11:09:09.000000000 +1000 +++ Linux-2.6.12/kernel/sched_cpustats.c 2005-08-15 12:14:21.000000000 +1000 @@ -38,6 +38,7 @@ csrq->total_intr_delay = 0; csrq->total_rt_intr_delay = 0; csrq->total_fork_delay = 0; + csrq->total_latency = 0; cpu_rq(cpu)->timestamp_last_tick = INITIAL_CPUSTATS_TIMESTAMP; } @@ -53,12 +54,14 @@ TASK_CPUSTATS(p).avg_sleep_per_cycle = 0; TASK_CPUSTATS(p).avg_delay_per_cycle = 0; TASK_CPUSTATS(p).avg_cpu_per_cycle = 0; + TASK_CPUSTATS(p).avg_latency = 0; TASK_CPUSTATS(p).total_sleep = 0; TASK_CPUSTATS(p).total_delay = 0; TASK_CPUSTATS(p).total_sinbin = 0; TASK_CPUSTATS(p).total_cpu = 0; TASK_CPUSTATS(p).total_wake_ups = 0; TASK_CPUSTATS(p).intr_wake_ups = 0; + TASK_CPUSTATS(p).total_latency = 0; TASK_CPUSTATS(p).avg_cycle_length = 0; p->timestamp = now; TASK_CPUSTATS(p).flags = CPUSTATS_JUST_FORKED_FL; @@ -119,17 +122,26 @@ if (TASK_CPUSTATS(p).flags & CPUSTATS_WOKEN_FOR_INTR_FL) rq_stats->total_rt_intr_delay += delta; } - if (unlikely(TASK_CPUSTATS(p).flags & CPUSTATS_JUST_FORKED_FL)) { - rq_stats->total_fork_delay += delta; - TASK_CPUSTATS(p).flags &= ~CPUSTATS_JUST_FORKED_FL; - } - if (TASK_CPUSTATS(p).flags & CPUSTATS_WOKEN_FOR_INTR_FL) { - rq_stats->total_intr_delay += delta; - TASK_CPUSTATS(p).flags &= ~CPUSTATS_WOKEN_FOR_INTR_FL; + if (TASK_CPUSTATS(p).flags & CPUSTATS_JUST_WOKEN_FL) { + rq_stats->total_latency += delta; + TASK_CPUSTATS(p).total_latency += delta; + if (likely(TASK_CPUSTATS(p).total_wake_ups > 1)) + TASK_CPUSTATS(p).avg_latency += delta; + else + TASK_CPUSTATS(p).avg_latency = SCHED_AVG_REAL(delta); + if (TASK_CPUSTATS(p).flags & CPUSTATS_WOKEN_FOR_INTR_FL) + rq_stats->total_intr_delay += delta; + TASK_CPUSTATS(p).flags &= + ~(CPUSTATS_WOKEN_FOR_INTR_FL|CPUSTATS_JUST_WOKEN_FL); } } #define SCHED_AVG_ALPHA ((1 << SCHED_AVG_OFFSET) - 1) +static inline void sched_avg_first_sample(unsigned long long *valp) +{ + *valp <<= SCHED_AVG_OFFSET; +} + static inline void apply_sched_avg_decay(unsigned long long *valp) { *valp *= SCHED_AVG_ALPHA; @@ -138,22 +150,44 @@ static inline void decay_cpustats_for_cycle(struct task_struct *p) { - apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_sleep_per_cycle); - apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_delay_per_cycle); - apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_cpu_per_cycle); + if (unlikely(TASK_CPUSTATS(p).flags & CPUSTATS_JUST_FORKED_FL)) { + struct runq_cpustats *rq_stats = &per_cpu(cpustats_runqs, task_cpu(p)); + + rq_stats->total_fork_delay += TASK_CPUSTATS(p).total_delay; + /* set the average to be equal to the first sample */ + sched_avg_first_sample(&TASK_CPUSTATS(p).avg_sleep_per_cycle); + sched_avg_first_sample(&TASK_CPUSTATS(p).avg_delay_per_cycle); + sched_avg_first_sample(&TASK_CPUSTATS(p).avg_cpu_per_cycle); + TASK_CPUSTATS(p).flags &= ~CPUSTATS_JUST_FORKED_FL; + } + else { + apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_sleep_per_cycle); + apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_delay_per_cycle); + apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_cpu_per_cycle); + } + /* sleepiness is an estimate of the the tasks sleep rate if it suffered no delays */ TASK_CPUSTATS(p).avg_cycle_length = TASK_CPUSTATS(p).avg_sleep_per_cycle + - TASK_CPUSTATS(p).avg_delay_per_cycle + TASK_CPUSTATS(p).avg_cpu_per_cycle; /* take short cut and avoid possible divide by zero below */ + if (TASK_CPUSTATS(p).avg_sleep_per_cycle == 0) + TASK_CPUSTATS(p).sleepiness = 0; + else + TASK_CPUSTATS(p).sleepiness = calc_proportion(TASK_CPUSTATS(p).avg_sleep_per_cycle, + TASK_CPUSTATS(p).avg_cycle_length); + TASK_CPUSTATS(p).avg_cycle_length += TASK_CPUSTATS(p).avg_delay_per_cycle; + /* take short cut and avoid possible divide by zero below */ if (TASK_CPUSTATS(p).avg_cpu_per_cycle == 0) TASK_CPUSTATS(p).cpu_usage_rate = 0; else - TASK_CPUSTATS(p).cpu_usage_rate = calc_proportion(TASK_CPUSTATS(p).avg_cpu_per_cycle, TASK_CPUSTATS(p).avg_cycle_length); + TASK_CPUSTATS(p).cpu_usage_rate = calc_proportion(TASK_CPUSTATS(p).avg_cpu_per_cycle, + TASK_CPUSTATS(p).avg_cycle_length); } void update_cpustats_at_wake_up(struct task_struct *p, unsigned long long now) { delta_sleep_cpustats(p, now); + apply_sched_avg_decay(&TASK_CPUSTATS(p).avg_latency); + TASK_CPUSTATS(p).flags |= CPUSTATS_JUST_WOKEN_FL; if (in_interrupt()) { TASK_CPUSTATS(p).intr_wake_ups++; TASK_CPUSTATS(p).flags |= CPUSTATS_WOKEN_FOR_INTR_FL; @@ -183,13 +217,15 @@ if (result) return sprintf(buffer, "Data unavailable\n"); return sprintf(buffer, - "%llu (%llu) %llu (%llu) %llu (%llu) %llu %llu %llu %lu %lu @ %llu\n", + "%llu (%llu) %llu (%llu) %llu (%llu) %llu (%llu) %llu %llu %llu %lu %lu @ %llu\n", stats.total_sleep, SCHED_AVG_RND(stats.avg_sleep_per_cycle), stats.total_cpu, SCHED_AVG_RND(stats.avg_cpu_per_cycle), stats.total_delay, SCHED_AVG_RND(stats.avg_delay_per_cycle), + stats.total_latency, + SCHED_AVG_RND(stats.avg_latency), stats.total_sinbin, stats.total_wake_ups, stats.intr_wake_ups, @@ -214,13 +250,14 @@ break; } len += sprintf(page + len, - "cpu%02d %llu %llu %llu %llu %llu %llu %llu %llu @ %llu\n", i, + "cpu%02d %llu %llu %llu %llu %llu %llu %llu %llu %llu @ %llu\n", i, stats.total_idle, stats.total_busy, stats.total_delay, stats.total_rt_delay, stats.total_intr_delay, stats.total_rt_intr_delay, + stats.total_latency, stats.total_sinbin, stats.nr_switches, stats.timestamp); @@ -230,17 +267,19 @@ total.total_rt_delay += stats.total_rt_delay; total.total_intr_delay += stats.total_intr_delay; total.total_rt_intr_delay += stats.total_rt_intr_delay; + total.total_latency += stats.total_latency; total.total_sinbin += stats.total_sinbin; total.nr_switches += stats.nr_switches; } if (avail) - len += sprintf(page + len, "total %llu %llu %llu %llu %llu %llu %llu %llu\n", + len += sprintf(page + len, "total %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", total.total_idle, total.total_busy, total.total_delay, total.total_intr_delay, total.total_rt_delay, total.total_rt_intr_delay, + total.total_latency, total.total_sinbin, total.nr_switches); else Index: Linux-2.6.12/kernel/sched_spa.c =================================================================== --- Linux-2.6.12.orig/kernel/sched_spa.c 2005-08-15 11:13:08.000000000 +1000 +++ Linux-2.6.12/kernel/sched_spa.c 2005-08-15 11:28:21.000000000 +1000 @@ -77,9 +77,9 @@ * 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 DEF_DESKTOP_TIMESLICE ((10 * HZ / 1000) ? (10 * HZ / 1000) : MIN_TIMESLICE) +#define DEF_TIMESLICE ((100 * HZ / 1000) ? : MIN_TIMESLICE) +#define MAX_TIMESLICE ((1000 * HZ / 1000) ? : MIN_TIMESLICE) +#define DEF_DESKTOP_TIMESLICE ((60 * HZ / 1000) ? : MIN_TIMESLICE) static unsigned long time_slice = DEF_TIMESLICE; static unsigned long sched_rr_time_slice = DEF_TIMESLICE; @@ -376,13 +376,7 @@ */ static inline void preempt_if_warranted(task_t *p, struct runqueue *rq) { - if (TASK_PREEMPTS_CURR(p, rq)) { - resched_task(rq->curr); - return; - } - - if ((p->prio == rq->curr->prio) && (p->sdu.spa.cpustats.flags & CPUSTATS_WOKEN_FOR_INTR_FL) - && !(rq->curr->sdu.spa.cpustats.flags & CPUSTATS_WOKEN_FOR_INTR_FL)) + if (TASK_PREEMPTS_CURR(p, rq)) resched_task(rq->curr); } @@ -522,9 +516,10 @@ return; get_task_cpustats(p, &stats, ×tamp); - printk("SCHED_EXIT[%d] (%s) %llu %llu %llu %llu %llu %llu %lu %lu @ %llu\n", + printk("SCHED_EXIT[%d] (%s) %llu %llu %llu %llu %llu %llu %llu %lu %lu @ %llu\n", p->pid, p->comm, stats.total_sleep, stats.total_cpu, stats.total_delay, + stats.total_latency, stats.total_sinbin, stats.total_wake_ups, stats.intr_wake_ups, p->nvcsw, p->nivcsw, timestamp); } @@ -1153,6 +1148,10 @@ stats->avg_delay_per_cycle += delta; if (is_sinbinned) stats->total_sinbin += delta; + if (stats->flags & CPUSTATS_JUST_WOKEN_FL) { + stats->total_latency += delta; + stats->avg_latency += delta; + } } else { stats->total_sleep += delta; stats->avg_sleep_per_cycle += delta; @@ -1206,6 +1205,7 @@ stats->total_rt_intr_delay = csrq->total_rt_intr_delay; stats->total_fork_delay = csrq->total_fork_delay; stats->total_sinbin = csrq->total_sinbin; + stats->total_latency = csrq->total_latency; stats->nr_switches = rq->nr_switches; spin_unlock_irq(&rq->lock); @@ -1436,10 +1436,11 @@ total.total_rt_intr_delay += stats.total_rt_intr_delay; total.total_fork_delay += stats.total_fork_delay; total.total_sinbin += stats.total_sinbin; + total.total_latency += stats.total_latency; total.nr_switches += stats.nr_switches; } if (avail) - len = sprintf(page, "%llu %llu %llu %llu %llu %llu %llu %llu %llu @ %llu\n", + len = sprintf(page, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu @ %llu\n", total.total_idle, total.total_busy, total.total_delay, @@ -1447,6 +1448,7 @@ total.total_rt_delay, total.total_rt_intr_delay, total.total_fork_delay, + total.total_latency, total.total_sinbin, total.nr_switches, timestamp);