[In-depth understanding of Linux kernel lock] 2. Interrupt shielding

img
My circle: a gathering place for senior engineers
I am Dong Ge, a senior embedded software development engineer, engaged in embedded Linux driver development and system development, and worked for a Fortune 500 company!
Creation concept: Focus on sharing high-quality embedded articles, so that everyone can read something!
img

insert image description here

1. Interrupt and shield thoughts

Interrupt masking, as its name suggests, shields the CPUinterrupt response function to solve the race condition problem caused by concurrency.

What are the advantages and disadvantages of shielding interrupts before entering the critical section?

The benefits are :

  • Guaranteed not to be interrupted by interrupts when executing critical section code
  • At the same time, the process scheduling of the system is closely related to interrupts, which also limits the concurrency of system processes and solves the race condition problem caused by system process concurrency.

The disadvantages are :

  • LinuxIn the kernel, in addition to system process scheduling relying on interrupts, there are also many asynchronous I/Ooperations that rely on interrupts. Therefore, shielding interrupts for a long time is very dangerous and will seriously affect the system. Therefore, the critical section code is also required to be short.
  • Turning off interrupts can solve process scheduling and race conditions caused by interrupts, but these are all internal CPU, and for SMPsymmetric multiprocessors, it is still inevitable to receive other CPUinterrupts. Therefore, it does not solve the race condition caused by SMPmultipleCPU

Therefore, interrupt masking alone is usually not a recommended way to avoid race conditions

 

2. Implementation of Linux kernel interrupt shielding

2.1 API interface provided by the Linux kernel

Regarding interrupt masking, Linuxthe interfaces provided by the kernel are as follows:

local_irq_enable()				//	使能本CPU的中断
local_irq_disable()				//	禁止本CPU的中断
local_irq_save(flags)			//	禁止本CPU的中断,并保存CPU中断位的信息
local_irq_restore(flags)		//	使能本CPU的中断,并恢复CPU中断位的信息
local_bh_disable(void)			//	禁止本CPU底半部中断
local_bh_enable(void)    		//	使能本CPU底半部中断

 

2.2 API interface implementation analysis

Because interrupt masking is related to the underlying chip architecture, different architectures have different processing methods, let's take it as ARMan example

2.2.1 local_irq_enable

#define local_irq_enable()	do {
      
       raw_local_irq_enable(); } while (0)

#define raw_local_irq_enable()		arch_local_irq_enable()

#define arch_local_irq_enable arch_local_irq_enable
static inline void arch_local_irq_enable(void)
{
    
    
	asm volatile(
		"	cpsie i			@ arch_local_irq_enable"
		:
		:
		: "memory", "cc");
}

Function introduction : local_irq_enableThe function is used to set CPSRthe interrupt enable bit in the register to 1, so that CPUthe interrupt can be responded.

Related implementations :

asm: declares an inline assembly expression

cpsie i: Assembly instruction, set the bit CPSRof the register Ito allow this CPUresponse interrupt.

memory: Explain to the assembly that the memory has changed here, similar to the role of a memory barrier

cc: flag indicating that the condition code may be modified

Assembly code syntax: https://www.jianshu.com/p/57fef17149ae

 

2.2.2 arch_local_irq_disable

#define arch_local_irq_disable arch_local_irq_disable
static inline void arch_local_irq_disable(void)
{
    
    
	asm volatile(
		"	cpsid i			@ arch_local_irq_disable"
		:
		:
		: "memory", "cc");
}

Function introduction : arch_local_irq_disableThe function is used to set CPSRthe interrupt enable bit in the register to 0, thereby prohibiting CPUthe response to interrupt.

Related implementation : ditto

  • cpsid: It is an assembly instruction, which is used to clear CPSRthe interrupt flag of the register to disable the interrupt!

 

2.2.3 arch_local_irq_save

#define arch_local_irq_save arch_local_irq_save
static inline unsigned long arch_local_irq_save(void)
{
    
    
	unsigned long flags;

	asm volatile(
		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ arch_local_irq_save\n"
		"	cpsid	i"
		: "=r" (flags) : : "memory", "cc");
	return flags;
}

Function introduction : arch_local_irq_saveFunction, used to save the current interrupt status and disable interrupts.

Related implementations :

mrs %0 IRQMASK_REG_NAME_R: mrsThe instruction moves the value of the register IRQMASK_REG_NAME_Rspecified by the macro into a variable.IRQMASKflags

Detailed Explanation of MRS Commands

Summary of assembly commands

 

2.2.4 arch_local_irq_restore

/*
 * restore saved IRQ & FIQ state
 */
#define arch_local_irq_restore arch_local_irq_restore
static inline void arch_local_irq_restore(unsigned long flags)
{
    
    
	asm volatile(
		"	msr	" IRQMASK_REG_NAME_W ", %0	@ local_irq_restore"
		:
		: "r" (flags)
		: "memory", "cc");
}

Function introduction : arch_local_irq_restorefunction, used to restore the current interrupt status and open the interrupt.

Related implementation : ditto

 

Regarding local_bh_disablethe local_bh_enabletwo interfaces, it involves the bottom half of the interrupt mechanism, the content is more complicated, and it will be disassembled separately later!

 

3. Summary

This article mainly understands the following points:

  1. Interrupt Shielding Thoughts
  2. Advantages and Disadvantages of Interrupt Masking
  3. LinuxThe interrupt mask interface provided by the kernel
  4. Basic assembly implementation of interrupt mask

Like + follow, never get lost

img
Welcome to pay attention to Official Account & Planet [Embedded Art], original by Dong Ge!

Guess you like

Origin blog.csdn.net/dong__ge/article/details/131120463