Linux 内核 spin_lock 和spin_unlock

本文详细阐述了spin_lock在ARMv8架构中的具体实现方式,重点介绍了spin_lock和spin_unlock的功能及内部机制,通过源码分析揭示了其在内核中的高效同步原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. spin_lock作为一种轻量级的同步机制,在内核应用广泛,本文将基于ARMv8讲述其具体实现。由于spin_lock家族比较庞大,不大算面面俱到的介绍每一个实现,重点介绍spin_lock和spin_unlock的实现。

include/linux/spinlock.h


static inline void spin_lock(spinlock_t *lock)
{
        raw_spin_lock(&lock->rlock);
}

static inline void spin_unlock(spinlock_t *lock)
{
        raw_spin_unlock(&lock->rlock);
}

#define raw_spin_lock(lock)     _raw_spin_lock(lock)

#define raw_spin_unlock(lock)           _raw_spin_unlock(lock)


include/linux/spinlock_api_smp.h


void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)            __acquires(lock);

void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock)          __releases(lock);


kernel/spinlock.c


void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
{
        __raw_spin_lock(lock);
}
EXPORT_SYMBOL(_raw_spin_lock);

void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock)
{
        __raw_spin_unlock(lock);
}
EXPORT_SYMBOL(_raw_spin_unlock);


include/linux/spinlock_api_smp.h


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);
}

static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
        spin_release(&lock->dep_map, 1, _RET_IP_);
        do_raw_spin_unlock(lock);
        preempt_enable();
}


include/linux/lockdep.h


#define LOCK_CONTENDED(_lock, try, lock)                        \
do {                                                            \
        if (!try(_lock)) {                                      \
                lock_contended(&(_lock)->dep_map, _RET_IP_);    \
                lock(_lock);                                    \
        }                                                       \
        lock_acquired(&(_lock)->dep_map, _RET_IP_);                     \
} while (0)

由以上函数调用可以看出spin_lock调用do_raw_spin_lock, spin_unlock调用do_raw_spin_unlock。


include/linux/spinlock.h


static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock)
{
        __acquire(lock);
        arch_spin_lock(&lock->raw_lock);
}
static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
{
        arch_spin_unlock(&lock->raw_lock);
        __release(lock);
}


2. Armv8 arch_spin_lock 和 arch_spin_unlock


 41 static inline void arch_spin_lock(arch_spinlock_t *lock)
 42 {
 43         unsigned int tmp;
 44
 45         asm volatile(
 46         "       sevl\n"
 47         "1:     wfe\n"
 48         "2:     ldaxr   %w0, %1\n"
 49         "       cbnz    %w0, 1b\n"
 50         "       stxr    %w0, %w2, %1\n"
 51         "       cbnz    %w0, 2b\n"
 52         : "=&r" (tmp), "+Q" (lock->lock)
 53         : "r" (1)
 54         : "cc", "memory");
 55 }

46行,设置本地事件

47行, 等待事件(可能进入低功耗状态)

48行,独占读取lock->lock

49行, 如果不是0,跳转到47行,等待事件。如果是,继续执行。

50行, 独占向lock->lock写入1.

51行, 如果不成功,跳转到48行。如果成功结束。


 73 static inline void arch_spin_unlock(arch_spinlock_t *lock)
 74 {
 75         asm volatile(
 76         "       stlr    %w1, %0\n"
 77         : "=Q" (lock->lock) : "r" (0) : "memory");
 78 }

76行,向lock->lock写入0;会发出唤醒事件。





1.使用谷歌浏览器下载并安装OneTab插件,OneTab插件的离线Chrome插件的下载链接可以在本文下方找到,安装离线 2.当用户使用Chrome打开过多新标签页的时候可以点击浏览器右上角的OneTab插件来一键清理Chrome的标签页列表,清理完成以后,OneTab插件会立即弹出一个新的标签页把清理的Chrome标签页列中,用户只需要选择有用的标签页点击并打开在谷歌浏览器的新标签页中就可以了,如下图所示: OneTab插件恢复Chrome中已经关闭的标签页 3.在已经关闭的标签页列表中,用户可以选择直接恢复所有已经关闭的标签页或者点击标签页列表中的某个关心的标签,并在Chrome的新标签页中打开。 4.除了在OneTab插件的标签页中恢复已经关闭的标签页以外,OneTab插件的标签页还允许用户分享到标签页或者给当前的标签页重新命名,如果在列表中的标签页比较重要,用户可以把当前的标签页列表锁定到OneTab标签列表中,具体的做法是点击标签多按钮(More)并点击锁定当前的标签组按钮。 5.如果用户需要OneTab插件多个性化的设置可以右键点击谷歌浏览器右上角的OneTab插件按钮并选择选项按钮来启动OneTab插件的设置界面,在这个设置界面中用户可以定义加符合自己操作习惯的OneTab插件,如图: OneTab插件的设置界面 OneTab的注意事项 1.OneTab插件的缓存内容只是保存了当前的URL地址,如果用户正在编辑标签内容的时候请不要使用OneTab插件,因为这样会丢失用户的操作! 2.如果用户打开老区两个独立的谷歌浏览器窗口,那么在其中一个浏览器窗口中使用OneTab插件的时候整个浏览器都会被关闭,OneTab插件的标签页会显示在另一个Chrome窗口中,所以莫要惊慌。 3.OneTab插件只是一款辅助用户关闭掉一些Chrome已经打开标签页的插件,当用户的Chrome标签页中含有比较重要内容的时候建议使用手动的方式一个一个去清除掉不需要的标签页(这样可以确保含有表单编辑的标签页能够正确地被关闭)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值