Spin lock

ImprimirCitar

In software engineering, a spinlock is a lock that causes a thread that tries to acquire it to simply wait in a loop ("spin" in English "spin") while it repeatedly checks whether the lock(lock) is available. Since the thread remains active but is not performing a useful task, the use of such a lock is a kind of busy wait. Once acquired, spinlocks will generally be held until explicitly released, although in some implementations they may be released automatically if the thread it is waiting on (whatever the lock is holding) blocks, or "goes to sleep".

Because they avoid the overhead of rescheduling operating system processes or context switching, spinlocks are efficient if threads are likely to block for only short periods. For this reason, operating system kernels often use spinlocks. However, spinlocks become wasteful if held for longer, as they can prevent other threads from running and require reprogramming. The longer a thread holds a lock, the greater the risk that the operating system scheduler will interrupt the thread while it holds the lock. If this happens, other threads will be left "spinning" (repeatedly trying to acquire the lock), while the thread holding the lock is not moving towards its release. The result is an indefinite postponement until the thread holding the lock can finish and release it. This is especially true on a single-processor system, where each waiting thread of the same priority can waste its amount (allocated time a thread can execute) spinning until the thread holding the lock finally finishes.

Implementing twist locks correctly presents challenges because programmers must account for the possibility of simultaneous lock access, which could cause race conditions. In general, such an implementation is only possible with special assembly language instructions, such as atomic test and set operations, and cannot be easily implemented in programming languages that do not support truly atomic operations. [1] On architectures without such operations, or if high-level language implementation is required, a non-atomic locking algorithm may be used, for example, Peterson's algorithm. However, such an implementation may require more memory than a spinlock, be slower to allow progress after unlocking, and may not be implementable in a high-level language if out-of-order execution is allowed.

Sample Implementation

The following example uses the x86 assembly language to implement a spinlock. It will work on any Intel 80386 compatible processor.

; Intel Syntaxlocked: ; The block variable. 1 = blocked, 0 = unlocked. dd 0spin_lock: mov eax, 1 Establish the EAX register to 1. xchg eax, [chuckles]locked] automatically change the EAX registry with the locking variable. ; This will always keep 1 in the block, leaving the previous value in the EAX registry. test eax, eax Try the EAX with yourself. Among other things, this goes to set the processor's Zero Indicator if EAX is 0. ; If EAX is 0, then the blockade was unlocked and We just unlocked it. ; Otherwise, EAX is 1 and we do not acquire the blockade. jnz spin_lock ; Jump to MOV instruction if the Zero Indicator is not established; the blockade was previously blocked, ; then we must turn in circles (spin) until it unlocks. ret ; The blockade was acquired, it becomes the function that he called The spinlock.spin_unlock: xor eax, eax ; EAX registration is set to 0. xchg eax, [chuckles]locked] ; Automatically changed registration ; EAX with the locking variable. ret The blockade was released.

Significant optimizations

The simple implementation above works on all CPUs using the x86 architecture. However, several performance optimizations are possible:

In later implementations of the x86 architecture, spin_unlock can safely use an unlocked MOV instead of the slower locked XCHG. This is due to subtle memory ordering rules behind it, although MOV is not a complete memory barrier. However, some processors (some Cyrix processors some revisions of Intel Pentium Pro (due to bugs) and older Pentium and i486 SMP systems) will do the wrong thing and the data protected by the lock could be corrupted. On most non-x86 architectures, an explicit memory barrier or atomic instructions must be used (as in the example). On some systems, like IA-64 there are special "unlock" which provide the necessary memory ordering.

To reduce bus traffic between CPUs, code trying to acquire a lock should read in a loop without trying to write anything until it reads a changed value. Due to MESI caching protocols this causes the cache line for the lock to become "Shared"; then, remarkably, there is no traffic on the bus while a CPU waits for the lock. This optimization is effective on all CPU architectures that have a per-CPU cache, because MESI is widespread.

Alternatives

The simple implementation above works on all CPUs using the x86 architecture. However, several performance optimizations are possible:


  1. Do not acquire the lock In many situations, it is possible to design data structures that do not require blocking, for example, using data by subprocess or by CPU and deactivating interruptions.
  2. Change to a different thread while waiting. This usually involves joining the current thread to a thread queue waiting for the block, followed by switching to another thread that is ready to do a useful job. This scheme also has the advantage that it ensures that the lack of resources does not occur as long as all threads leave the blockades they acquire and decisions can be made on which thread should advance first. Spinlocks that never involve commutation, usable by real-time operating systems are sometimes called unformatted spinlocks. [2]

Most operating systems (including Solaris, Mac OS X and FreeBSD) use a hybrid approach called "adaptive mutex". The idea is to use a spinlock when trying to access a resource closed by a currently running thread, but to sleep if the thread is not currently running. (The latter is always the case on single processor systems.)

OpenBSD tried to replace "spinlocks" with ticket locks applying the " first in, first out" but this resulted in higher CPU usage in the kernel and larger applications like Firefox getting slower. [Four. Five]

See also

  • Synchronization
  • Occupied sword
  • Dead point
  • Seqlock
  • @Ticket Lock

Contenido relacionado

Oil refining

The refining of petroleum is a process that includes the fractioning and chemical transformation of petroleum to produce commercial...

Valve

Valve is a fluid regulation and control instrument. A more complete definition describes the valve as a mechanical device with which the circulation of...

Thermal Power Plant

A thermal power plant is a facility used to generate electrical energy from thermal energy, such as that released by fossil fuels, uranium, a conventional...
Más resultados...
Tamaño del texto:
Copiar