In the previous blog post, roughly scattered about some of the interruption-related things, but the soft break of the part is not carefully introduced, here a unified summary.
Interrupts the processing of the upper half and assembles the process between the handle of the REQUEST_IRQ.
http://blog.csdn.net/jackjones_008/article/details/42387241
A little record of the MIPS platform
http://blog.csdn.net/jackjones_008/article/details/41945909
Tasklet/workqueue's introduction is described in more detail in the following blog post.
http://blog.csdn.net/jackjones_008/article/details/42295411
The processing of interrupts is, of course, the processing of the assembly part after the hardware interrupt occurs, and then after the HARDIRQ processing, in the function irq_exit, if it is found that there is currently no HARDIRQ and SOFTIRQ is not forbidden,
There is also no local SOFTIRQ for pending, and the call DO_SOFTIRQ to handle SOFTIRQ is displayed. In the process of processing SOFTIRQ, the hardware interrupts are shielded.
asmlinkage void Do_softirq (void) {__u32 pending;unsigned long flags;if (In_interrupt ()) Return;local_irq_save (flags); Pending = Local_softirq_pending (); if (pending) __do_softirq (); Local_irq_restore (flags);}
In __do_softirq, after getting pending SOFTIRQ, the hardware interrupt is turned on. Then we will deal with pending's Softirq in turn.
This, in turn, is performed from HI_SOFTIRQ to RCU_SOFTIRQ according to the definition in enum.
More wordy, why there are pending SOFTIRQ, because the code somewhere to call the __raise_softirq_irqoff.
We can also note that the __DO_SOFTIRQ defines a max_restart, which is 10, a compromise of the system that handles soft interrupts, but does not unduly affect the execution of other processes.
Can't finish, can give KSOFTIRQD this kernel thread to do.
asmlinkage void __do_softirq (void) {struct Softirq_action *h;__u32 pending;int max_restart = Max_softirq_restart;int CPU ;p ending = local_softirq_pending (); Account_system_vtime (current); __local_bh_disable ((unsigned long) __builtin_ Return_address (0)); Trace_softirq_enter (); CPU = smp_processor_id (); restart:/* Reset the pending bitmask before enabling IRQs */set_softirq_pending (0); local_irq_enable (); h = softirq_vec;do {if (pending & 1) {int prev_count = Preempt_count (); H->action (h); if (unlikely (prev_count! = Preempt_count ())) {PRINTK (kern_err "Huh, entered Softirq%td%p" "With Preempt_count%08x, "exited with%08x?\n", H-softirq_vec, H->action, Prev_count, Preempt_count ());p ree Mpt_count () = Prev_count;} Rcu_bh_qsctr_inc (CPU);} h++;p ending >>= 1;} while (pending); Local_irq_disable ();p ending = local_softirq_pending (); if (pending &&--max_restart) goto Restart;if (Pending) Wakeup_softirqd (); Trace_softirq_exit (); Account_system_vtime (current); _local_bh_enAble ();}
ENUM{HI_SOFTIRQ=0,TIMER_SOFTIRQ,NET_TX_SOFTIRQ,NET_RX_SOFTIRQ,BLOCK_SOFTIRQ,TASKLET_SOFTIRQ,SCHED_SOFTIRQ, hrtimer_softirq,rcu_softirq,/* preferable RCU should always being the last SOFTIRQ */nr_softirqs};
Then, after processing the restart, there are pending SOFTIRQ words, to the kernel process ksoftirqd to do. This kernel process will also explicitly call DO_SOFTIRQ to handle.
static int ksoftirqd (void * __bind_cpu) {set_current_state (task_interruptible); while (!kthread_should_stop ()) { Preempt_disable (); if (!local_softirq_pending ()) {preempt_enable_no_resched (); schedule ();p reempt_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_s OFTIRQ ();p reempt_enable_no_resched (); cond_resched ();p reempt_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;}
At this time, it is inevitable to return to interrupt the upper half and the second half of the topic, the top half we can understand to have been executed to REQUEST_IRQ registered in the handle so far. The processing of the SOFTIRQ begins in the lower part.
In the treatment of the lower part, the mechanism of tasklet and workqueue can be used depending on the sleep or not.
In fact, Tasklet is also belong to the SOFTIRQ, and not sleep. The workqueue mechanism is given to the kernel thread to execute, allowing sleep to be allowed.
Summary of Linux interrupt processing subsystem