1. The Soft Interrupt of registration is, of course, through open_softirq
Example:
void __init init_timers(void){int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,(void *)(long)smp_processor_id());init_timer_stats();BUG_ON(err == NOTIFY_BAD);register_cpu_notifier(&timers_nb);open_softirq(TIMER_SOFTIRQ, run_timer_softirq);}void open_softirq(int nr, void (*action)(struct softirq_action *)){softirq_vec[nr].action = action;}
The interrupt processing function of the Soft Interrupt timer_softirq is run_timer_softirq.
Softirq is triggered indirectly by hardware interruptions. How can this problem be indirectly triggered:
Hardware Interrupt Processing Function --> position corresponding to Soft Interrupt --> wake up ksoftirqd thread --> execute Soft Interrupt Processing Function
2. How to wake up the ksoftirqd thread through the position during hardware interruption
Timer interrupt handler->
Timer_tick->
Update_process_times->
Run_local_timers->
Hrtimer_run_queues () and raise_softirq (timer_softirq)->
Raise_softirq_irqoff->
_ Raise_softirq_irqoff {or_softirq_pending (1ul <(NR ));}
That is, (local_softirq_pending () | = (x ))
3. How to execute Soft Interrupt action <interrupt processing function>
For timer_softirq, every time the system clock is interrupted, that is, when a tick arrives, run_local_timers will be called in the system clock interrupt handler to set the timer_softirq trigger condition; that is, the timer_softirq_pending bits of the _ softirq_pending member in the irq_cpustat_t struct corresponding to the current CPU are set to 1. When this condition is met, the ksoftirqd thread (entry function run_ksoftirqd, cpu_callback: kthread_create (run_ksoftirqd,
Hcpu, "ksoftirqd/% d", hotcpu);) will be awakened, and then call the Action registered by timer_softirq in the array softirq_vec according to the following procedure, that is, run_timer_softirq.
Run_ksoftirqd ---> do_softirq --- >__ do_softirq ---> softirq_vec [timer_softirq]. Action
static int run_ksoftirqd(void * __bind_cpu){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_sched_qs((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;}