--- linux-2.2.10/kernel/sched.c Mon May 10 18:55:21 1999 +++ linux/kernel/sched.c Mon Aug 2 12:07:09 1999 @@ -124,6 +124,74 @@ #endif +//RL +extern unsigned long cpu_hz; // from linux/arch/i386/time.c +#define LAT_MAX_OVERRUNS 10 +#define LAT_MIN_LATENCY 5 // ms +#define LAT_MS_CYCLES (cpu_hz/ 1000) // (boot_cpu_data.loops_per_sec / 1000) +static int lat_overruns; +static unsigned long lat_PC[LAT_MAX_OVERRUNS]; +static cycles_t lat_start_cycle; + +static __inline__ void lat_start() +{ + if (lat_start_cycle == 0) + lat_start_cycle = get_cycles(); // could get 0, low prob. 1:2^32 ! + // unless no TSC then hight prob. 1:1 +} + +#define LatMinimum2(a) (a > 2 ? a : 2) +static __inline__ int lat_time() +{ + if (lat_start_cycle != 0) { + signed long diff = get_cycles() - lat_start_cycle; + return diff / LAT_MS_CYCLES; + } else if (lat_overruns >= LatMinimum2(LAT_MS_CYCLES * HZ / 1000)) { + // great for non TSC computers + // Note: min 2 since otherwice we could be (un)lucky to get a sample + // immediately after lat_start() + return lat_overruns * 1000 / HZ; + } else { + return 0; + } +} + +static __inline__ void lat_restart() +{ + lat_start_cycle = 0; + lat_overruns = 0; +} + +static __inline__ void lat_sample(struct pt_regs * regs) +{ + if (current->need_resched && + lat_overruns < LAT_MAX_OVERRUNS) { + lat_PC[lat_overruns++] = instruction_pointer(regs); + } +} + +static void lat_print(struct task_struct * prev) { + int overruns = lat_overruns; // sample... + int resched_time = lat_time(); + if (resched_time >= LAT_MIN_LATENCY) { + int ix; + + printk("Latency %3dms PID %5d PCs ", + resched_time, + prev->pid); + + for (ix = 0; ix < overruns; ix++) { +#if (BITS_PER_LONG == 32) + printk(" %08lX ", lat_PC[ix]); +#else + printk(" %016lx ", lat_PC[ix]); +#endif + } + + printk("%% %-8s\n", prev->comm); // keeping it last, for auto tools! + } +} + void scheduling_functions_start_here(void) { } /* @@ -306,6 +374,7 @@ send_now: target_cpu = target_tsk->processor; + lat_start(); //RL does not really handle SMP... target_tsk->need_resched = 1; spin_unlock_irqrestore(&runqueue_lock, flags); /* @@ -323,8 +392,11 @@ struct task_struct *tsk; tsk = cpu_curr(this_cpu); - if (preemption_goodness(tsk, p, this_cpu) > 0) + if (preemption_goodness(tsk, p, this_cpu) > 0) { + //RL + lat_start(); tsk->need_resched = 1; + } #endif } @@ -689,7 +761,10 @@ struct task_struct *prev, *next, *p; int this_cpu, c; - if (tq_scheduler) + //RL latency improvement, correct? + //RL skip if forced reschedule (a normal will arrive soon...) + if (!current->need_resched && + tq_scheduler) goto handle_tq_scheduler; tq_scheduler_back: @@ -729,7 +804,15 @@ del_from_runqueue(prev); case TASK_RUNNING: } + //RL processes are not switched yet, should this be moved + if (prev->need_resched) { + lat_print(prev); + } + prev->need_resched = 0; + //RL + lat_restart(); + repeat_schedule: @@ -778,13 +861,14 @@ * sched_data. */ sched_data->curr = next; + #ifdef __SMP__ next->has_cpu = 1; next->processor = this_cpu; #endif spin_unlock_irq(&runqueue_lock); - if (prev == next) + if (prev == next) //RL BUG? note: compare with next comment, strange! goto same_process; #ifdef __SMP__ @@ -1470,6 +1554,7 @@ p->counter -= ticks; if (p->counter < 0) { p->counter = 0; + lat_start(); p->need_resched = 1; } if (p->priority < DEF_PRIORITY) @@ -1534,6 +1619,8 @@ lost_ticks_system++; if (tq_timer) mark_bh(TQUEUE_BH); + + lat_sample(regs); } #ifndef __alpha__ @@ -1766,6 +1853,8 @@ if (p->next_run) move_first_runqueue(p); + //RL + lat_start(); current->need_resched = 1; out_unlock: @@ -1848,6 +1937,8 @@ spin_lock_irq(&runqueue_lock); if (current->policy == SCHED_OTHER) current->policy |= SCHED_YIELD; + //RL + lat_start(); current->need_resched = 1; move_last_runqueue(current); spin_unlock_irq(&runqueue_lock);