/* * 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 say that they'd like to reschedule) */ void cpu_idle(void) { int cpu = smp_processor_id(); current_thread_info()->status |= TS_POLLING; /* endless idle loop with no priority at all */ while (1) { tick_nohz_stop_sched_tick(); while (!need_resched()) { check_pgt_cache(); rmb(); if (rcu_pending(cpu)) rcu_check_callbacks(cpu, 0); if (cpu_is_offline(cpu)) play_dead(); local_irq_disable(); __get_cpu_var(irq_stat).idle_timestamp = jiffies; /* Don't trace irqs off for idle */ stop_critical_timings(); pm_idle(); start_critical_timings(); } tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); preempt_disable(); } }
/* * Check to see if any future RCU-related work will need to be done * by the current CPU, even if none need be done immediately, returning * 1 if so. This function is part of the RCU implementation; it is -not- * an exported member of the RCU API. */ int rcu_needs_cpu(int cpu) { struct rcu_data *rdp = &per_cpu(rcu_data, cpu); struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu); return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu)); }
asmlinkage void do_softirq(void) { unsigned int i, cpu; unsigned long pending; for ( ; ; ) { /* * Initialise @cpu on every iteration: SCHEDULE_SOFTIRQ may move * us to another processor. */ cpu = smp_processor_id(); if ( rcu_pending(cpu) ) rcu_check_callbacks(cpu); if ( (pending = softirq_pending(cpu)) == 0 ) break; i = find_first_set_bit(pending); clear_bit(i, &softirq_pending(cpu)); (*softirq_handlers[i])(); } }