static void hard_idle(void) { while (!need_resched) { if (hlt_works_ok && !hlt_counter) { #ifdef CONFIG_APM /* If the APM BIOS is not enabled, or there is an error calling the idle routine, we should hlt if possible. We need to check need_resched again because an interrupt may have occurred in apm_do_idle(). */ start_bh_atomic(); if (!apm_do_idle() && !need_resched) __asm__("hlt"); end_bh_atomic(); #else __asm__("hlt"); #endif } if (need_resched) break; schedule(); } #ifdef CONFIG_APM apm_do_busy(); #endif }
static void apm_cpu_idle(void) { static int use_apm_idle; /* = 0 */ static unsigned int last_jiffies; /* = 0 */ static unsigned int last_stime; /* = 0 */ int apm_idle_done = 0; unsigned int jiffies_since_last_check = jiffies - last_jiffies; unsigned int bucket; recalc: if (jiffies_since_last_check > IDLE_CALC_LIMIT) { use_apm_idle = 0; last_jiffies = jiffies; last_stime = current->stime; } else if (jiffies_since_last_check > idle_period) { unsigned int idle_percentage; idle_percentage = current->stime - last_stime; idle_percentage *= 100; idle_percentage /= jiffies_since_last_check; use_apm_idle = (idle_percentage > idle_threshold); if (apm_info.forbid_idle) use_apm_idle = 0; last_jiffies = jiffies; last_stime = current->stime; } bucket = IDLE_LEAKY_MAX; while (!need_resched()) { if (use_apm_idle) { unsigned int t; t = jiffies; switch (apm_do_idle()) { case 0: apm_idle_done = 1; if (t != jiffies) { if (bucket) { bucket = IDLE_LEAKY_MAX; continue; } } else if (bucket) { bucket--; continue; } break; case 1: apm_idle_done = 1; break; default: /* BIOS refused */ break; } } if (original_pm_idle) original_pm_idle(); else default_idle(); local_irq_disable(); jiffies_since_last_check = jiffies - last_jiffies; if (jiffies_since_last_check > idle_period) goto recalc; } if (apm_idle_done) apm_do_busy(); local_irq_enable(); }