local_irq_enable与local_irq_disable
在单处理器不可抢占系统中,使用local_irq_enable与local_irq_disable是消除异步并发源的有效方式。
虽然驱动程序中应避免使用这两个宏,但在spinlock等互斥机制中常常用到这两个宏。
local_irq_save与local_irq_restore
防止在一个中断关闭环境中因为调用local_irq_disable与local_irq_enable将之前的中断响应状态破坏掉。
自旋锁
static inline void spin_lock(spinlock_t *lock) { raw_spin_lock(&lock->rlock); } static inline void raw_spin_lock(raw_spinlock_t *lock) { preempt_disable(); do_raw_spin_lock(lock); } raw_spin_lock要先调用preempt来关闭系统的可抢占性,为了保护共享资源不会收到破坏。
当知道一个自旋锁在终端上下文中有可能会被使用到时,应该使用spin_lock_irq函数。
还有一个类似变体,spin_lock_irqsave。另一个版本spin_lock_bh(spin_unlock_bh)的功能就是用来处理进程
与延迟处理导致的并发互斥问题。
即使在单处理器上只需调用local_irq_enable / local_irq_disable来对共享资源进行保护,也应该使用
spin_lock_irq / spin_unlock_irq函数,因为若将来代码移植到多处理器。
读取者与写入者自旋锁rwlock
read_lock_irq / read_unlock_irq
write_lock_irq / write_unlock_irq
信号量
信号量down操作
void down(struct semaphore *sem); int down_interruptible(struct semaphore *sem); //中断可中断 int down_trylock(struct semaphore *sem); //不睡眠立即返回 int down_timeout(struct semaphore *sem): //处于睡眠状态有时间限制
信号量up操作
up(struct semaphore *sem);
读取者与写入者信号量rwsem
读取者信号量down操作
void_sched down_read(struct rw_semaphore * sem); int down_read_trylock(struct rw_semaphore * sem);
读取者信号量up操作
void up_read(struct rw_semaphore * sem);
写入者信号量down操作
void_sched down_write(struct rw_semaphore * sem); int down_write_trylock(struct rw_semaphore * sem);
写入者信号量up操作
void up_write(struct rw_semaphore * sem);
互斥锁
互斥锁初始化
void mutex_init(struct mutex *lock);
互斥锁down操作
void_sched mutex_lock(struct mutex *lock);
互斥锁up操作
void_sched mutex_unlock(struct mutex *lock);
顺序锁
顺序锁设计思想,对某一共享数据读取时不加锁,写的时候加锁。为了保证读取时不会因为
写入者的出现导致该共享数据的更新,需要在读取者和写入者之间引入一整型变量,称为顺序
值,读取者在开始读取前读取该sequence,在读取后再重读该值,如果与读取之前的值不一致,
则说明本次读取过程中发生了数据更新,读取无效。
静态定义一个seqlock并初始化,可以使用
#define DEFINE_SEQLOCK(x)
动态初始化一个seqlock变量,可以使用
seqlock_init(x)
写入者顺序锁上锁操作
static inline void write_seqlock(seqlock_t *sl) static inline void write_seqlock_irq(seqlock_t *sl) static inline void write_seqlock_irqsave(seqlock_t *sl) static inline void write_seqlock_bh(seqlock_t *sl) static inline void write_tryseqlock(seqlock_t *sl)
写入者顺序锁的解锁操作
static inline void write_sequnlock(seqlock_t *sl) static inline void write_sequnlock_irq(seqlock_t *sl) static inline void write_sequnlock_irqrestore(seqlock_t *sl) static inline void write_sequnlock_bh(seqlock_t *sl)
对于读取者顺序锁代码
例子: do{ start = read_seqbegin(&demo_seqlock); do_read(); }while( read_seqretry(&demo_seqlock, start) ); read_seqbegin_irqsave(lock, flags); read_seqretry_irqrestore(lock,iv,flags);
原子变量操作
//Task A void taska_addflag() { atomic_inc(&g_flag); } //Task B void taskb_addflag() { atomic_inc(&g_flag); }