Linux kernel 原子操作

Linux kernel 原子操作

主要看一下汇编是怎么实现的, 最后发现是通过硬件提供的指令集来完成的。
1- 预取内存数据
2- 原子加载、存储数据
3- 判断 PE 标记, 失败则跳转 2- 循环

内核原子操作

内核使用atomic_t类型的原子变量,具体的实现依赖于不同的体系架构,我这里是ARM64的代码进行分析。

atomic_t类型定义:

typedef struct {
	int counter;
} atomic_t;

#ifdef CONFIG_64BIT
typedef struct {
	long counter;
} atomic64_t;
#endif

内核提供了许多原子变量的操作函数:可以查看arch/arm64/include/asm/atomic.h里面的定义。

在这里插入图片描述

分析原子汇编代码

随便找一个包含内核atomic.h头文件的代码进行一个预编译,比如我之前写的一份trace的代码:

make ARCH=arm64 CROSS_COMPILE=aarch64-himix100-linux- drivers/mj/trace.i

编译之后可以找到里面atomic相关的预编译之后的函数,这里找一个简单常用的atomic_add()函数进行分析一下:

在这里插入图片描述

里面的知识点比较散,前面的always_inline以及no_instrument_function是在gcc手册的,具体内容可以查看gcc手册或者上面的简单注释:内联,不生成概要函数分析调用。

arm嵌入汇编也可以查看一下gcc手册的6.47 How to Use Inline Assembly Language in C Code。这里主要将一下参数部分的那几个=,&,r,+,Q是什么意思,更详细的内容还是要看gcc手册的介绍。

在这里插入图片描述

比如上面的IQ可能在不同的架构中又不同的定义:

在这里插入图片描述

看一下汇编指令的内容,这里要查找对应的数据手册,这里是armv8-a.pdfarm架构参考手册。

prfm 预取指令

预取存储器(寄存器)向存储器系统发出信号,表明在不久的将来很可能发生从指定地址访问数据存储器的事件。内存系统可以通过采取确实会加快内存访问速度的操作来做出响应,例如将包含指定地址的缓存行预加载到一个或多个缓存中。

在这里插入图片描述

在这里插入图片描述

ldxr 原子的加载操作

加载独占寄存器从基本寄存器值派生地址,从内存加载 32 位单词或 64 位双字,然后写入寄存器。内存访问是原子的。PE 标记将正在访问的物理地址标记为独占访问。

在这里插入图片描述

stxr 原子的存储操作

存储独占寄存器存储 32 位单词或 64 位双字从寄存器存储到内存(如果 PE 具有对内存地址的独占访问权限)的状态值,如果存储成功,则返回状态值 0;如果未执行存储,则返回 1 的状态值。

在这里插入图片描述

cbnz 非0跳转

非零上的比较和分支比较寄存器中的值为零,如果比较不相等,则有条件地分支为 PC 相对偏移处的标签。它提供了一个提示,提示这不是子例程调用或返回。此指令不会影响条件标志。

在这里插入图片描述

Armv8的同步原语

Armv8使用同步原语提供共享内存的非阻塞同步。 本节中有关通过同步原语进行内存访问的信息适用于对普通内存和任何类型的设备内存的访问。

在这里插入图片描述

看一下ldaxrldxr的区别:ldaxr也是原子操作,但ldaxr使用的描述说是Load-Acquire,看一下它给的连接。

在这里插入图片描述

是支持发布一直想顺序一致性模式?暂时不理解,但看spin_lock的代码是使用的这个指令。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值