void rcu_check_callbacks(int cpu, int user) { if (user || (idle_cpu(cpu) && !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) { rcu_qsctr_inc(cpu); rcu_bh_qsctr_inc(cpu); } else if (!in_softirq()) rcu_bh_qsctr_inc(cpu); tasklet_schedule(&per_cpu(rcu_tasklet, cpu)); }
/* * Check to see if the scheduling-clock interrupt came from an extended * quiescent state, and, if so, tell RCU about it. */ void rcu_check_callbacks(int cpu, int user) { if (!rcu_needs_cpu(0)) return; /* RCU doesn't need anything to be done. */ if (user || (idle_cpu(cpu) && !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) rcu_qsctr_inc(cpu); else if (!in_softirq()) rcu_bh_qsctr_inc(cpu); }
static int ksoftirqd(void * __bind_cpu) { set_user_nice(current, 19); current->flags |= PF_NOFREEZE; set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { preempt_disable(); if (!local_softirq_pending()) { preempt_enable_no_resched(); schedule(); preempt_disable(); } __set_current_state(TASK_RUNNING); while (local_softirq_pending()) { /* Preempt disable stops cpu going offline. If already offline, we'll be on wrong CPU: don't process */ if (cpu_is_offline((long)__bind_cpu)) goto wait_to_die; do_softirq(); preempt_enable_no_resched(); cond_resched(); preempt_disable(); rcu_qsctr_inc((long)__bind_cpu); } preempt_enable(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); return 0; wait_to_die: preempt_enable(); /* Wait for kthread_stop */ set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { schedule(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); return 0; }
/* * Enter dynticks-idle mode, which is an extended quiescent state * if we have fully entered that mode (i.e., if the new value of * dynticks_nesting is zero). */ void rcu_enter_nohz(void) { if (--rcu_dynticks_nesting == 0) rcu_qsctr_inc(0); /* implies rcu_bh_qsctr_inc(0) */ }