--- zzzz-none-000/linux-2.6.28.10/arch/arm/kernel/process.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/arch/arm/kernel/process.c 2011-03-14 11:49:31.000000000 +0000 @@ -35,6 +35,9 @@ #include #include #include +#ifdef CONFIG_AVM_POWERMETER +#include +#endif/*--- #ifdef CONFIG_AVM_POWERMETER ---*/ static const char *processor_modes[] = { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , @@ -123,6 +126,88 @@ EXPORT_SYMBOL_GPL(arm_pm_restart); +/*--------------------------------------------------------------------------------------*\ +\*--------------------------------------------------------------------------------------*/ +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 */ * 200))) { + 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; + } +} /* * This is our default idle handler. We need to disable * interrupts here to ensure we don't miss a wakeup call. @@ -163,8 +248,12 @@ idle = default_idle; leds_event(led_idle_start); tick_nohz_stop_sched_tick(1); - while (!need_resched()) + while (!need_resched()) { + cpu_wait_start(); idle(); + cpu_wait_end(); + } + cpu_wait_info(); leds_event(led_idle_end); tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); @@ -392,3 +481,33 @@ } while (count ++ < 16); return 0; } + +static struct kmem_cache *thread_info_cache; + +struct thread_info *alloc_thread_info(struct task_struct *tsk) +{ + struct thread_info *ti; + + ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL); + if (unlikely(ti == NULL)) { + return NULL; + } + if((unsigned long)ti & (THREAD_SIZE - 1)) { + printk("[%s] task struct not aligned 0x%p\n", __FUNCTION__, ti); + } +#ifdef CONFIG_DEBUG_STACK_USAGE + memset(ti, 0, THREAD_SIZE); +#endif + return ti; +} + +void free_thread_info(struct thread_info *ti) +{ + kmem_cache_free(thread_info_cache, ti); +} + +void thread_info_cache_init(void) +{ + thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, THREAD_SIZE, 0, NULL); + BUG_ON(thread_info_cache == NULL); +}