--- linux-2.4.1-pre10/kernel/sched.c Tue Jan 23 19:28:16 2001 +++ linux-akpm/kernel/sched.c Tue Jan 23 23:18:21 2001 @@ -33,6 +33,13 @@ extern void tqueue_bh(void); extern void immediate_bh(void); +#include +static struct { + unsigned long acc_time; + unsigned long n_times; + unsigned long long in; +} ____cacheline_aligned schedule_stats[NR_CPUS + 1]; + /* * scheduler variables */ @@ -505,7 +512,7 @@ * tasks can run. It can not be killed, and it cannot sleep. The 'state' * information in task[0] is never used. */ -asmlinkage void schedule(void) +static void __schedule(void) { struct schedule_data * sched_data; struct task_struct *prev, *next, *p; @@ -688,6 +695,88 @@ BUG(); return; } + +////////////////////// + +static unsigned long long dummy; +static unsigned long long calib; +static int done_calib; + +static void do_one(void) +{ + rdtscll(dummy); +} + +static void calibrate(void) +{ + unsigned long long in, out; + unsigned long flags; + int i; + + local_irq_save(flags); + rdtscll(in); + for (i = 0; i < 0x10000; i++) { + do_one(); + } + rdtscll(out); + local_irq_restore(flags); + calib = (out - in) >> 16; + done_calib = 1; +} + +asmlinkage void schedule(void) +{ + int cpu = smp_processor_id(); + unsigned long long out; + + if (!done_calib) + calibrate(); + + rdtscll(schedule_stats[cpu].in); + __schedule(); + rdtscll(out); + + schedule_stats[cpu].acc_time += out - schedule_stats[cpu].in - calib; + schedule_stats[cpu].n_times++; +} + +static atomic_t cpu_count; + +static void ss_dumper(void *dummy) +{ + int cpu = smp_processor_id(); + while (atomic_read(&cpu_count) != cpu) + ; + printk("CPU %d: %lu / %lu = %lu cycles/switch\n", + cpu, schedule_stats[cpu].acc_time, schedule_stats[cpu].n_times, + schedule_stats[cpu].acc_time / schedule_stats[cpu].n_times); + + schedule_stats[NR_CPUS].acc_time += schedule_stats[cpu].acc_time; + schedule_stats[NR_CPUS].n_times += schedule_stats[cpu].n_times; + + schedule_stats[cpu].acc_time = 0; + schedule_stats[cpu].n_times = 0; + atomic_inc(&cpu_count); + if (atomic_read(&cpu_count) == smp_num_cpus) { + printk("total: %lu / %lu = %lu cycles/switch\n", + schedule_stats[NR_CPUS].acc_time, schedule_stats[NR_CPUS].n_times, + schedule_stats[NR_CPUS].acc_time / schedule_stats[NR_CPUS].n_times); + } +} + +void dump_schedule_stats(void) +{ + schedule_stats[NR_CPUS].acc_time = 0; + schedule_stats[NR_CPUS].n_times = 0; + atomic_set(&cpu_count, 0); + printk("\n"); + smp_call_function(ss_dumper, 0, 0, 0); + ss_dumper(0); +} + + +////////////////////////// + static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode, int nr_exclusive, const int sync) --- linux-2.4.1-pre10/drivers/char/sysrq.c Tue Dec 12 19:24:17 2000 +++ linux-akpm/drivers/char/sysrq.c Tue Jan 23 22:35:34 2001 @@ -95,6 +95,9 @@ sysrq_power_off(); } break; + case 'q': + dump_schedule_stats(); + break; case 's': /* S -- emergency sync */ printk("Emergency Sync\n"); emergency_sync_scheduled = EMERG_SYNC;