嵌入式LINUX驱动学习之8竞态和并发相关问题(三)衍生自旋锁

嵌入式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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值