spin_lock, spin_lock_irq, spin_lock_irqsave的区别

kernel version: 2.6.26

linux kernel代码中有很多自旋锁的使用场景,同时存在很多spin_lock的接口定义,那么怎么去区分这些接口的使用场景呢?

首先来看spin_lock的实现:

#define spin_lock(lock)         _spin_lock(lock)

void __lockfunc _spin_lock(spinlock_t *lock)
{
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
}

spin_lock_irq的实现,我们按照smp来看:

#define spin_lock_irq(lock)     _spin_lock_irq(lock)

void __lockfunc _spin_lock_irq(spinlock_t *lock)
{
    local_irq_disable();
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
}

spin_lock_irqsave的实现

#define spin_lock_irqsave(lock, flags)  flags = _spin_lock_irqsave(lock)

unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
{
    unsigned long flags;

    local_irq_save(flags);
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    /*
     * On lockdep we dont want the hand-coded irq-enable of
     * _raw_spin_lock_flags() code, because lockdep assumes
     * that interrupts are not re-enabled during lock-acquire:
     */
#ifdef CONFIG_LOCKDEP
    LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
#else
    _raw_spin_lock_flags(lock, &flags);
#endif
    return flags;
}

显而易见,spin_lock_irq还调用了local_irq_disable函数,禁用本地中断;
假设当进程A调用spin_lock访问临界区时,如果中断来临,刚好调度到这个cpu核上,并且也去获取spin_lock,此时进程A已经被设置为TASK_INTERRUPT,同时中断处理程序因为拿不到锁,一直在忙等,进程调度无法调度进程A,导致死锁。而如果这个中断是在另一个cpu核上,就不会出现这种情况,因为另一个cpu核的中断并不会导致进程A运行状态被设置为TASK_INTERRUPT,只是被调度换出。
所以在使用spin_lock接口时,需要注意是否会在中断处理中获取锁。

而spin_lock_irqsave在进入临界区前,会保存当前中断状态flag,关闭本地中断,然后进入临界区,在退出临界区时,把保存的flag写回到中断寄存器。
spin_lock_irq在进入临界区前不保存中断状态,关中断,进入临界区,在退出临界区时,开中断。

spin_lock_irqsave锁返回时,中断状态不会被改变,调用spin_lock_irqsave前是开中断返回就开中断。
spin_lock_irq锁返回时,永远都是开中断,即使spin_lock_irq前是关中断

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值