Linux kernel spin lock + interrupt spin_lock_bh/spin_unlock_bh

Spin_lock_bh is usually used in processes to prohibit stealing and soft interrupts.

In spin_lock_bh(), local_bh_disable() will be called to disable the software interrupt of the current CPU. The function spin_unlock_bh() calls local_bh_enable() to enable the software interrupt of the local CPU. When the software interrupt is disabled, all the software interrupts of the local CPU will not be executed.

If a softirq shares data with the user context, there are two problems: first, the current user context may be interrupted by softirq; second, the critical section may be entered in another CPU. At this time spin_lock_bh() (include/linux/spinlock.h) has its place. It will disable softirqs on that CPU and then acquire the
lock. spin_unlock_bh() does the opposite job. (Due to historical reasons, the suffix'bh' has become a generic term for various lower parts, the latter being the old name for software interrupts. In fact, spin_lock_bh should be called spin_lock_softirq to be appropriate), note that you can also use spin_lock_irq() or spin_lock_irqsave( ), this will not only disable softirqs, but also disable hardware interrupts.

Tasklets and timers are actually a kind of softirq. From the perspective of locking, the status of tasklets and timers is equivalent.

Hard interrupts usually communicate with a tasklet or softirq. This usually involves putting a task in a certain queue and then taking it out by softirq. If a hardware interrupt service routine shares data with a softirq, there are two points to consider. First, the execution of softirq may be interrupted by a hardware interrupt; second, the critical section may be entered by a hardware interrupt on another CPU. This is where spin_lock_irq() comes in handy. It disables interrupts on that CPU and then acquires the lock. spin_unlock_irq() does the opposite job.
There is no need to use spin_lock_irq() in the hardware interrupt service routine, because softirq is impossible to execute when it is executing: it can use spin_lock(), which will be faster. The only exception is that another hardware interrupt service routine uses the same lock: spin_lock_irq() will disable that hardware interrupt.

Precautions for use of spin lock:

  • Because it is in the 自旋 state while waiting for the spin lock  , the holding time of the lock cannot be too long, it must be short, otherwise it will reduce the system performance. If the critical section is large and the running time is longer, other concurrent processing methods can be used, such as semaphores and mutexes

  • The critical section protected by the spin lock cannot call any API function that may cause the thread to sleep, otherwise it may cause a deadlock

  • You cannot apply for a spin lock recursively, because once you apply for a lock you are holding recursively, you have to 自旋wait for the lock to be released. However, you are in a 自旋state and cannot release the lock at all. The result is that I locked myself dead!

  • When writing the driver, we must consider the portability of the driver. Therefore, no matter whether you use a single-core or multi-core SOC, use it as a multi-core SOC to write the driver.

Guess you like

Origin blog.csdn.net/wangquan1992/article/details/108960171