--- zzzz-none-000/linux-2.6.28.10/arch/mips/kernel/process.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/arch/mips/kernel/process.c 2011-03-14 11:49:31.000000000 +0000 @@ -42,7 +42,95 @@ #include #include #include +#ifdef CONFIG_AVM_POWERMETER +#include +#endif/*--- #ifdef CONFIG_AVM_POWERMETER ---*/ + +/*--------------------------------------------------------------------------------------*\ +\*--------------------------------------------------------------------------------------*/ +static struct _cpu_idlecount { + unsigned int last_value; + unsigned long last_value_done; + unsigned int wait_count; + unsigned int run_count; + unsigned int sum_count; + unsigned int show; + unsigned int fullrun; + unsigned int fulldisp_jiffies; +} cpu_idlecount; + +#define COUNT_DIFF(act, last) ((act) - (last)) +/*--------------------------------------------------------------------------------*\ +\*--------------------------------------------------------------------------------*/ +static void cpu_wait_start(void) { + unsigned int count, tmp; + count = get_cycles(); + if(cpu_idlecount.last_value) { + tmp = COUNT_DIFF(count, cpu_idlecount.last_value); + cpu_idlecount.run_count += tmp; + cpu_idlecount.sum_count += tmp; + } + cpu_idlecount.last_value = count; + cpu_idlecount.last_value_done = 0; + if(cpu_idlecount.fulldisp_jiffies == 0) { + cpu_idlecount.fulldisp_jiffies = jiffies; + } +} +/*--------------------------------------------------------------------------------------*\ +\*--------------------------------------------------------------------------------------*/ +int cpu_wait_end(void) { + if(test_and_set_bit(0, &cpu_idlecount.last_value_done) == 0) { + int count, tmp; + count = get_cycles(); + tmp = COUNT_DIFF(count, cpu_idlecount.last_value); + cpu_idlecount.wait_count += tmp; + cpu_idlecount.sum_count += tmp; + cpu_idlecount.last_value = count; + return 0; + } +#ifdef CONFIG_AVM_POWERMETER + if((COUNT_DIFF(get_cycles(), cpu_idlecount.last_value) > (1000 * 1000 /* usec */ * 250))) { + register int j_diff; + cpu_idlecount.last_value = get_cycles(); + PowerManagmentRessourceInfo(powerdevice_loadrate, 100); /*--- triggere alle Sekunde ---*/ + cpu_idlecount.fullrun++; + j_diff = COUNT_DIFF(jiffies, cpu_idlecount.fulldisp_jiffies); + if(j_diff >= (10 * HZ)) { + cpu_idlecount.fulldisp_jiffies = jiffies; + if(cpu_idlecount.fullrun >= 10) { + printk("system-load 100 %% curr: %s runnable: %ld\n", current->comm, nr_running()); + } else { + printk("system-load %d curr: %s runnable: %ld\n", cpu_idlecount.fullrun, current->comm, nr_running()); + } + cpu_idlecount.fullrun = 0; + } + /*--- printk(""); ---*/ + } +#endif/*--- #ifdef CONFIG_AVM_POWERMETER ---*/ + return 1; +} +/*--------------------------------------------------------------------------------*\ +\*--------------------------------------------------------------------------------*/ +static void cpu_wait_info(void) { + register unsigned int sum_count = cpu_idlecount.sum_count; + if(sum_count > (1 << 29)) { + int p_idle = ((cpu_idlecount.wait_count >> 8) * 100) / (cpu_idlecount.sum_count >> 8); + +#ifdef CONFIG_AVM_POWERMETER + PowerManagmentRessourceInfo(powerdevice_loadrate, max(0, 100 - p_idle)); +#else + int p_run = ((cpu_idlecount.run_count >> 8) * 100) / (sum_count >> 8); + if(cpu_idlecount.show) printk("[idle]: %u%% (run %u%%)\n", p_idle, p_run); +#endif/*--- #ifdef CONFIG_AVM_POWERMETER ---*/ + cpu_idlecount.sum_count >>= 8; + cpu_idlecount.wait_count >>= 8; + cpu_idlecount.run_count >>= 8; + } +} + +void (*pm_idle)(void) = NULL; +EXPORT_SYMBOL(pm_idle); /* * The idle thread. There's no useful work to be done, so just try to conserve * power and have a low exit latency (ie sit in a loop waiting for somebody to @@ -54,14 +142,21 @@ while (1) { tick_nohz_stop_sched_tick(1); while (!need_resched()) { + cpu_wait_start(); #ifdef CONFIG_MIPS_MT_SMTC extern void smtc_idle_loop_hook(void); smtc_idle_loop_hook(); #endif - if (cpu_wait) + if (pm_idle) + (*pm_idle)(); + + if (cpu_wait) { (*cpu_wait)(); + } + cpu_wait_end(); } + cpu_wait_info(); tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); @@ -104,7 +199,7 @@ { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; - long childksp; + unsigned long childksp; p->set_child_tid = p->clear_child_tid = NULL; childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32; @@ -121,6 +216,7 @@ /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; + childksp = (unsigned long) childregs; *childregs = *regs; childregs->regs[7] = 0; /* Clear error flag */