Mastering the Linux kernel Design (iii): Soft interrupt of the lower half mechanism

Source: Internet
Author: User
Tags exit in

"copyright notice: respect for the original, reproduced please retain the source: Blog.csdn.net/shallnet, the article is only for learning exchange, do not use for commercial use "
The interrupt handler executes asynchronously, interrupting other important code, which is blocked by other interrupts at runtime, and all other interrupts on the current processor may be masked, and interrupt handlers cannot be blocked, so the interrupt processing needs to be ended as soon as possible. Due to these flaws in the interrupt handler, theThe interrupt handler is only part of the entire hardware interrupt processing process, and for those tasks that are not time-critical, leave another part of the interrupt processing process, which is the lower half of the interrupt processing process that this sectionto is talking about. Which work is done by the interrupt handler, and what is left to the bottom half for execution? In fact, the work of the upper and lower part of the division does not have a certain strict restrictions, which depends largely on the driver developer's own judgment, it is generally better to reduce the execution time of the interrupt handler to a minimum. Interrupt handlers almost always need to confirm the arrival of interrupts through the operating hardware, and sometimes do time-sensitive work (such as copying data), leaving the rest largely to the bottom half for processing, The lower half is the work that is closely related to interrupt handling but that the interrupt handler itself does not perform. these tasks, which are typically time-sensitive, hardware-related, and are guaranteed not to be interrupted by other interrupts (especially the same interrupts), are performed in the interrupt handler, and other tasks are considered to be performed in the lower part. When is the second half going to be executed? The lower half does not require explicit execution time, as long as the task is postponed a little, so that they can execute after the system is not too busy and the recovery is interrupted, and all interrupts can be made during execution. The top half can only be implemented by an interrupt handler, while the lower half is implemented in a variety of mechanisms, in 2.6.32, there are three different forms of the lower half implementation mechanism: Soft interrupt, Tasklet, and task queue. Let's look at the implementation of these three lower halves.
Soft Interruptin the Start_kernerl () function, the system initializes the soft interrupt.
asmlinkage void __init Start_kernel (void) {    char * command_line;    extern struct Kernel_param __start___param[], __stop___param[];    SMP_SETUP_PROCESSOR_ID ();    Softirq_init ();//Initialize soft interrupt    ... /* Do the rest non-__init ' Ed, we ' re now alive *    /Rest_init ();}

A soft interrupt of two common types is registered in Softirq_init (), as follows (in kernel/softirq.c):
void __init softirq_init (void) {    int cpu;    FOR_EACH_POSSIBLE_CPU (CPU) {        int i;        PER_CPU (Tasklet_vec, CPU). Tail =            &per_cpu (Tasklet_vec, CPU). Head;        PER_CPU (Tasklet_hi_vec, CPU). Tail =            &per_cpu (Tasklet_hi_vec, CPU). Head;        for (i = 0; i < Nr_softirqs; i++)            Init_list_head (&per_cpu (softirq_work_list[i], CPU));    }    Register_hotcpu_notifier (&remote_softirq_cpu_notifier);    Register here for two soft interrupt    Open_softirq (TASKLET_SOFTIRQ, tasklet_action);     OPEN_SOFTIRQ (HI_SOFTIRQ, tasklet_hi_action);}

The registration function OPEN_SOFTIRQ () parameter means:
NR: Soft Interrupt type action: Soft Interrupt handling function
void Open_softirq (int nr, void (*action) (struct softirq_action *)) {    softirq_vec[nr].action = action;}
the softirq_action structure represents a soft interrupt, defined in <include/linux/interrupt.h>
struct softirq_action{    void    (*action) (struct softirq_action *);}
32 Arrays of this struct are defined in file <kernel/softirq.c>:
static struct softirq_action Softirq_vec[nr_softirqs] __cacheline_aligned_in_smp;
each registered soft interrupt takes up one position in the array, so there are up to 32 soft interrupts in the system. From the above code, we can see: Open_softirq (). In fact, it is the Nr item assignment to the Softirq_vec array. Softirq_vec is an array of 32 elements, and the Linux kernel actually uses only a few items:
/* Please, avoid to allocate new SOFTIRQS, if you need not _really_ high   frequency threaded job scheduling. For almost all the purposes   tasklets is more than enough. F.E. All serial device BHs et   al. should is converted to tasklets, not to Softirqs. */enum{    hi_softirq=0,    time R_SOFTIRQ,    Net_tx_softirq,    Net_rx_softirq,    Block_softirq,    Block_iopoll_softirq,    tasklet_ SOFTIRQ,    Sched_softirq,    Hrtimer_softirq,    RCU_SOFTIRQ,/    * Preferable RCU should always being the last SOFTIRQ */    Nr_softirqs};
after the soft interrupt registration is complete, when will trigger the soft interrupt handler function to execute? Typically, a soft interrupt marks the interrupt handler before it returns, making it executable at a later time. The pending soft interrupts are checked and executed in the following places:
1. After processing a hardware interrupt;
2. In the KSOFTIRQD kernel thread;
3. In the code that shows the check and execution of the soft interrupt to be processed, such as in the network subsystem. For information on the network subsystem, refer to the article: http://blog.csdn.net/shallnet/article/details/26269781

In any case, soft interrupts are performed in DO_SOFTIRQ () (in <kernel/softirq.c> ), and if a soft interrupt is to be processed, DO_SOFTIRQ loops through each one, Call their soft interrupt handlers.
asmlinkage void Do_softirq (void) {     __u32 pending;     unsigned long flags;     If you exit in a hardware interrupt environment, soft interrupts can not be used in hardware interrupt contexts or in soft-interrupt environments, use In_interrupt () to prevent soft-break nesting, and preempt hard-interrupt environments.     if (In_interrupt ())         return;     Prohibit local interrupt     local_irq_save (flags);     Pending = Local_softirq_pending ();        If there is a soft interrupt to be processed, enter __DO_SOFTIRQ ()    if (pending)         __do_softirq ();     Local_irq_restore (flags);     

here 's a look.__do_softirq ()implementation of:
asmlinkage void __do_softirq (void) {struct softirq_action *h;       __U32 pending;    int max_restart = Max_softirq_restart;    int CPU;    Pending = Local_softirq_pending ();    The pending is used to retain the pending soft interrupt 32-bit bitmap account_system_vtime (current);    __local_bh_disable ((unsigned long) __builtin_return_address (0));    Lockdep_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) {//If pending nth bit is set to 1, then the soft interrupt int prev_count = Preempt_count () of the corresponding type of nth bit is processed;            KSTAT_INCR_SOFTIRQS_THIS_CPU (H-softirq_vec);            Trace_softirq_entry (H, Softirq_vec);    H->action (h);            Perform soft interrupt processing function trace_softirq_exit (h, Softirq_vec);                       if (unlikely (prev_count! = Preempt_count ())) {PRINTK (kern_err "Huh, entered Softirq%td%s%p"              "With Preempt_count%08x,"         "Exited with%08x?\n", H-softirq_vec, Softirq_to_name[h-softirq_vec],                H->action, Prev_count, Preempt_count ());            Preempt_count () = Prev_count;        } rcu_bh_qs (CPU);        } h++;    Pending >>= 1;    Pending one bit to the right, looping through each of its bits} while (pending);    The loop executes up to 32 times until pending becomes 0,pending up to 32 bits.    Local_irq_disable ();    Pending = Local_softirq_pending ();    if (pending &&--max_restart) goto restart;    if (pending) Wakeup_softirqd ();    Lockdep_softirq_exit ();    Account_system_vtime (current); _local_bh_enable ();}
The use of soft interrupts must be statically registered during compilation, generally only like the network of high performance requirements for the use of soft interrupts, the article before we also see that the system registered soft interrupt just a few. Most of the time, using the second half of another mechanism tasklet more, Tasklet can be dynamically registered and can be seen as a product of balancing performance and usability. In fact, most drivers use Tasklet to implement theirthe lower half of the section.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Mastering the Linux kernel Design (iii): Soft interrupt of the lower half mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.