Spinlock Linux device drivers

concept

Spin lock code may be used no longer dormant, such as interrupt processing routine; when properly used, may provide a spin lock generally be higher than the performance of the semaphore;

A mutex is a spin-lock device, it is only by two values, locked and unlocked; generally implemented as a single-bit integer values; want specific bit code tests associated lock, if the lock is available, the lock bit is set, and it continues to whine enter the critical section; the contrary, if the lock is to get someone else, then the code busy checking the lock loop and repeat until the lock is available ; this is a spin lock spin cycle parts;

Spinlock implemented on different architectures are different, but the core concept is lower than all systems are the same, when there is a spin lock, waiting for the processor to perform a busy cycle can not do any useful work;

Spinlock originally for use on multiprocessor systems designed, taking into account the concurrency issues, single-processor workstation running preemptive kernel, which behaves like SMP ; seize because, even if not intended to run on SMP systems their whine, we still need to achieve correct lock;

Spinlock context atoms and

Suitable for spin-lock rule is: any code has a spin lock must be atomic, it can not sleep; in fact, it can not give up the processor for any reason, in addition to service disruption at this time also (in some cases You can not give up the processor);

The kernel preemption has spinlock process code itself; any time, as long as the kernel code has a spin lock, to seize on the associated processor will be banned; even on a single processor, you must also disable preemption in the same way to avoid race;

When holding the lock is sometimes very difficult to avoid sleep, sleep may occur in many places can not be expected, when we write the code to be executed in the spin-lock, you must pay attention to the function of each call;

Another case, when the driver is performed, and acquires a lock that controls access to the device; at this time, the device generates an interrupt, causes an interrupt handling routine is invoked; interrupted processing example Cheng before accessing the device, but also to acquire the lock; have a lock in the interrupt handling routine is legal; however, interrupt handling routines have run on the processor where the lock code when, in the spin lock acquired in the initial state, at a time when non-disruptive code will not have any chance to release the lock; the processor will spin forever down; to avoid this, we need to ban local cpu interrupt when you have a spin lock;

The last important rule spinlock used: spin locks must have in the shortest possible time; the longer owns the spin lock time, other processors have to wait longer to release the spin-spin lock time; It has long locks will prevent the current processor scheduling, which means a higher priority process had to wait; to avoid such problems, keep in mind the time that has the lock as short as possible;

The use of spin locks

Using a spin lock need to include <linux / spinlock.h> header; spinlock_t actual type having a lock, and any other similar data structures, a spin-lock must be initialized;

During compilation static declare and initialize the following ways:

1 #define DEFINE_SPINLOCK(x)

Or you can call the following macro to dynamically spinlock initialization runtime:

1 #define spin_lock_init(_lock)

Before entering the critical zone, you need to acquire a lock spin_lock correlation function: Note: All spin lock waits are essentially non-interrupted, once called spin_lock, before acquiring the lock will remain in the spin state;

1  static __always_inline void spin_lock (spinlock_t * Lock )
 2  
3  / * ban soft interrupt, hardware interrupt is opened * / 
4  static __always_inline void spin_lock_bh (spinlock_t * Lock )
 5  
6  / * disable local interrupts without saving interrupt status, the need to ensure no other code disables the local processor interrupts * / 
. 7  static __always_inline void spin_lock_irq (spinlock_t * Lock )
 . 8  
. 9  / * disable local processor interrupt, save interrupt status * / 
10  #define spin_lock_irqsave (Lock, the flags)                

When leaving the critical region, to release the lock has been acquired, you can use the following method:

1 static __always_inline void spin_unlock(spinlock_t *lock)
2 
3 static __always_inline void spin_unlock_bh(spinlock_t *lock)
4 
5 static __always_inline void spin_unlock_irq(spinlock_t *lock)
6 
7 static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)

The kernel also provides non-blocking locking methods:

1 static __always_inline int spin_trylock(spinlock_t *lock)
2 
3 static __always_inline int spin_trylock_bh(spinlock_t *lock)
4 
5 static __always_inline int spin_trylock_irq(spinlock_t *lock)
6 
7 #define spin_trylock_irqsave(lock, flags)
Read-write spin locks

The kernel provides the spin lock read / write form, this lock allows any number of readers at the same time to enter the critical section, but the writer must be mutually exclusive access, that writer will be waiting to acquire a spin lock; read / write from twistlocks use rwlock_t type defined in the <linux / rwlock_types.h> and <linux / rwlock.h> using spin locks need to include both read-write header files;

Static declaration and initialization:

1 #define DEFINE_RWLOCK(x)

Dynamic declaration and initialization:

1 # define rwlock_init(lock)

Acquire the lock as follows:

 

Guess you like

Origin www.cnblogs.com/wanpengcoder/p/11760722.html