嵌入式LINUX驱动学习之8竞态和并发相关问题(三)衍生自旋锁
一、头文件、函数及说明
衍生自旋锁主要是基于自旋锁和中断屏蔽实现,对于使用衍生自旋锁的内容不能进行休眠操作
/*
对要操作的全局变量或寄存器添加衍生自旋锁函数:
spin_lock_irqsave(lock,flags);
参数:
lock : spinlock_t lock;
flags: unsigned long flags);
注:在spin_lock_irqsave函数中做形参使用时;lock应当取地址
lock:应当都为全局静态变量,
flags:一般用局部变量即可;
用法:
static spinlock_t lock;
static unsigned long flags;
static void/int/... xxx_func(..形参 ...){
spin_lock_irqsave(&lock,flags);
......要操作的全局变量或寄存器...
spin_unlock_irqrestore(&lock,flags);
源码位置:include/linux/spinlock.h
*/
#define spin_lock_irqsave(lock, flags) \
do { \
raw_spin_lock_irqsave(spinlock_check(lock), flags);//源码实现见附A.1 \
} while (0)
/*
释放衍生自旋锁函数:spin_unlock_irqrestore()
*/
static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
{
raw_spin_unlock_irqrestore(&lock->rlock, flags);
}
附A.1
/*函数功能,将形参lock转换为raw_spinlock_t结构体类型*/
static inline raw_spinlock_t *spinlock_check(spinlock_t *lock)
{
//结构体spinlock_t的成员变量rlock为,结构体struct raw_spinlock类型
//而结构体类型:raw_spinlock_t为struct raw_spinlock别名
//详见源代码:include/linux/spinlock_types.h
return &lock->rlock;
}
#define raw_spin_lock_irqsave(lock, flags) \
do { \
typecheck(unsigned long, flags); \
flags = _raw_spin_lock_irqsave(lock);//源码实现见附A.1.1 \
} while (0)
/*
函数typecheck(a,b)功能:
检查形参 b 是否为形参 a 类型
*/
附A.1.1
//源码位置:linux/spinlock_api_smp.h
#define _raw_spin_lock_irqsave(lock) __raw_spin_lock_irqsave(lock)
static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
unsigned long flags;
local_irq_save(flags); //使用中断屏蔽
preempt_disable(); //关闭抢占
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
#ifdef CONFIG_LOCKDEP
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);//实现方法见附A1.1.1
#else
do_raw_spin_lock_flags(lock, &flags); //使用中断屏蔽,实现方法见附A1.1.2
#endif
return flags;
}
附A1.1.1
#ifdef CONFIG_LOCK_STAT
extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
extern void lock_acquired(struct lockdep_map *lock, unsigned long ip);
#define LOCK_CONTENDED(_lock, try, lock) \
do {
/*
do_raw_spin_trylock(lock)
*/
if (!try(_lock)) { \
lock_contended(&(_lock)->dep_map, _RET_IP_); \
lock(_lock); \
} \
lock_acquired(&(_lock)->dep_map, _RET_IP_); \
} while (0)
/* do_raw_spin_trylock()函数实现*/
//源码位置:include/linux/spinlock.h
static inline int do_raw_spin_trylock(raw_spinlock_t *lock)
{
return arch_spin_trylock(&(lock)->raw_lock);
}
//源码位置:include/linux/spinlock_up.h
static inline int arch_spin_trylock(arch_spinlock_t *lock)
{
char oldval = lock->slock;
lock->slock = 0;
return oldval > 0;
}
附A1.1.2
/* do_raw_spin_lock_flags()函数实现
源码位置:include/linux/spinlock.h
*/
static inline void\
do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags) __acquires(lock)
{
__acquire(lock);
arch_spin_lock_flags(&lock->raw_lock, *flags);//实现方式如下:
}
//源码位置:include/linux/spinlock_up.h
static inline void\
arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)
{
local_irq_save(flags);
lock->slock = 0;
}
//arch_spinlock_t结构体原型
typedef struct {
volatile unsigned int slock;
} arch_spinlock_t;