Only one old-style bottom half can run at any time, regardless of the number of CPUs
旧式的BH不能并行执行
Only one instance of each tasklet can run at any time. Different tasklets can run concurrently on different CPUs. This means that given any tasklet, there is no need to enforce any serialization because already it is enforced by the kernel: you cannot have multiple instances of the same tasklet running concurrently
一个tasklet不能和它自己并行,但是可以和其他的tasklet在不同的CPU上并行,所以它的执行不需要同步
Only one instance of each softirq can run at the same time on a CPU. However, the same softirq can run on different CPUs concurrently. This means that given any softirq you need to make sure that accesses to shared data by different CPUs use proper locking. To increase parallelization, the softirqs should be designed to access only per-CPU data as much as possible, reducing the need for locking considerably
一个softirq可以并行的在多个CPU上执行,但是同一时刻在同一个CPU上只有一个此softirq运行。因此要考虑同步问题。优化的做法是每个softirq只尽可能的访问本CPU的数据
Softirqs, like the old bottom halves, run with interrupts enabled and therefore can be suspended at any time to handle a new, incoming interrupt.
the kernel does not allow a new request for a softirq to run on a CPU if another instance of that softirq has been suspended on that CPU
Function/macro | Description |
---|---|
in_interrupt | in_interrupt returns TRUE if the CPU is currently serving a hardware or software interrupt, or preemption is disabled. |
in_softirq | in_softirq returns TRUE if the CPU is currently serving a software interrupt. |
in_irq | in_irq returns TRUE if the CPU is currently serving a hardware interrupt. |
In the section "Preemption ," and with the help of Figure 9-3 , you can see how these three routines are implemented. | |
softirq_pending | Returns TRUE if there is at least one softirq pending (i.e., scheduled for execution) for the CPU whose ID was passed as the input argument. |
local_softirq_pending | Returns TRUE if there is at least one softirq pending for the local CPU. |
__raise_softirq_irqoff | Sets the flag associated with the input softirq type to mark it pending. |
raise_softirq_irqoff | This is a wrapper around _ _raise_softirq_irqoff that also wakes up ksoftirqd when in_interrupt( ) returns FALSE. |
raise_softirq | This is a wrapper around raise_softirq_irqoff that disables hardware interrupts before calling it and restores them to their original status. |
_ _local_bh_enable local_bh_enable local_bh_disable | _ _local_bh_enable enables bottom halves (and thus softirqs/tasklets) on the local CPU, and local_bh_enable also invokes invoke_softirq if any softirq is pending and in_interrupt( ) returns FALSE. |
local_bh_disable disables bottom halves on the local CPU. | |
local_irq_disable local_irq_enable | Disable and enable interrupts on the local CPU. |
local_irq_save local_irq_restore | local_irq_save first saves the current state of interrupts on the local CPU and then disables them. |
local_irq_restore restores the state of interrupts on the local CPU thanks to the information previously saved with local_irq_save . | |
spin_lock_bh spin_unlock_bh | Acquire and release a spinlock, respectively. Both functions disable and then re-enable bottom halves and preemption during the operation |