ARM下的原子操作实现原理

本文的重点是学习C内嵌汇编的语法和ldrex/strex指令。

1、atomic_t类型定义
typedef struct {
    int counter;
} atomic_t;
把整型原子操作定义为结构体,让原子函数只接收atomic_t类型的参数进而确保原子操作只与这种特殊类型数据一起使用,同时也保证了该类型的数据不会被传递给非原子函数。

2、定义并初始化一个atomic_t变量
atomic_t v = ATOMIC_INIT(0);
#define ATOMIC_INIT(i)    { (i) }

3、基本操作
atomic_inc(v); // 原子变量自增1
atomic_dec(v); // 原子变量自减1
4、atomic_inc()函数的实现
static inline void atomic_inc(atomic_t *v)
{
atomic_add_return(1, v);
}

#define atomic_inc_return(v)    atomic_add_return(1, (v))
static inline int atomic_add_return(int i, atomic_t *v)
{
    unsigned long tmp;
    int result;
    smp_mb();
 
    __asm__ __volatile__("@ atomic_add_return\n"
        "1:    ldrex    %0, [%3]\n"
        "    add    %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;
}

4.1 C函数内嵌汇编
4.1.1 内嵌汇编语法
__asm__内嵌汇编关键字,告知编译器下述语句为汇编代码
__volatile__告知编译器不要优化(比如重组优化)下述汇编语句
语法的格式:
__asm__ (
    "asm code 1\n" // instruction list
    "asm code 2\n"
    "asm code n"
    : Output Operands // 把汇编指令的数值输出到C代码的变量中
    : Input  Operands
    : clobbers // 告知编译器这条指令会修改什么值
);

变量列表中常见符号:
"+":操作数可读可写
"=":操作数只写
"&":常用于输出操作,表示输出操作不能使用输入操作使用过的寄存器,只能+&或=&方式使用
"r":操作数是任何可用的通用寄存器
"m":操作数是内存变量
"p":操作数是一个合法的内存地址
"I":0~31之间的立即数
"i":操作数是立即数
"Q":A memory address which uses a single base register with no offset
"o":操作数是内存变量,但其寻址方式必须是偏移量类型的,即基址寻址或基址加变址寻址
"V":操作数是内存变量,但其寻址方式非偏移量类型

4.1.2 atomic_add_return中汇编分析
__asm__ __volatile__("@ atomic_add_return\n"
    "1:    ldrex    %0, [%3]\n"
    "    add    %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");
%0 <-- result
%1 <-- tmp
%3 <-- v->counter的地址
%4 <-- i
注意:此时C变量的数据都已经放至寄存器中
(1) ldrex %0, [%3]
独占式地加载(Load-Exclusive)v->counter的地址,把它的值放到result中,并更新exclusive monitor(s)
用C描述就是:
result = v->counter
(2) add %0, %0, %4
result = result + i
(3) strex %1, %0, [%3]
独占式地保存(Store-Exclusive)数据至v->counter的地址,数据来自result,操作结果(成功/失败)保存在tmp中
用C描述就是:
v->counter = result
(4) teq %1, #0
检测strex的操作是否成功
(5) bne 1b
strex的操作失败的话,向后跳转到指定标号(jump to 1 label backward)处重新执行
(6) "cc"

"cc"是一个特殊的参数,用来标明汇编代码会修改标志寄存器(flags register)
在某些机器平台上,GCC通过一个特殊的硬件寄存器表征条件类型的代码,"cc"就是这个特殊寄存器的名字
某些机器平台没有上述功能,"cc"会被忽略,不起作用。

附:

1、How to Use Inline Assembly Language in C Code

2、ldrex和strex简介

LDREX and STREX
The LDREX and STREX instructions split the operation of atomically updating memory into
two separate steps. Together, they provide atomic updates in conjunction with exclusive
monitors that track exclusive memory accesses.
Load-Exclusive and Store-Exclusive must only access memory regions marked as
Normal.

LDREX
The LDREX instruction loads a word from memory, initializing the state of the exclusive
monitor(s) to track the synchronization operation. For example, LDREX R1, [R0]
performs a Load-Exclusive from the address in R0, places the value into R1 and updates
the exclusive monitor(s).

STREX
The STREX instruction performs a conditional store of a word to memory. If the exclusive
monitor(s) permit the store, the operation updates the memory location and returns the
value 0 in the destination register, indicating that the operation succeeded. If the
exclusive monitor(s) do not permit the store, the operation does not update the memory
location and returns the value 1 in the destination register. This makes it possible to
implement conditional execution paths based on the success or failure of the memory
operation. For example, STREX R2, R1, [R0] performs a Store-Exclusive operation to the
address in R0, conditionally storing the value from R1 and indicating success or failure
in R2.

详见ARM Synchronization Primitives
————————————————
版权声明:本文为CSDN博主「__2017__」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013686019/article/details/78235624

ARM下的原子操作实现原理相关推荐

  1. linux qt wifi连接,贡献自己写的,在linux,arm下的屏幕搜索wifi并连接(qt,多选择,wifi按信号排列)...

    当前位置:我的异常网» Linux/Unix » 贡献自己写的,在linux,arm下的屏幕搜索wifi并连接 贡献自己写的,在linux,arm下的屏幕搜索wifi并连接(qt,多选择,wifi按信 ...

  2. 解决Windows下Arm下Linux下Qt4程序的中文乱码问题

    解决Windows下Arm下Linux下Qt4程序的中文乱码问题 ################################################################### ...

  3. 走进 San CLI(下):实现原理

    作者:胡粤 上期我们讨论了 San CLI 的使用,这期我们再深入一点,来看看 San CLI 的实现原理. 核心模块和核心概念 为了方便理解下文的 San CLI 的整体工作流程(主流程),我们先来 ...

  4. [css] 解释下 CSS sprites的原理和优缺点分别是什么

    [css] 解释下 CSS sprites的原理和优缺点分别是什么 我来说下我的观点 原理: 多张图合并成一张图优点&解决的问题hover效果,如果是多个图片,网络正常的情况下首次会闪烁一下. ...

  5. linux shell 原理,linux下shell的工作原理

    linux下shell的工作原理 2009-12-8 10:19:53   出处:https://www.yqdown.com shell是用户和Linux操作系统之间的接口.Linux中有多种she ...

  6. linux下文件删除的原理精华讲解(考试题答案系列)

    说明:本文为老男孩linux培训某节课前考试试题及答案分享博文内容的一部分,也是独立成题的,你可以点下面地址查看全部的内容信息.http://oldboy.blog.51cto.com/2561410 ...

  7. Win32环境下动态链接库(DLL)编程原理

    Win32环境下动态链接库(DLL)编程原理 比较大应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作.其中可能存在一些模块的功能较为通用,在构造其它软件系 ...

  8. qt4.8.5在arm下的移植

    下载并编译tslib-1.4 下载地址:http://pan.baidu.com/disk/home#from=share_pan_logo&path=%2FWizNote 名称为:tslib ...

  9. Linux下调试器工作原理

    Linux下调试器工作原理之一-基础篇 介绍关于Linux下的调试器实现的主要组成部分--ptrace系统调用.本文中出现的代码都在32位的Ubuntu系统上开发.请注意,这里出现的代码是同平台紧密相 ...

最新文章

  1. RHEL5.4在线调整磁盘分区大小
  2. python浅蓝色对应的代码_浅蓝色Python模块不在m上工作
  3. Scaffold php,GitHub - yiiplus/scaffold: scaffold是一个基于Yii2高级项目模版工程化实现的应用程序...
  4. 人生聚散,一切随缘!
  5. c++用向量给句子排序_用C ++对向量排序
  6. 计算机编程及常用术语英语词汇大全
  7. 如何压缩图片大小?这几种图片压缩方法总有一款适合你
  8. MAX232(电平转换:RS232-TTL)
  9. 1156针最强cpu,1156的CPU什么最好?
  10. 如何用计算机求极限,计算器的极限_500字
  11. delphi 调用浏览器内核_深入理解浏览器原理
  12. 上年龄的笔记本升级固态硬盘和内存经验谈
  13. 12306查询车票(爬虫小练_1)
  14. (附源码)springboot考研规划系统 毕业设计 541230
  15. 【数据库】SQL Server的使用教程
  16. 2.6 修饰符的位置
  17. 十大物联网名词,专业人士才懂全!
  18. 施一公演讲太精彩!让科研迷茫的人少走很多弯路
  19. TcpListener和TcpClient传输文件
  20. GEE:使用Sentinel-2数据做基于NDVI的长势监测(求5年影像集的NDVI均值,和当前年份的NDVI,两个影像做数学运算)

热门文章

  1. ssm框架的整合搭建(一)
  2. [SQL] SQL 基础知识梳理(三) - 聚合和排序
  3. 老平台已死,整理个文档留下做纪念
  4. 基于JQUERY使用FLASH的AJAX上传进度条插件uploadify
  5. 10个不为人知 但绝对值得收藏的网站
  6. 单例模式应用场景_三、单例模式详解
  7. Baseline needs more love
  8. mysql 索引分析工具_Mysql:性能分析以及Explain工具的使用
  9. 【数理知识】《数值分析》李庆扬老师-第8章-矩阵特征值计算
  10. 1.8 为什么是人的表现-深度学习第三课《结构化机器学习项目》-Stanford吴恩达教授