打开CPU的本地中断使用sti汇编指令。spin_lock_bh/spin_unlock_bh/spin_trylock_bhspin_lock_bh函数在得到自旋锁的同时禁止本地软中断,spin_unlock_bh函数释放自旋锁的同时,也打开本地的软中断。
#define spin_lock_bh(lock) do { local_bh_disable(); spin_lock(lock); } while (0)
#define local_bh_disable() cpu_bh_disable(smp_processor_id())
#define cpu_bh_disable(cpu) \do { local_bh_count(cpu)++; barrier(); } while (0)
#define spin_unlock_bh(lock) do { spin_unlock(lock); local_bh_enable(); } while (0)
#define spin_trylock_bh(lock) ({ int __r; local_bh_disable();\__r = spin_trylock(lock); \if (!__r) local_bh_enable(); \__r; })
spin_lock/spin_unlock/spin_trylock上面各组函数最终都需要调用自旋锁操作函数。spin_lock函数用于获得自旋锁,如果能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋锁的保持者释放。spin_unlock函数则释放自旋锁。此外,还有一个spin_trylock函数。尽力获得自旋锁lock,如果能立即获得锁,它获得锁并返回真,否则不能立即获得锁,立即返回假。它不会自旋等待lock被释放。spin_lock/spin_unlock/spin_trylock在UP环境下由于Linux 2.4.x为不可抢占的内核,在单处理器环境下,自旋锁什么都不需要做。自旋锁类型spinlock_t设置为空,除了在GCC的早期版本中不支持内容为空的数据结构。typedef struct {} spinlock_t;相应地,自旋锁的操作函数不进行任何实质性处理。
#define spin_lock_init(lock) do { } while(0)
#define spin_lock(lock) (void)(lock) /* Not "unused variable". */
#define spin_is_locked(lock) (0)#define spin_trylock(lock) ({1; })
#define spin_unlock_wait(lock) do { } while(0)
#define spin_unlock(lock) do { } while(0)
spin_lock/spin_unlock/spin_trylock在SMP环境下在SMP环境下,自旋锁类型spinlock_t含有一个unsigned int域lock。未加锁时值为1,加锁后值为0或负值。声明时也使用了volatile描述符,要求编译器不要对其作优化处理,对它的读写都需要从内存中访问。
typedef struct { volatile unsigned int lock;} spinlock_t;
static inline void spin_lock(spinlock_t *lock){ __asm__ __volatile__( spin_lock_string :"=m" (lock->lock) : : "memory");}