Linux kernel SoftIRQ mechanism (3)

xiaoxiao2021-03-06  20

Linux kernel SoftIRQ mechanism (3)

6.3 Bottom HALF Mechanism The Bottom Half mechanism is retained in the new SoftIRQ mechanism and as part of the Softirq framework. Its implementation seems to be more complex because it is incorporated into the SoftiRQ framework through the Tasklet mechanism. In fact, the soft interrupt vector HI_SOFTIRQ is the kernel dedicated to execute BH functions. 6.3.1 Definition of data structure The original 32 BH function pointer is preserved, defined in the kernel / Softirq.c file: Static void (* BH_BASE [32]) (Void); however, each BH function is Corresponding to a tasklet, and is responsible for calling the corresponding BH function (which BH function of the FUNC function is specified). The Tasklet corresponding to 32 BH function pointers is as follows (Kernel / Softirq.c): struct tasklet_struct BH_TASK_VEC [32]; the above Tasklet array allows the system to be globally, which is visible to all CPUs. Since there is only one CPU in an execution BH function in a certain moment, a global spin lock is defined to protect the BH function, as shown below (kernel / Softirq.c): spinlock_t global_bh_lock = spin_lock_unlocked; 6.3.2 Initialization In the initialization function of the SoftIRQ mechanism, the FUNC function pointer in each of the Tasklet in each of the Tasklet in the BH_TASK_VEC [32] array is set to the same function BH_Action, and the DATA member (i.e., the call parameters of the FUNC function) are set. The index value of this tasklet in the array is as follows: void __init softirq_init () {... for (i = 0; i <32; i ) tasklet_init (bh_task_vec i, bh_action, i); ......} Therefore, The BH_ACTION () function will be responsible for calling the BH function specified by the parameter accordingly. This function is the key to connecting the Tasklet mechanism and the Bottom HALF mechanism. 6.2.3 BH_ACTION () Function The source code of this function is as follows: static void bh_action (unsigned long nr) {int CPU = SMP_Processor_ID (); if (! Spin_trylock (& ​​global_bh_lock) goto resched; if (! hardirq_trylock (cpu)) goto resched_unlock; if (bh_base [nr]) bh_base [nr] (); hardirq_endlock (cpu); spin_unlock (& ​​global_bh_lock); return; resched_unlock: spin_unlock (& ​​global_bh_lock); resched: mark_bh (nr); } The comments for this function are as follows: 1 First, call the spin_trylock () function to attempt to lock the spin lock global_bh_lock, while the function will return the original value of the spin lock Global_BH_LOCK.

Therefore, if the global_bh_lock has been locked by a CPU (the CPU is definitely executing a BH function), SPIN_TRYLOCK () will return to 0 means the lock failed, in which case the current CPU is The BH function cannot be performed because the other CPU is executing the BH function, so the GOTO statement is executed to jump to the Resched block to schedule the BH function again on the current CPU. 2 Call the HardirQ_Trylock () function locks the current CPU to ensure that the current CPU is not in the hardware interrupt request service, if the lock fails, jump to the Resched_unlock block, so that the global_bh_lock is unlocked, and the BH function is re-scheduled once. 3 At this time, we can have a BH function on the current CPU at this time. Of course, the corresponding BH function pointer BH_BASE [NR] must be valid. 4 After returning from the BH function, first call the hardirq_endlock () function (actually what does not do, call it just to keep this plus, unlock the pair relationship), then release the spin lock global_bh_lock, the final function can return . 5Resched_unlock block: First release the spin lock Global_BH_LOCK, and then execute the Reched block. 6RESCHED program: When a CPU is executing the BH function, the current CPU cannot call the execution any BH function via the BH_Action () function, so by calling the mark_bh () function on the current CPU again, so that this The BH function is left when the next soft interrupt service is left. 6.3.4 BOTTOM HALF's original interface function (1) init_bh () function This function is used to register a specified BH function in the BH_BASE [] array, as shown below (kernel / Softirq.c): void init_bh (int Nr, void (* routine) (void)) {BH_BASE [NR] = routine; MB ();} (2) Remove_bh () function This function is used to log out of the specified function pointer in the BH_BASE [] array while Corresponding tasklet kills. As shown below (kernel / Softirq.c): void remove_bh (int NR) {tasklet_kill (BH_TASK_VEC NR); BH_BASE [NR] = NULL;} (3) Mark_BH () function This function is used to mark the current CPU BH function waits to execute. It actually adds the corresponding tasklet to the current CPU's Tasklet queue tasklet_hi_vec [cpu], then trigger the soft interrupt request Hi_SoftIRQ, as shown (include / Linux / interrupt.h): static inline void mark_bh (int NR) {tasklet_hi_schedule (BH_TASK_VEC NR);} 6.3.5 Predefined BH functions In 32 BH function pointers, most of them have been fixed for some common peripherals, such as: 0th BH function It is fixed to the clock interrupt.

转载请注明原文地址:https://www.9cbs.com/read-39680.html

New Post(0)