In the Linux kernel (linux-4.14.12/mm/slab.c#3389), at first glance at the bottom of the code, it seems that L3389 have a bug, so I read around the interest of a bit local_irq_save/local_irq_ The source code of the restore.
/*linux-4.14.12/mm/slab.c#3389*/3377 Static__always_inlinevoid*3378Slab_alloc (structKmem_cache *cachep, gfp_t flags, unsignedLongcaller)3379 {3380UnsignedLongsave_flags;3381 void*OBJP;3389Local_irq_save (save_flags);3390OBJP =__do_cache_alloc (Cachep, flags);3391Local_irq_restore (save_flags);3399 returnOBJP;3400}
In L3380 and L3389, if Local_irq_save () is a function, there must be a bug, because Save_flags's variable address needs to be passed to Local_irq_save ().
3380 Long save_flags; 3389 Local_irq_save (Save_flags);
However,Local_irq_save () and Local_irq_restore () are not functions, but macros , so there is no bug.
1. Implementation of Local_irq_save () and Local_irq_restore ()
/*linux-4.14.12/include/linux/irqflags.h#139*/ the#ifdef config_trace_irqflags ... the #defineLocal_irq_save (Flags)111 Do { theRaw_local_irq_save (Flags); 113Trace_hardirqs_off (); the} while(0) the the117 #defineLocal_irq_restore (Flags)118 Do { 119 if(Raw_irqs_disabled_flags (Flags)) { -Raw_local_irq_restore (Flags); 121Trace_hardirqs_off (); 122}Else { 123trace_hardirqs_on (); 124Raw_local_irq_restore (Flags); the } 126} while(0)...135 #else/* ! Config_trace_irqflags * *...139 #defineLocal_irq_save (Flags) $ Do { 141Raw_local_irq_save (Flags); 142} while(0)143 #defineLocal_irq_restore (Flags) do {Raw_local_irq_restore (flags),} while (0)...146 #endif/* Config_trace_irqflags */
For the sake of simplicity, we are only concerned! The Config_trace_irqflags branch is just fine,
139 #define Local_irq_save (Flags) , 141 Raw_local_irq_save (flags); 142 while (0) 143 #define Local_irq_restore (Flags) do {Raw_local_irq_restore (flags),} while (0)
Thus, we can assume that Locale_irq_save ()/local_irq_restore () is equivalent to:
#define Local_irq_save (Flags) Raw_local_irq_save (flags)#define Local_irq_restore (Flags) RAW _local_irq_restore (Flags)
2. Implementation of Raw_local_irq_save () and Raw_local_irq_restore ()
/*linux-4.14.12/include/linux/irqflags.h#78*/ + #defineRaw_local_irq_save (Flags) - Do { theTypecheck (unsignedLong, flags); BayiFlags =Arch_local_irq_save (); the} while(0) the #defineRaw_local_irq_restore (Flags) - Do { -Typecheck (unsignedLong, flags); theArch_local_irq_restore (Flags); the} while(0)
About Macro Typecheck () does not explain, because it is very intuitive, is to ensure that the type of flags must be unsigned long. Thus, Raw_local_irq_save () and Raw_local_irq_restore () are equivalent to:
#define Raw_local_irq_save (flags) flags = Arch_local_irq_save ()#define Raw_local_irq_restore (flags) Arch_local_irq_restore (Flags)
The following is an example of the implementation of the functions of Arch_local_irq_save () and Arch_local_irq_restore () x86.
3. Arch_local_irq_save () and Arch_local_irq_restore () the implementation of these two functions on the x86
/*linux-4.14.12/arch/x86/include/asm/irqflags.h#70*/ - StaticInline Notrace unsignedLongArch_local_save_flags (void) in { the returnNative_save_fl (); the } About the StaticInline NotracevoidArch_local_irq_restore (unsignedLongflags) the { theNATIVE_RESTORE_FL (flags); +}
Clearly, it's just a matter of understanding the specific implementation of NATIVE_SAVE_FL () and NATIVE_RESTORE_FL ().
Implementation of 3.1 NATIVE_SAVE_FL ()
/*linux-4.14.12/arch/x86/include/asm/irqflags.h#16*/ - Staticinline unsignedLongNATIVE_SAVE_FL (void) - { -UnsignedLongflags; + - /** "=RM" is safe here, because "pops" adjusts the stack Before22 * It evaluates its effective address-- This was part of THE23 * documented behavior of the "Pop" instruction.24*/ -Asmvolatile("# __raw_save_flags\n\t" - "PUSHF; pop%0" -:"=rm"(Flags) -:/*No input*/ in:"Memory"); - to returnflags; +}
This is an inline assembly code, followed by a simple demo to explain.
Implementation of 3.2 NATIVE_RESTORE_FL ()
。。。 Not to be continued ....
Understanding the Linux kernel for interrupt saving and recovery