Linux tasklet Analysis notes

Source: Internet
Author: User
Tags bit set

Linux tasklet Analysis notes

Chapter 1:

During initialization, the driver creates a tasklet through the task_init function, then calls the tasklet_schedule function to place the tasklet in the header of the tasklet_vec linked list, and wakes up the background thread ksoftirqd. When the backend thread ksoftirqd runs the call _ do_softirq, The tasklet_action function corresponding to the interrupt number tasklet_softirq in the softirq_vec table is executed, and then tasklet_action traverses the tasklet_vec linked list, call the function of each tasklet to complete the Soft Interrupt operation.

The following is an analysis of the functions tasklet_init and tasklet_schedule:

The tasklet_init function initializes a tasklet. Its Parameter T is the tasklet described in the tasklet_struct structure, and the parameter (* func) is the soft interrupt response function.

Void tasklet_init (struct tasklet_struct * t, void (* func) (unsigned long), unsigned long data)
{
T-> next = NULL;
T-> state = 0;
Atomic_set (& T-> count, 0 );
T-> func = func;
T-> DATA = data;
}

The driver calls the tasklet_schedule function to run tasklet.

Static inline void tasklet_schedule (struct tasklet_struct * t)
{
If (! Test_and_set_bit (tasklet_state_sched, & T-> State ))
_ Tasklet_schedule (t );
}

Function _ tasklet_schedule obtains the tasklet_vec linked list of the current CPU, and executes the tasklet_softirq Soft Interrupt.

Void fastcall _ tasklet_schedule (struct tasklet_struct * t)
{
Unsigned long flags;

Local_irq_save (flags );
T-> next = _ get_cpu_var (tasklet_vec). List;
_ Get_cpu_var (tasklet_vec). List = T;
Raise_softirq_irqoff (tasklet_softirq );
Local_irq_restore (flags );
}

The raise_softirq_irqoff function sets the Soft Interrupt NR to the suspended state, and wakes up the thread ksoftirqd when there is no interruption. The raise_softirq_irqoff function must be run in case of Guanzhong disconnection.

Inline fastcall void raise_softirq_irqoff (unsigned int nr)
{
_ Raise_softirq_irqoff (NR );

/*
* If we're in an interrupt or softirq, we're done
* (This also catches softirq-disabled Code). We will
* Actually run the softirq once we return from
* The IRQ or softirq.
*
* Otherwise we wake up ksoftirqd to make sure we
* Schedule the softirq soon.
*/
If (! In_interrupt ())
Wakeup_softirqd ();
}

The following are the definitions of tasklet_struct and softirq_action.

Struct tasklet_struct
{
Struct tasklet_struct * next;
Unsigned long state;
Atomic_t count;
Void (* func) (unsigned long );
Unsigned long data;
};

Struct softirq_action
{
Void (* Action) (struct softirq_action *);
Void * data;
};

Excerpt from Linux kernel analysis and programming>
Http://hi.baidu.com/ryderlee/blog/item/ceeec316e8d1f318962b431a.html
1. tasklet can be run earlier than normal shedule by hi-schedule and general schedule;
2. The same tasklet can be simultaneously used by hi-schedule and General Schedule;
3. If the same tasklet is concurrently hi-schedule multiple times, it is equivalent to only hi-shedule once, because when tasklet is not running, hi-schedule-
Shedule is meaningless for the same tasklet, and the previous tasklet will be washed out;
4. For general shedule, the same as above.
5. Different tasklets run in parallel instead of in the shedule order.
6. tasklet running time:
A. If schedule tasklet is interrupted, it runs immediately after the interruption ends;
B. If the CPU is busy, it will not run immediately after the interruption;
C. Do not interrupt shedule tasklet;
D. soft or hard interruptions are running;
E. Return from system call; (only when process is idle)
F. Return from the exception;
G. debug program scheduling. (When ksoftirqd is running, the CPU is idle)
7. taskelet's hi-schedule uses softirq 0. Generally, schedule uses softirq 30;
8. tasklet's run at the end of the next time tick. (Softirq will run when the outermost layer is interrupted, and softirq of shedule or shedule will be called after it is interrupted .)
In summary: tasklet can ensure that the running time is (1000/Hz) MS, generally 10 ms. Tasklet is called after the CPU is idle or interrupted.

Chapter 2:

The tasklet mechanism is a special Soft Interrupt. Tasklet is originally meant to be a small task.
Is a short piece of executable code, and usually appears in the form of a function. Soft Interrupt vectors hi_softirq and
Tasklet_softirq is implemented using the tasklet mechanism.
To some extent, the tasklet mechanism is an extension of the BH mechanism in the Linux kernel. Introduced in kernel 2.4
After the softirq mechanism, the original BH mechanism is integrated into the softirq mechanism through the tasklet mechanism.
In the Framework. It is precisely because of this historical extension that the tasklet mechanism has some problems with the soft interrupt in the general sense.
However, they present the following two notable features:
1. Unlike General soft interruptions, A tasklet code can only run on one CPU at a time, unlike
A general Soft Interrupt service function (that is, the action function pointer in the softirq_action structure) -- in the same
It can be concurrently executed by multiple CPUs.
2. Unlike the BH mechanism, different tasklet codes can be concurrently executed on multiple CPUs at the same time, unlike
The BH mechanism must be strictly serialized in that way (that is, at the same time the system can only have one CPU to execute the BH Function
Number ).
Linux uses the data structure tasklet_struct to describe a tasklet. The data structure is defined in
Include/Linux/interrupt. h header file. As follows:
Struct tasklet_struct
{
Struct tasklet_struct * next;
Unsigned long state;
Atomic_t count;
Void (* func) (unsigned long );
Unsigned long data;
};
The meaning of each member is as follows:
(1) Next pointer: pointer to the next tasklet.
(2) State: defines the current state of the tasklet. This 32-bit unsigned long integer currently only uses
Bit [1] and bit [0] status bits. Bit [1] = 1 indicates that the tasklet is currently in
It is executed on the CPU and only makes sense to the SMP system. It is used to prevent multiple CPUs from executing one
Tasklet occurs. Bit [0] = 1 indicates that the tasklet has been scheduled to wait for execution. For the two
The macro definition of the status bit is as follows (Interrupt. h ):
Enum
{
Tasklet_state_sched,/* tasklet is scheduled for execution */
Tasklet_state_run/* tasklet is running (SMP only )*/
};
(3) Atomic count: The reference count value of this tasklet. Note! Only when count is equal to 0,
Tasklet code segment can be executed, that is, tasklet is enabled at this time; If count is not zero, this
Tasklet is disabled. Anyone who wants to execute a tasklet code segment must first check its count
Whether the Member is 0.
(4) function pointer FUNC: points to the executable tasklet code segment in the form of a function.
(5) Data: The function func parameter. This is a 32-bit unsigned integer.
For example, it is interpreted as an address value pointing to a user-defined data structure.
In Linux, the interrupt. h header file defines two auxiliary tools used to define the tasklet_struct Structure Variables.
MACRO:
# Define declare_tasklet (name, func, data )/
Struct tasklet_struct name = {null, 0, atomic_init (0), func, data}
# Define declare_tasklet_disabled (name, func, data )/
Struct tasklet_struct name = {null, 0, atomic_init (1), func, data}
Obviously, from the source code above, we can see that the tasklet defined by the declare_tasklet macro is enabled during initialization.
Enabled because its count member is 0. Which is defined by the declare_tasklet_disabled macro
Tasklet is disabled at the beginning because its count is equal to 1.
Here, the tasklet State refers to two aspects: (1) the running state represented by the State member; (2) the Count member.
Determines the enable/disable status.
(1) Changing the running status of a tasklet
Bit [0] In the State member indicates whether a tasklet has been scheduled to wait for execution, and bit [1] indicates
Whether the tasklet is being executed on a CPU. A change in the state variable must be an atomic operation because
This operation can be performed by defining the bit operations in the include/ASM/bitops. h header file.
Because bit [1] (tasklet_state_run) is only meaningful to the SMP system
The interrupt. h header file explicitly defines the operations on the tasklet_state_run bit. As follows:
# Ifdef config_smp
# Define tasklet_trylock (t )(! Test_and_set_bit (tasklet_state_run, & (t )-
> State ))
# Define tasklet_unlock_wait (t) while (test_bit (tasklet_state_run, & (t )-
> State) {/* nothing */}
# Define tasklet_unlock (t) clear_bit (tasklet_state_run, & (t)-> state)
# Else
# Define tasklet_trylock (t) 1
# Define tasklet_unlock_wait (t) do {} while (0)
# Define tasklet_unlock (t) do {} while (0)
# Endif
Obviously, in the SMP system, the tasklet_trylock () Macro will put the state in a tasklet_struct Structure Variable
The bit [1] bit in the member is set to 1, and the non-bit of bit [1] is also returned. Therefore, if the bit [1] bit is original
If the value is 1 (indicating that another CPU is executing the tasklet code), the tasklet_trylock () macro returns
0 indicates that the lock is unsuccessful. If the original value of bit [1] is 0, then the tasklet_trylock () Macro
The return value 1 indicates that the lock is successful. In a single CPU system, the tasklet_trylock () macro always returns 1.
Any program that wants to execute a tasklet code must first call the macro tasklet_trylock () to try
Tasklet (that is, set the tasklet_state_run bit), and can only be locked successfully.
Execute this tasklet. Suggestions! Even if your program runs only on the CPU system, you need to execute tasklet before
Call the tasklet_trylock () macro to make your code portable.
In the SMP system, the tasklet_unlock_wait () Macro will continuously test the value of the tasklet_state_run bit,
Until the value of this bit changes to 0 (that is, it waits until it is unlocked). If: cpu0 is executing the code of tasklet
During this period, cpu1 also wants to execute the code of tasklet A, but cpu1 finds the tasklet_state_run bit of tasklet.
It can use the tasklet_unlock_wait () macro to wait for tasklet A to be unlocked (that is
Tasklet_state_run bit is cleared ). In a single CPU system, this is an empty operation.
Macro tasklet_unlock () is used to unlock a tasklet, And the tasklet_state_run bit is also cleared.
Zero. In a single CPU system, this is an empty operation.
(2) enable/disable a tasklet
Enable and disable operations are always called in pairs. The tasklet_disable () function is as follows:
(Interrupt. h ):
Static inline void tasklet_disable (struct tasklet_struct * t)
{
Tasklet_disable_nosync (t );
Tasklet_unlock_wait (t );
}
The tasklet_disable_nosync () function is also a static inline function, which simply uses atomic operations
The value of the count member variable is reduced by 1. As shown below (Interrupt. h ):
Static inline void tasklet_disable_nosync (struct tasklet_struct * t)
{
Atomic_inc (& T-> count );
}
The tasklet_enable () function is used to enable a tasklet, as shown below (Interrupt. h ):
Static inline void tasklet_enable (struct tasklet_struct * t)
{
Atomic_dec (& T-> count );
}
The tasklet_init () function is used to initialize a specified tasklet descriptor. The source code is as follows:
(Kernel/softirq. C ):
Void tasklet_init (struct tasklet_struct * t,
Void (* func) (unsigned long), unsigned long data)
{
T-> func = func;
T-> DATA = data;
T-> state = 0;
Atomic_set (& T-> count, 0 );
}
The tasklet_kill () function is used to kill a scheduled tasklet and restore it to an unscheduled state.
Status. The source code is as follows (kernel/softirq. C ):
Void tasklet_kill (struct tasklet_struct * t)
{
If (in_interrupt ())
Printk ("attempt to kill tasklet from interrupt/N ");
While (test_and_set_bit (tasklet_state_sched, & T-> State )){
Current-> state = task_running;
Do {
Current-> Policy | = sched_yield;
Schedule ();
} While (test_bit (tasklet_state_sched, & T-> State ));
}
Tasklet_unlock_wait (t );
Clear_bit (tasklet_state_sched, & T-> State );
}
Multiple tasklets can be linked to a one-way pair column through the next member pointer in the tasklet descriptor. To this end,
Linux defines the data structure tasklet_head in the header file include/Linux/interrupt. h.
A tasklet pointer to the column header. As follows:
Struct tasklet_head
{
Struct tasklet_struct * List;
} _ Attribute _ (_ aligned _ (smp_cache_bytes )));
Although the tasklet mechanism is specific to the implementation of Soft Interrupt vectors hi_softirq and tasklet_softirq
The tasklet mechanism is still within the framework of softirq. Therefore, its design and implementation are still required.
The idea of "who triggers and who executes" must be adhered. Therefore, Linux defines
Tasklet indicates that each CPU is responsible for executing the tasklet column. As shown below
(Kernel/softirq. C ):
Struct tasklet_head tasklet_vec [nr_cpus] _ cacheline_aligned;
Struct tasklet_head tasklet_hi_vec [nr_cpus] _ cacheline_aligned;
Here, the tasklet_vec [] array is used for the soft interrupt vector tasklet_softirq, and tasklet_hi_vec []
The array is used for the soft interrupt vector hi_softirq. That is, if the cpui (0 ≤ I ≤ NR_CPUS-1) triggers a Soft Interrupt
If the vector tasklet_softirq is used, every tasklet in the tasklet_vec [I] column will be in the cpui service.
Cpui executes the soft interrupt vector tasklet_softirq. Similarly, if cpui (0 ≤ I ≤ nr_cpus-
1) when the soft interrupt vector hi_softirq is triggered, every tasklet in the queue tasklet_vec [I] Will
Cpui is executed by cpui when serving the soft interrupt vector hi_softirq.
How each tasklet in the queue tasklet_vec [I] And tasklet_hi_vec [I] is executed by the cpui
? The key is the Soft Interrupt Service Program of the Soft Interrupt vectors tasklet_softirq and hi_softirq --
Tasklet_action () and tasklet_hi_action () functions. Next we will analyze these two functions.
Linux provides dedicated trigger functions and soft interrupt services for the Soft Interrupt vectors tasklet_softirq and hi_softirq.
Function. The tasklet_schedule () and tasklet_hi_schedule () functions are used in the current
The Soft Interrupt vectors tasklet_softirq and hi_softirq are triggered on the CPU, and the specified tasklet is added to the current CPU.
Wait for execution in the corresponding tasklet queue. Tasklet_action () and tasklet_hi_action ()
The functions are soft interrupt service functions of the Soft Interrupt vectors tasklet_softirq and hi_softirq respectively. In the initialization letter
In softirq_init (), the descriptors softirq_vec [0] And softirq_vec corresponding to the two Soft Interrupt Vectors
The action function pointer in [3] is initialized to the tasklet_hi_action () and function respectively.
Tasklet_action ().
(1) trigger function tasklet_schedule () of the soft interrupt vector tasklet_softirq ()
This function is an inline function in the include/Linux/interrupt. h header file. The source code is as follows:
Description:
Static inline void tasklet_schedule (struct tasklet_struct * t)
{
If (! Test_and_set_bit (tasklet_state_sched, & T-> State )){
Int CPU = smp_processor_id ();
Unsigned long flags;
Local_irq_save (flags );
T-> next = tasklet_vec [CPU]. List;
Tasklet_vec [CPU]. List = T;
_ Cpu_raise_softirq (CPU, tasklet_softirq );
Local_irq_restore (flags );
}
}
The parameter t of this function points to the tasklet to be executed on the current CPU. Note the function as follows:
① Call the test_and_set_bit () function to set the bit [0] bit of the State member variable of the tasklet to be scheduled (also
That is, set tasklet_state_sched bit) to 1. This function also returns the original tasklet_state_sched bit.
Value. Therefore, if the original value of bit [0] is already 1, it indicates that this tasklet has been scheduled to another
The CPU goes up and waits for execution. Because a tasklet can only be executed by one CPU at a time
The tasklet_schedule () function returns a result without doing anything. Otherwise, continue the following scheduling operation.
② First, call the local_irq_save () function to disable the current CPU interruption.
The CPU is run atomically.
③ Add the tasklet to be scheduled to the header of the tasklet queue corresponding to the current CPU.
④ Next, call the _ cpu_raise_softirq () function to trigger the soft interrupt request on the current CPU.
Tasklet_softirq.
⑤ Call the local_irq_restore () function to interrupt the current CPU.
(2) Service Program tasklet_action () of the soft interrupt vector tasklet_softirq ()
The tasklet_action () function is the link between the tasklet mechanism and the soft interrupt vector tasklet_softirq. Exactly
This function puts each tasklet in the tasklet queue of the current CPU into the current CPU for execution. Implementation of this function
In the kernel/softirq. c file, the source code is as follows:
Static void tasklet_action (struct softirq_action *)
{
Int CPU = smp_processor_id ();
Struct tasklet_struct * List;
Local_irq_disable ();
List = tasklet_vec [CPU]. List;
Tasklet_vec [CPU]. List = NULL;
Local_irq_enable ();
While (list! = NULL ){
Struct tasklet_struct * t = List;
List = List-> next;
If (tasklet_trylock (t )){
If (atomic_read (& T-> count) = 0 ){
Clear_bit (tasklet_state_sched, & T-> State );
T-> func (t-> data );
/*
* Talklet_trylock () uses test_and_set_bit that imply
* An MB when it returns zero, thus we need the explicit
* MB only here: while closing the critical section.
*/
# Ifdef config_smp
Smp_mb _ before_clear_bit ();
# Endif
Tasklet_unlock (t );
Continue;
}
Tasklet_unlock (t );
}
Local_irq_disable ();
T-> next = tasklet_vec [CPU]. List;
Tasklet_vec [CPU]. List = T;
_ Cpu_raise_softirq (CPU, tasklet_softirq );
Local_irq_enable ();
}
}
Note:
① First, when the current CPU is disconnected, read the tasklet queue header pointer of the current CPU "atomically,
Save it to the local variable list pointer, and then set the current CPU tasklet queue header pointer to null,
In theory, the current CPU will no longer have tasklet to be executed (but the actual result is not necessarily the same,
As shown in the following figure ).
② Then, use a while {} loop to traverse the tasklet queue pointed to by the list. Each element in the queue is
Is the tasklet that will be executed on the current CPU. The steps for executing the loop body are as follows:
L The pointer T is used to represent the current queue element, that is, the tasklet to be executed.
L update the list pointer to list-> next so that it points to the next tasklet to be executed.
L use the tasklet_trylock () macro to try to lock the tasklet (pointed by pointer T) to be executed, as shown in figure
If the lock is successful (no other CPU is currently executing this tasklet), the atomic READ function is used.
Atomic_read () further judges the value of the count member. If count is 0, this tasklet is allowed for execution.
So: (1) first clear the tasklet_state_sched bit; (2) then, call this tasklet executable
Row function func; (3) executes the barrier () operation; (4) calls the macro tasklet_unlock () to clear
Tasklet_state_run bit. (5) Finally, execute the continue statement to skip the following steps and return to the while loop.
Continue to traverse the next element in the queue. If the Count value is not 0, the tasklet is not allowed to run.
Call tasklet_unlock () to clear the tasklet_state_run bit set with tasklet_trylock.
L if tasklet_trylock () fails to be locked, or the execution is not allowed because the Count value of the current tasklet is not 0
When running, we must re-release this tasklet to the tasklet queue of the current CPU to stay under this CPU
The soft interrupt vector tasklet_softirq is executed again. Perform these steps: (1) first turn off the CPU
To guarantee the atomicity of the following operations. (2) re-release the tasklet to the tasklet queue of the current CPU.
(3) Call the _ cpu_raise_softirq () function to trigger a soft interrupt request on the current CPU.
Tasklet_softirq; (4) interrupt.
L finally, return to the while loop to continue traversing the queue.
(3) trigger function of Soft Interrupt vector hi_softirq tasklet_hi_schedule ()
This function is almost the same as tasklet_schedule (). The source code is as follows:
(Include/Linux/interrupt. h ):
Static inline void tasklet_hi_schedule (struct tasklet_struct * t)
{
If (! Test_and_set_bit (tasklet_state_sched, & T-> State )){
Int CPU = smp_processor_id ();
Unsigned long flags;
Local_irq_save (flags );
T-> next = tasklet_hi_vec [CPU]. List;
Tasklet_hi_vec [CPU]. List = T;
_ Cpu_raise_softirq (CPU, hi_softirq );
Local_irq_restore (flags );
}
}
(4) Soft Interrupt vector hi_softirq service function tasklet_hi_action ()
This function is almost the same as the tasklet_action () function. Its source code is as follows (kernel/softirq. C ):
Static void tasklet_hi_action (struct softirq_action *)
{
Int CPU = smp_processor_id ();
Struct tasklet_struct * List;
Local_irq_disable ();
List = tasklet_hi_vec [CPU]. List;
Tasklet_hi_vec [CPU]. List = NULL;
Local_irq_enable ();
While (list! = NULL ){
Struct tasklet_struct * t = List;
List = List-> next;
If (tasklet_trylock (t )){
If (atomic_read (& T-> count) = 0 ){
Clear_bit (tasklet_state_sched, & T-> State );
T-> func (t-> data );
Tasklet_unlock (t );
Continue;
}
Tasklet_unlock (t );
}
Local_irq_disable ();
T-> next = tasklet_hi_vec [CPU]. List;
Tasklet_hi_vec [CPU]. List = T;
_ Cpu_raise_softirq (CPU, hi_softirq );
Local_irq_enable ();
}
}
The bottom half mechanism is retained in the new softirq mechanism and is part of the softirq framework. Actually
It also seems more complicated because it is incorporated into the softirq framework through the tasklet mechanism as an intermediary bridge.
. In fact, the soft interrupt vector hi_softirq is used by the kernel to execute the BH function.
The original 32 BH function pointers are reserved and are defined in the kernel/softirq. c file:
Static void (* bh_base [32]) (void );
However, each BH function has a tasklet, And the executable function func of tasklet calls
Corresponding BH function (the func function parameter specifies which BH function to call ). Corresponding to 32 BH function pointers
Tasklet is defined as follows (kernel/softirq. C ):
Struct tasklet_struct bh_task_vec [32];
The tasklet array above makes the system global, which can be seen for all CPUs. Since there can be only one
The CPU is executing the BH function, so 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;
In softirq's initialization function softirq_init (), set each of the bh_task_vec [32] Arrays
The func function pointer in tasklet is set to direct to the same function bh_action, and the data member (that is, func
Function call parameters) is set to the index value of the tasklet in the array, as shown below:
Void _ init softirq_init ()
{
......
For (I = 0; I <32; I ++)
Tasklet_init (bh_task_vec + I, bh_action, I );
......
}
Therefore, the bh_action () function calls the BH function specified by the parameter accordingly. This function is used to connect tasklet
Mechanism and bottom half mechanism.
The source code of this function is as follows (kernel/softirq. C ):
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 );
}
Note the function as follows:
① First, call the spin_trylock () function to try to lock the spin lock global_bh_lock.
The original value of the spin lock global_bh_lock is returned. Therefore, if global_bh_lock is already used by a CPU
Locks instead of 0 (the CPU must be executing an BH function), then the value of spin_trylock () is 0.
Lock failed. In this case, the current CPU cannot execute the BH function, because another CPU is executing the BH function.
So execute the GOTO statement to jump to the resched program segment to schedule the BH function again on the current CPU.
② Call the hardirq_trylock () function to lock the current CPU and ensure that the current CPU is not in the hardware interrupt request service.
If the lock fails, jump to the resched_unlock block to unlock global_bh_lock first.
Re-schedule the BH function once.
③ At this time, we can safely execute the BH function on the current CPU. Of course, the corresponding BH function pointer
Bh_base [Nr] must be valid.
④ After returning data from the BH function, call the hardirq_endlock () function first (in fact, it does nothing,
In order to maintain the pairing relationship between the accesskey and the unlock), and then remove the spin lock global_bh_lock, the final function can return
Back.
⑤ Resched_unlock section: First remove the spin lock global_bh_lock and then execute the reched section.
⑥ Resched program segment: When a CPU is executing the BH function, the current CPU cannot pass the bh_action () function.
Number to call and execute any BH function, so by calling the mark_bh () function, re-schedule one on the current CPU
So that this BH function will be executed during the next Soft Interrupt.
(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 deregister the specified function pointer in the bh_base [] array and kill the corresponding tasklet.
As follows (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 as being executed by an BH function. It actually calls
The tasklet_hi_schedule () function adds the corresponding tasklet to the tasklet queue of the current CPU.
Tasklet_hi_vec [CPU], and then trigger the soft interrupt request hi_softirq, as shown below:
(Include/Linux/interrupt. h ):
Static inline void mark_bh (INT nr)
{
Tasklet_hi_schedule (bh_task_vec + nR );
}
Among the 32 BH function pointers, most of them have been fixed for some common peripherals, for example, 0th BH functions are fixed.
Used for clock interruption. Linux defines these used files in the header file include/Linux/interrupt. h.
The BH function is introduced as follows:
Enum {
Timer_bh = 0,
Tqueue_bh,
Digi_bh,
Serial_bh,
Riscom8_bh,
Specialix_bh,
Export ra_bh,
Esp_bh,
Scsi_bh,
Immediate_bh,
Cyclades_bh,
Cm206_bh,
Js_bh,
Macserial_bh,
Isicom_bh
};

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.