当前位置: 首页 > news >正文

linux atomic 原子变量操作

原子操作是指指令以原子的方式操作,执行过程不会被打断。linux内核提供了atomic_t类型的原子变量,它的实现依赖于不同的体系结构。

include/linux/types.h

typedef struct {

int counter;

} atomic_t;

#ifdef CONFIG_64BIT

typedef struct {

long counter;

} atomic64_t;

#endif

ARM使用ldrex和strex指令来保证操作的原子性

ldrex Rt,[Rn] 把Rn寄存器指向内存地址的内容加载到Rt寄存器中

strex Rd,Rt,[Rn] 把Rt寄存器的值保存到Rn寄存器指向的内存地址中,Rd保存更新的结果,0表示更新成功,1:表示失败。

下面分析ARM中原子操作实现,其中涉及到arm内嵌汇编的一些内容,大家可以先简单查阅下内嵌汇编的内容,本文这里默认大家熟悉这些内容。

#define ATOMIC_OP(op, c_op, asm_op)					\
static inline void atomic_##op(int i, atomic_t *v)			\
{									\unsigned long tmp;						\int result;							\\prefetchw(&v->counter);						\__asm__ __volatile__("@ atomic_" #op "\n"			\
"1:	ldrex	%0, [%3]\n"						\
"	" #asm_op "	%0, %0, %4\n"					\
"	strex	%1, %0, [%3]\n"						\
"	teq	%1, #0\n"						\
"	bne	1b"							\: "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)		\: "r" (&v->counter), "Ir" (i)					\: "cc");							\
}	
#define ATOMIC_OP_RETURN(op, c_op, asm_op)				\
static inline int atomic_##op##_return(int i, atomic_t *v)		\
{									\unsigned long tmp;						\int result;							\\smp_mb();							\prefetchw(&v->counter);						\\__asm__ __volatile__("@ atomic_" #op "_return\n"		\
"1:	ldrex	%0, [%3]\n"						\
"	" #asm_op "	%0, %0, %4\n"					\
"	strex	%1, %0, [%3]\n"						\
"	teq	%1, #0\n"						\
"	bne	1b"							\: "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)		\: "r" (&v->counter), "Ir" (i)					\: "cc");							\\smp_mb();							\\return result;							\/*返回原子变量v的旧值*/
}
static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
{int oldval;unsigned long res;smp_mb();prefetchw(&ptr->counter);do {__asm__ __volatile__("@ atomic_cmpxchg\n""ldrex	%1, [%3]\n"   /*存放ptr->counter值到oldval*/"mov	%0, #0\n"	  /*res=0*/"teq	%1, %4\n"     /*测试oldval(ptr->counter值)和old值是否相等*/"strexeq %0, %5, [%3]\n" /*如果相等则将new赋值给ptr->counter,最终将strex结果存放到res中*/: "=&r" (res), "=&r" (oldval), "+Qo" (ptr->counter): "r" (&ptr->counter), "Ir" (old), "r" (new): "cc");} while (res); /*res!=0表示独占访问失败,继续尝试*/smp_mb();return oldval;
}
static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{int oldval, newval;unsigned long tmp;smp_mb();prefetchw(&v->counter);__asm__ __volatile__ ("@ atomic_add_unless\n"
"1:	ldrex	%0, [%4]\n" /*将v->counter赋值给oldval*/
"	teq	%0, %5\n"	    /*测试oldval值和u是否相等*/
"	beq	2f\n"			/*相等则不做任何操作,跳转到2初*/
"	add	%1, %0, %6\n"   /*newval=oldval+a*/
"	strex	%2, %1, [%4]\n" /*v->counter=newval*/
"	teq	%2, #0\n"	/*测试独占访问是否成功,失败跳转到1处*/
"	bne	1b\n"
"2:": "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter): "r" (&v->counter), "r" (u), "r" (a): "cc");if (oldval != u)smp_mb();return oldval; /*返回旧值*/
}

#define ATOMIC_OPS(op, c_op, asm_op) \

ATOMIC_OP(op, c_op, asm_op) \

ATOMIC_OP_RETURN(op, c_op, asm_op)

/*atomic_add,atomic_add_return*/

ATOMIC_OPS(add, +=, add)

/*atomic_sub,atomic_sub_return*/

ATOMIC_OPS(sub, -=, sub)

#undef ATOMIC_OPS

#undef ATOMIC_OP_RETURN

#undef ATOMIC_OP

#define atomic_xchg(v, new) (xchg(&((v)->counter), new))

/*下面的宏定义都是依赖atomic_add,atomic_add_return,atomic_sub,atomic_sub_return的实现*/

#define atomic_inc(v) atomic_add(1, v)

#define atomic_dec(v) atomic_sub(1, v)

#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)

#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)

#define atomic_inc_return(v) (atomic_add_return(1, v))

#define atomic_dec_return(v) (atomic_sub_return(1, v))

#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)

#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【数列求值 / B】
  • Parallels Desktop 20(Mac虚拟机) v20.0.0 for Mac 最新破解版(支持M系列)
  • 【tomcat】tomcat学习笔记
  • 阿里云 Quick BI使用介绍
  • 基于SAM大模型的遥感影像分割工具,用于创建交互式标注、识别地物的能力,可利用Flask进行封装作为Web后台服务
  • 利用H5无插件播放RTSP流的实现方案
  • 【二等奖论文】2024年华为杯研究生数学建模F题成品论文(后续会更新)
  • 搜维尔科技:Unity中的A.R.T.测量工具
  • Spring Cloud Alibaba-(4)Sentinel【流控和降级】
  • C# 入坑JAVA 潜规则 大小写敏感文件名和类名 枚举等 入门系列2
  • 策略模式在 Spring Boot 框架中的应用
  • 实验3 Hadoop集群运行环境搭建和使用
  • 创建索引遇到这个Bug,19c中还没有修复
  • 粒子向上持续瀑布动画效果(直接粘贴到记事本改html即可)
  • 【AI实战攻略】保姆级教程:用AI打造治愈动画vlog,轻松打造爆款,快速涨粉!
  • [译]Python中的类属性与实例属性的区别
  • codis proxy处理流程
  • JS基础之数据类型、对象、原型、原型链、继承
  • npx命令介绍
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 如何学习JavaEE,项目又该如何做?
  • 探索 JS 中的模块化
  • 详解NodeJs流之一
  • 学习JavaScript数据结构与算法 — 树
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 如何正确理解,内页权重高于首页?
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • #13 yum、编译安装与sed命令的使用
  • #162 (Div. 2)
  • #php的pecl工具#
  • #pragma预处理命令
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • $.ajax中的eval及dataType
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (3)llvm ir转换过程
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (附源码)ssm高校实验室 毕业设计 800008
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (三) diretfbrc详解
  • (转)C#调用WebService 基础
  • (转)菜鸟学数据库(三)——存储过程
  • (转)四层和七层负载均衡的区别
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .net core 的缓存方案
  • .Net Core和.Net Standard直观理解
  • .net 怎么循环得到数组里的值_关于js数组