diff -aurpN -X /home/fletch/.diff.exclude 272-config_irqbal/arch/i386/kernel/.io_apic.c.swp 274-percpu_real_loadavg/arch/i386/kernel/.io_apic.c.swp --- 272-config_irqbal/arch/i386/kernel/.io_apic.c.swp Wed Dec 31 16:00:00 1969 +++ 274-percpu_real_loadavg/arch/i386/kernel/.io_apic.c.swp Thu Jan 1 23:22:19 2004 @@ -0,0 +1,15 @@ +b0VIM 6.1?Tfletchtitus~fletch/linux/views/2.6.1-rc1-mjb1/272-config_irqbal/arch/i386/kernel/io_apic.c3210#"! Utp!}w#5yg~mxpg}q% ad#w=d$ ` 2 . -   c D (   p o U T   + + + + + + + +k +j +g +, + + + { x @ & " !  ^!d$ jGF- trqnHD O5VUI5!wv break; if (!entry->next) io_apic_modify(entry->apic, 0x10 + pin*2, reg |= 0x00010000); reg = io_apic_read(entry->apic, 0x10 + pin*2); break; if (pin == -1) pin = entry->pin; unsigned int reg; for (;;) { struct irq_pin_list *entry = irq_2_pin + irq; int pin;{static void __mask_IO_APIC_irq (unsigned int irq)/* mask = 1 */} } entry = irq_2_pin + entry->next; break; if (!entry->next) } entry->pin = newpin; entry->apic = newapic; if (entry->apic == oldapic && entry->pin == oldpin) { while (1) { struct irq_pin_list *entry = irq_2_pin + irq;{ int newapic, int newpin) int oldapic, int oldpin,static void __init replace_pin_at_irq(unsigned int irq, */ * Reroute an IRQ to a different pin./*} entry->pin = pin; entry->apic = apic; } panic("io_apic.c: whoops"); if (++first_free_entry >= PIN_MAP_SIZE) entry = irq_2_pin + entry->next; entry->next = first_free_entry; if (entry->pin != -1) { entry = irq_2_pin + entry->next; while (entry->next) struct irq_pin_list *entry = irq_2_pin + irq; static int first_free_entry = NR_IRQS;{static void __init add_pin_to_irq(unsigned int irq, int apic, int pin) */ * fast in the common case, and fast for shared ISA-space IRQs. * shared ISA-space IRQs, so we have to support them. We are super * The common case is 1:1 IRQ<->pin mappings. Sometimes there are/*#endif#define vector_to_irq(vector) (vector)#else (platform_legacy_irq(vector) ? vector : vector_irq[vector])#define vector_to_irq(vector) \int vector_irq[NR_IRQS] = { [0 ... NR_IRQS -1] = -1};#ifdef CONFIG_PCI_USE_VECTOR} irq_2_pin[PIN_MAP_SIZE]; int apic, pin, next;static struct irq_pin_list { */ * between pins and IRQs. * the indexing order of this array favors 1:1 mappings * * This is performance-critical, we want to do it O(1)/*#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)#define MAX_PLUS_SHARED_IRQS NR_IRQS */ * be changed anytime. * Rough estimation of how many shared IRQs there are, can/*int nr_ioapic_registers[MAX_IO_APICS]; */ * # of IRQ routing registers/*int sis_apic_bug = -1; */ * -1 = don't know, 0 = no, 1 = yes * Is the SiS APIC rmw bug present ?/*static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;#define APIC_LOCKUP_DEBUG#undef APIC_LOCKUP_DEBUG#include "io_ports.h"#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include */ * Paul Diefenbaugh : Added full ACPI support * for testing these extensively * and Rolf G. Tews * thanks to Eric Gilmore * Maciej W. Rozycki : Bits for genuine 82489DX APICs; * Fixes * * and Ingo Molnar * further tested and cleaned up by Zach Brown * Hidemi Kishimoto , * Ken-ichi Yaku and * (c) 1999, Multiple IO-APIC support, developed by * * patches and reporting/debugging problems patiently! * Many thanks to Stig Venaas for trying out countless experimental * * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo * * Intel IO-APIC support for multi-Pentium hosts./*ad2 %pS0\ q g : 7 6   m 3   #endif /*CONFIG_ACPI_BOOT*/} return 0; spin_unlock_irqrestore(&ioapic_lock, flags); io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); spin_lock_irqsave(&ioapic_lock, flags); disable_8259A_irq(irq); if (!ioapic && (irq < 16)) set_intr_gate(entry.vector, interrupt[irq]); } irq_desc[irq].handler = &ioapic_edge_type; } else { irq_desc[irq].handler = &ioapic_level_type; if (edge_level) { irq = IO_APIC_VECTOR(irq); if (use_pci_vector() && !platform_legacy_irq(irq)) mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); "IRQ %d Mode:%i Active:%i)\n", ioapic, printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " entry.vector = assign_irq_vector(irq); add_pin_to_irq(irq, ioapic, pin); entry.mask = 1; entry.polarity = active_high_low; entry.trigger = edge_level; entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); entry.dest_mode = INT_DEST_MODE; entry.delivery_mode = INT_DELIVERY_MODE; \ No newline at end of file diff -aurpN -X /home/fletch/.diff.exclude 272-config_irqbal/arch/i386/kernel/apic.c 274-percpu_real_loadavg/arch/i386/kernel/apic.c --- 272-config_irqbal/arch/i386/kernel/apic.c Mon Nov 17 18:29:41 2003 +++ 274-percpu_real_loadavg/arch/i386/kernel/apic.c Thu Jan 1 23:22:19 2004 @@ -1028,7 +1028,7 @@ int setup_profiling_timer(unsigned int m * multiplier is 1 and it can be changed by writing the new multiplier * value into /proc/profile. */ - +extern void calc_load_cpu(int cpu); inline void smp_local_timer_interrupt(struct pt_regs * regs) { int cpu = smp_processor_id(); @@ -1056,6 +1056,7 @@ inline void smp_local_timer_interrupt(st #ifdef CONFIG_SMP update_process_times(user_mode(regs)); + calc_load_cpu(cpu); #endif } diff -aurpN -X /home/fletch/.diff.exclude 272-config_irqbal/fs/proc/proc_misc.c 274-percpu_real_loadavg/fs/proc/proc_misc.c --- 272-config_irqbal/fs/proc/proc_misc.c Thu Jan 1 23:21:51 2004 +++ 274-percpu_real_loadavg/fs/proc/proc_misc.c Thu Jan 1 23:22:19 2004 @@ -134,6 +134,41 @@ static struct vmalloc_info get_vmalloc_i return vmi; } +static int real_loadavg_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int a, b, c, cpu; + int len; + + a = tasks_running[0] + (FIXED_1/200); + b = tasks_running[1] + (FIXED_1/200); + c = tasks_running[2] + (FIXED_1/200); + len = sprintf(page,"Domain load1 load2 load3 nr_run/nr_thrd\n"); + len += sprintf(page+len,"SYSTEM %5d.%02d %5d.%02d %5d.%02d %7ld/%7d\n", + LOAD_INT(a), LOAD_FRAC(a), + LOAD_INT(b), LOAD_FRAC(b), + LOAD_INT(c), LOAD_FRAC(c), + nr_running(), nr_threads); + for (cpu = 0; cpu < NR_CPUS; ++cpu) { + unsigned long nr_running; + if (!cpu_online(cpu)) + continue; + preempt_disable(); + a = per_cpu(cpu_tasks_running,cpu)[0] + (FIXED_1/200); + b = per_cpu(cpu_tasks_running,cpu)[1] + (FIXED_1/200); + c = per_cpu(cpu_tasks_running,cpu)[2] + (FIXED_1/200); + nr_running = nr_running_cpu(cpu); + preempt_enable(); + len += sprintf(page+len, "%5d %5d.%02d %5d.%02d %5d.%02d %7ld/%7d\n", + cpu, + LOAD_INT(a), LOAD_FRAC(a), + LOAD_INT(b), LOAD_FRAC(b), + LOAD_INT(c), LOAD_FRAC(c), + nr_running, nr_threads); + } + return proc_calc_metrics(page, start, off, count, eof, len); +} + static int uptime_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -757,6 +792,7 @@ void __init proc_misc_init(void) int (*read_proc)(char*,char**,off_t,int,int*,void*); } *p, simple_ones[] = { {"loadavg", loadavg_read_proc}, + {"real_loadavg",real_loadavg_read_proc}, {"uptime", uptime_read_proc}, {"meminfo", meminfo_read_proc}, {"version", version_read_proc}, diff -aurpN -X /home/fletch/.diff.exclude 272-config_irqbal/include/linux/sched.h 274-percpu_real_loadavg/include/linux/sched.h --- 272-config_irqbal/include/linux/sched.h Thu Jan 1 21:24:54 2004 +++ 274-percpu_real_loadavg/include/linux/sched.h Thu Jan 1 23:22:19 2004 @@ -71,7 +71,11 @@ struct exec_domain; * the EXP_n values would be 1981, 2034 and 2043 if still using only * 11 bit fractions. */ -extern unsigned long avenrun[]; /* Load averages */ +extern unsigned long avenrun[]; /* Load averages */ +extern unsigned long tasks_running[3]; /* Real load averages */ +DECLARE_PER_CPU(unsigned long[3],cpu_tasks_running); /* Real load averages per cpu */ + +extern unsigned long tasks_running[]; /* Real load averages */ #define FSHIFT 11 /* nr of bits of precision */ #define FIXED_1 (1<nr_running; +} + unsigned long nr_uninterruptible(void) { unsigned long i, sum = 0; diff -aurpN -X /home/fletch/.diff.exclude 272-config_irqbal/kernel/timer.c 274-percpu_real_loadavg/kernel/timer.c --- 272-config_irqbal/kernel/timer.c Mon Dec 8 09:55:53 2003 +++ 274-percpu_real_loadavg/kernel/timer.c Thu Jan 1 23:22:19 2004 @@ -768,6 +768,8 @@ static unsigned long count_active_tasks( * Requires xtime_lock to access. */ unsigned long avenrun[3]; +unsigned long tasks_running[3]; +DEFINE_PER_CPU(unsigned long[3],cpu_tasks_running); /* * calc_load - given tick count, update the avenrun load estimates. @@ -775,7 +777,7 @@ unsigned long avenrun[3]; */ static inline void calc_load(unsigned long ticks) { - unsigned long active_tasks; /* fixed-point */ + unsigned long active_tasks, running_tasks; /* fixed-point */ static int count = LOAD_FREQ; count -= ticks; @@ -785,7 +787,37 @@ static inline void calc_load(unsigned lo CALC_LOAD(avenrun[0], EXP_1, active_tasks); CALC_LOAD(avenrun[1], EXP_5, active_tasks); CALC_LOAD(avenrun[2], EXP_15, active_tasks); + running_tasks = nr_running() * FIXED_1; + CALC_LOAD(tasks_running[0], EXP_1, running_tasks); + CALC_LOAD(tasks_running[1], EXP_5, running_tasks); + CALC_LOAD(tasks_running[2], EXP_15, running_tasks); } +} + +/* + * This does the frequency calculation a little bit different from the + * global version above. It doesn't ever look at the kernel's concept + * of time, it just updates that stats every LOAD_FREQ times into the + * function. + * + * Using jiffies is more accurate, but there _are_ just statistics, so + * they're not worth messing with xtime_lock and company. If we miss + * an interrupt or two, big deal. + */ +void calc_load_cpu(int cpu) +{ + unsigned long running_tasks; + static DEFINE_PER_CPU(int, count) = { LOAD_FREQ }; + + per_cpu(count, cpu)--; + if (per_cpu(count, cpu) != 0) + return; + + per_cpu(count, cpu) += LOAD_FREQ; + running_tasks = nr_running_cpu(cpu) * FIXED_1; + CALC_LOAD(per_cpu(cpu_tasks_running, cpu)[0], EXP_1, running_tasks); + CALC_LOAD(per_cpu(cpu_tasks_running, cpu)[1], EXP_5, running_tasks); + CALC_LOAD(per_cpu(cpu_tasks_running, cpu)[2], EXP_15, running_tasks); } /* jiffies at the most recent update of wall time */