ARM Linux 如何--注冊和觸發--軟中斷
1. 注冊軟中斷當然是通過open_softirq
例子如下:
[cpp] view plain copy- 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;
- }
軟中斷TIMER_SOFTIRQ的中斷處理函數為:run_timer_softirq
之所以成為softirq,是因為這些中斷是由硬件中斷來間接觸發的,如何間接觸發的呢:
硬件中斷處理函數-->對軟中斷的相應位置位-->喚醒ksoftirqd線程-->執行軟中斷的中斷處理函數
2. 硬件中斷如何通過置位喚醒ksoftirqd線程
timer interrupt handler->
timer_tick->
update_process_times->
run_local_timers->
hrtimer_run_queues()和raise_softirq(TIMER_SOFTIRQ)->
raise_softirq_irqoff->
__raise_softirq_irqoff { or_softirq_pending(1UL << (nr)); }
即(local_softirq_pending() |= (x))
3. 如何執行軟中斷的action<中斷處理函數>
對于TIMER_SOFTIRQ來說,每次system clock產生中斷時,即一個tick 到來時,在system clock的中斷處理函數中會調用run_local_timers來設置TIMER_SOFTIRQ觸發條件;也就是當前CPU對應的irq_cpustat_t結構體中的__softirq_pending成員的第TIMER_SOFTIRQ個BIT被置為1。 而當這個條件滿足時,ksoftirqd線程(入口函數run_ksoftirqd,cpu_callback:kthread_create(run_ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);)會被喚醒,然后按照下面的流程調用TIMER_SOFTIRQ在數組softirq_vec中注冊的action,即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;
- }
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成