Quoted from: http://blog.csdn.net/lizhibin1091666592/article/details/6976254
A basic principle of the kernel is that in the interrupt or atomic context, the kernel cannot access user space, and the kernel cannot sleep. That is to say, in this case, the kernel cannot call any function that may cause sleep. Generally, the atomic context refers to the interruption or soft interruption, and the holding of the spin lock. The kernel provides four macros to determine whether a disk is in these conditions: # define in_irq () (hardirq_count () // In handling hard interruptions # define in_softirq () (softirq_count ()) // In Soft Interrupt Processing # define in_interrupt () (irq_count () // in hard interrupt processing or Soft Interrupt Processing # define in_atomic () (preempt_count ()&~ Preempt_active )! = 0) // contains all the preceding conditions. The Count accessed by these four macros is thread_info-> preempt_count. This variable is actually a bitmask. The minimum 8 bits indicates the preemption count, which is usually modified by the spin_lock/spin_unlock, or the programmer enforces the modification. It also indicates that the maximum preemption depth allowed by the kernel is 256. The 8-15 bits indicate the Soft Interrupt count, which is usually modified by local_bh_disable/local_bh_enable. It also indicates that the maximum Soft Interrupt depth allowed by the kernel is 256. 16-27 represents the hard interrupt count, which is usually modified by enter_irq/exit_irq. It also indicates that the maximum hard interrupt depth allowed by the kernel is 4096. The 28th-bit flag is preempt_active. The code indicates: preempt_mask: 0x000000ffsoftirq_mask: 0x0000ff00hardirq_mask: 0x0fff0000. If the first four macros return 1, they are atomic context. kernel access to user space is not allowed and kernel sleep is not allowed, calls to any function that may cause sleep are not allowed. It also indicates that thread_info-> preempt_count is not 0, which tells the kernel that the preemption is disabled. However, for in_atomic (), it works well when preemption is enabled. It can tell whether the kernel currently holds a spin lock and whether preemption is disabled. However, if preemptible is not enabled, spin_lock does not modify preempt_count at all. Therefore, even if the kernel calls spin_lock and holds the spin lock, in_atomic () still returns 0, indicates that the kernel is in a non-atomic context. Therefore, any code that depends on in_atomic () to determine whether it is in the atomic context is problematic when preemption is prohibited.