Synchronization mechanism of the Linux kernel---spin lock

Source: Internet
Author: User
Tags mutex semaphore

Spin Lock thinking: http://bbs.chinaunix.net/thread-2333160-1-1.html

recently in See Song Baohua "device driver Development detailed" Second edition, see the Spin lock part, some doubts, so come to ask everyone.
Here are some of the ideas I've drawn from some of the web's information, whether it's right or not, and what we're talking about:
(1) There are three implementations of spin locks on Linux:
1. In a single CPU, cannot preempt the kernel, the spin lock is an empty operation.
2. In a single CPU, can preempt the kernel, the spin lock is implemented as "Prohibit kernel preemption", does not implement "spin".
3. In multi-CPU, can preempt the kernel, the spin lock is implemented as "Prohibit kernel preemption" + "spin".
(2) about preemptive kernel and non-preemptive kernel:
In a non-preemptive kernel, if a process is running in the kernel state, it will be switched only in the following two scenarios:
1. Its run is complete (return to user space)
2. Proactively make up the CPU (that is, the active call to schedule or the task blocking in the kernel-this also causes the call to schedule)

In a preemptive kernel, if a process is running in the kernel state, it will be switched only in the following four scenarios:
1. Its run is complete (return to user space)
2. Proactively make up the CPU (that is, the active call to schedule or the task blocking in the kernel-this also causes the call to schedule)
3. When the interrupt handler is executing and before the kernel space is returned (at this point the preemption flag Premptcount must be 0).
4. When the kernel code is once again preemptive, such as unlocking and enabling soft interrupts.

In Song Baohua's book, it is mentioned that when you use a spin lock, you avoid using it to protect "containing code that causes blocking" because blocking means switching processes. This is confusing to me. Since the use of spin locks in a preemptive kernel is a "no kernel preemption", since the "forbidden kernel preemption" happens, how does the process switch?
Now that's what I'm thinking: banning kernel preemption just turns off the "preemption flag" instead of banning process switching. Process scheduling occurs when an explicit use of schedule or process blocking (which also causes the call to schedule).

Here are some ideas: Song Baohua's book says that when a spin lock is used to protect a critical area, a deadlock occurs when a critical section is blocked due to "containment-induced blocking code", which causes the process to switch, and if another process attempts to acquire the spin lock.
personally, deadlocks can occur only in multi-CPU situations where the kernel can be preempted. In the case of a single CPU, the kernel can be preempted or not preempted, and there will be no deadlock, but the spin lock fails at this time (i.e., the function of protecting the critical section cannot be achieved). This is because the multi-CPU preemption kernel implements the "spin", which causes deadlocks, and a single CPU can preempt or not preempt the kernel, does not implement "spin", only "Prohibit kernel preemption", so there is no deadlock, but there will be unprotected repeated access to the critical section of the situation (that is, unable to achieve the protection of the critical section)

The above views are only personal ideas, inappropriate, please also point out, thank you.



Five, Spin lock (Spinlock)

A spin lock is a bit like a mutex, except that the spin lock does not cause the caller to sleep, and if the spin lock has been held by another execution unit, the caller has been circulating there to see if the spin lock's hold has released the lock, and the word "spin" is named.

Since spin-lock users generally keep the lock time very short, it is necessary to choose a spin instead of sleep, and the spin lock is much more efficient than a mutex.

Semaphores and read and write semaphores are suitable for long periods of time, they cause the caller to sleep, so they can be used only in the context of the process (_trylock variants can be used in the interrupt context), and the spin lock is suitable for situations where the hold time is very short and is used in any context.

If the protected shared resource is accessed only in the context of the process, it is appropriate to use semaphores to protect the shared resource, and if access to the common lane resource is very short, the spin lock can. However, a spin lock must be used if the protected shared resource needs to break context access, including the bottom half of the interrupt handling handle and the top half of the soft interrupt.

The spin lock retention period is a preemption failure, while the semaphore and read/write semaphore retention period can be preempted. spin locks are only really needed if the kernel is preempted or SMP, and all operations on the spin lock are empty operations under a single CPU and non-preemptive kernel.

Like a mutex, an execution unit that accesses a shared resource protected by a spin lock must first obtain a lock, which must be released after the shared resource has been accessed. If no execution unit holds the lock when acquiring a spin lock, the lock is immediately obtained, and if the lock has a hold when the spin lock is acquired, then the acquire lock operation will spin there until the lock is released by the hold of the spin lock .

Whether it is a mutex or a spin lock, there can be at most one hold at any time, and it is said that at most one execution unit can acquire a lock at any time.

The spin lock APIs are:

Spin_lock_init (x)

This macro is used to initialize the spin lock x. Spin locks must be initialized before they are actually used. The macro is used for dynamic initialization.

Define_spinlock (x)

The macro declares a spin lock x and initializes it. The macro is defined for the first time in 2.6.11 and does not have the macro in the previous kernel.

Spin_lock_unlocked

This macro is used to statically initialize a spin lock.

Define_spinlock (x) is equivalent to spinlock_t x = spin_lock_unlockedspin_is_locked (x)

The macro is used to determine if the spin lock x has been held by an execution unit (that is, locked), and if so, returns True, otherwise false.

Spin_unlock_wait (x)

The macro is used to wait for the spin lock X to become not persisted by any execution unit, and if no execution unit holds the spin lock, the macro returns immediately, otherwise it will loop there until the spin lock is released by the hold.

Spin_trylock (Lock)

The macro tries to obtain a spin lock lock, and if it can get the lock immediately, it gets the lock and returns to true, otherwise it cannot immediately obtain the lock and immediately returns false. It does not spin to wait for lock to be released.

Spin_lock (Lock)

the macro is used to obtain a spin lock lock, and if it is able to get the lock immediately, it returns immediately, otherwise it will spin out there until the spin lock is released by the hold, at which point it gets the lock and returns. In short, only it gets a lock to return.

Spin_lock_irqsave (lock, flags)

The macro obtains a spin lock while saving the value of the flag register to the variable flags and fails the local interrupt.

SPIN_LOCK_IRQ (Lock)

the macro is similar to Spin_lock_irqsave, except that the macro does not save the value of the flag register .

SPIN_LOCK_BH (Lock)

The macro fails the local soft interrupt while the spin lock is obtained.

Spin_unlock (Lock)

The macro releases the spin lock lock, which is paired with Spin_trylock or Spin_lock. If Spin_trylock returns False, it indicates that no spin lock is obtained, so it is not necessary to use Spin_unlock release.

Spin_unlock_irqrestore (lock, flags)

The macro releases the spin lock lock while also restoring the value of the flag register to the variable flags saved value. It is paired with the Spin_lock_irqsave.

SPIN_UNLOCK_IRQ (Lock)

This macro releases the spin lock lock while also enabling local interrupts. It is paired with the Spin_lock_irq app .

SPIN_UNLOCK_BH (Lock)

the macro releases the spin lock lock while also enabling local soft interrupts. It is paired with the Spin_lock_bh .

Spin_trylock_irqsave (lock, flags)
if the macro obtains a spin lock lock, it will also save the value of the flag register to the variable flags and fail the local interrupt, and if the lock is not obtained, it does nothing.

So if you can get the lock immediately, it is equivalent to Spin_lock_irqsave, and if you cannot get the lock, it is equivalent to Spin_trylock. If the macro obtains the spin lock lock, it needs to be released using Spin_unlock_irqrestore .

SPIN_TRYLOCK_IRQ (Lock)

The macro is similar to Spin_trylock_irqsave, except that the macro does not save the flag register. If the macro obtains a spin lock lock, it needs to be released using SPIN_UNLOCK_IRQ.

SPIN_TRYLOCK_BH (Lock)

if the macro obtains a spin lock, it will also fail the local soft interrupt. If you can't get a lock, it doesn't do anything . Therefore, if a lock is obtained, it is equivalent to SPIN_LOCK_BH, and if not, it is equivalent to Spin_trylock. If the macro gets a spin lock, it needs to be freed using SPIN_UNLOCK_BH.

Spin_can_lock (Lock)

the macro is used to determine if the spin lock lock can be locked , and it is actually spin_is_locked reversed. If lock is not locked, it returns True, otherwise, false is returned. The macro is defined for the first time in 2.6.11 and does not have the macro in the previous kernel.

There are several versions of the spin lock and release spin lock, so it is necessary to let the reader know what version of the macro to use to obtain and release the lock in what case.

if a protected shared resource is accessed only in process context access and soft interrupt context, then when the shared resource is accessed in the context of the process, it may be interrupted by a soft interrupt that may enter the soft interrupt context to access the protected shared resource, so access to the shared resource must use Spin_ for this case LOCK_BH and Spin_unlock_bh to protect .

of course, using SPIN_LOCK_IRQ and SPIN_UNLOCK_IRQ as well as Spin_lock_irqsave and Spin_unlock_irqrestore can also, they fail the local hard interrupt, and the fail hard interrupt implicitly also fails the soft interrupt. But using SPIN_LOCK_BH and SPIN_UNLOCK_BH is the most appropriate, it is faster than the other two .

If the protected shared resource is accessed only in the process context and in the Tasklet or timer context, then the same macro that obtains and releases the lock should be used, as the Tasklet and timer are implemented with soft interrupts.

If a protected shared resource is accessed only in a Tasklet or timer context, then no spin lock is required because the same tasklet or timer can only run on one CPU, even in an SMP environment. The Tasklet actually binds the Tasklet to the current CPU when the tasklet_schedule tag is called, so the same tasklet is never likely to run on the other CPU at the same time.

The timer is also used to Add_timer to the current CPU when it is added to the timer queue, so the same timer will never run on other CPUs. Of course the same tasklet with two instances running on the same CPU at the same time is more unlikely.

If a protected shared resource is accessed only in two or more tasklet or timer contexts, access to the shared resource needs to be protected only with Spin_lock and Spin_unlock, not the _BH version, because when the Tasklet or timer runs, There can be no other tasklet or timer running on the current CPU.

If a protected shared resource is accessed only in context of a soft interrupt (except Tasklet and timer), the shared resource needs to be protected with spin_lock and spin_unlock because the same soft interrupt can run on different CPUs at the same time.

If a protected shared resource is accessed in two or more soft interrupt contexts, the shared resource will of course need to be protected with Spin_lock and spin_unlock, with different soft interrupts running on different CPUs at the same time.

If protected shared resources are accessed in soft interrupts (including Tasklet and timer) or process contexts and hard interrupt contexts, then during soft break or process context access, a hard interrupt may be interrupted to access the shared resource in a hard interrupt context, so The process or soft interrupt context requires the use of SPIN_LOCK_IRQ and SPIN_UNLOCK_IRQ to protect access to shared resources.

What version is used in the interrupt handling handle, depending on the situation, if only one interrupt handler handle accesses the shared resource, only Spin_lock and Spin_unlock are required in the interrupt handling handle to secure access to the shared resource.

Because during the execution of the interrupt handling handle, it is not possible to be interrupted by a soft interrupt or process on the same CPU. However, if you have different interrupt handling handles to access the shared resource, you need to use SPIN_LOCK_IRQ and SPIN_UNLOCK_IRQ in the interrupt handling handle to secure access to the shared resource.

In the case of using SPIN_LOCK_IRQ and SPIN_UNLOCK_IRQ, it is entirely possible to replace it with Spin_lock_irqsave and Spin_unlock_irqrestore, and which one should be used depending on the situation. It is better to use SPIN_LOCK_IRQ if you can be sure that interrupts are enabled before access to shared resources.

Because it's faster than Spin_lock_irqsave, but if you're not sure if the interrupt is enabled, then using Spin_lock_irqsave and Spin_unlock_irqrestore is better, This is because it will revert to the interrupt flag before accessing the shared resource instead of directly enabling the interrupt.

Of course, there are situations where it is necessary to break down when accessing a shared resource, and it must be interrupted when the access is complete, which is best when using SPIN_LOCK_IRQ and SPIN_UNLOCK_IRQ.

A special reminder to the reader that Spin_lock is used to block the simultaneous access of the execution units on different CPUs to shared resources, and the non-synchronous access to shared resources resulting from the different process contexts being preempted by each other. Interrupt failure and soft interrupt invalidation are designed to prevent soft interrupts on the same CPU or to interrupt non-synchronous access to shared resources.

Resources

Kernel Locking techniques,http://www.linuxjournal.com/article/5833

Redhat 9.0 Kernel source tree

kernel.org 2.6.12 Source Tree

The new lock mechanism in the Linux 2.6 kernel--rcu (read-copy Update),

http://www.ibm.com/developerworks/cn/linux/l-rcu/

unreliable Guide to Locking.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.