首页 > 其他 > 详细

spin_lock, spin_lock_irq, spin_lock_irqsave, spin_lock_bh

时间:2021-05-29 17:16:06      阅读:19      评论:0      收藏:0      [点我收藏+]

在阅读driver 源码时,经常看到spin_lock, spin_lock_irq,spin_lock_irqsave 这几个同步方法,那当要使用spinlock的时候,需要怎么选择呢?看一下它们实现的差异:

  • spin_lock

spin_lock() ->_raw_spin_lock(&lock->rlock) 

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

可以看到先禁止了调度,再去拿锁。这个过程仅仅禁止调度,如果有中断进来,还是可以被打断,切换到中断上下文运行。

  • spin_lock_irq

spin_lock_irq() -> _raw_spin_lock_irq(&lock->rlock)

static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
{
    local_irq_disable();
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

首先disable local irq(禁止当前cpu的中断),再禁止调度,此时没有任何情况可以打断,是完全安全的。如果临界资源中断处理函数也会使用,需要使用spin_lock_irq来保证同步。

  • spin_lock_irqsave

spin_lock_irqsave() -> _raw_spin_lock_irqsave(&lock->rlock)

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_);
    /*
     * On lockdep we dont want the hand-coded irq-enable of
     * do_raw_spin_lock_flags() code, because lockdep assumes
     * that interrupts are not re-enabled during lock-acquire:
     */
#ifdef CONFIG_LOCKDEP
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
#else
    do_raw_spin_lock_flags(lock, &flags);
#endif
    return flags;
}

local_irq_save -> arch_local_irq_save 这里面会将irq flag保存起来,然后再disable local irq, 最后会将当前irq flags返回。在spin_unlock_irqrestore的时候,返回的flags会当作参数传下去,unlock的同时,会将lock前的irq状态还原。

  • spin_lock_bh
static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
{
    __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

bh是bottom half的意思,__local_bh_disable_ip 会禁止softirq,但是硬中断可以响应。这个比较少见,在阅读上面三个spinlock函数时看到这个,顺便查看了一下。

 

spinlock翻译成中文叫做自旋锁,在等待过程中,它是忙等,不会发生睡眠(因为获取锁前先禁止调度,别人是无法抢占的),所以它适合在中断上下文这种不能发生睡眠的地方使用。但由于是禁止抢占,那么临界区执行的代码需要简短,不能够长时间禁止调度,否则系统将出现性能问题。如果怀疑有这类问题,可以使用ftrace的irqoff/preemptoff/preemptirqoff 来检查,会记录一次关闭中断或者抢占最长时间的操作。

 

spin_lock, spin_lock_irq, spin_lock_irqsave, spin_lock_bh

原文:https://www.cnblogs.com/hyyft/p/14825163.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!