Android原子操作的实现原理
来源:互联网 发布:web数据挖掘系统 编辑:程序博客网 时间:2024/05/10 22:29
Android原子操作的实现方式和CPU的架构有密切关系,现在的原子操作一般都是在CPU指令级别实现的,这样不但简单,而且效率非常高。下面看看arm平台下Android是如何实现原子操作的。
虽然原子操作的接口函数有十来个,但是实际上只有两个函数中通过汇编代码实现了原子操作:函数android_atomic_add和android_atomic_cas,其他的函数都是在内部调用它们而已。这两个函数的原理差不多,下面我们以加法为例来了解一下原子变量的实现原理。函数android_atomic_add的代码如下:
externANDROID_ATOMIC_INLINE
int32_tandroid_atomic_add(int32_t increment, volatile int32_t*ptr)
{
}
上面代码中的宏ANDROID_ATOMIC_INLINE的定义是:
#defineANDROID_ATOMIC_INLINE inline__attribute__((always_inline))
实际上就是把函数规定为inline函数。
android_memory_barrier是告诉CPU这里需要内存屏障。下节会介绍内存屏障。
接下来是一段内嵌汇编,这段汇编可以用伪代码来表示:
do{
ldrex
add
strex
}whiile(status != 0)
在add指令的前后有两条看上去比较陌生的指令:ldrex和strex。这两条是AMRV6新引入的同步指令。ldrex指令的作用是把指针ptr指向的内容放到prev变量中,同时给执行处理器做一个标记(tag),标记上指针ptr的地址,表示这个内存地址已经有一个CPU正在访问。当执行到strex指令时,它会检查是否存在ptr的地址标记,如果标记存在,strex指令会把add指令执行的的结果写入指针ptr指向的地址,并且返回0,然后清除该标记。返回的结果0会放在status变量中,这样循环将结束。
如果在strex指令执行前发生了线程的上下文切换,在切换回来后,ldrx指令设置的标志将会被清除。这时再执行strex指令时,由于没有了这个标志,strex指令将不会完成对ptr指针的存储操作,而且status变量中的返回结果是1。这样循环不能结束,重新开始执行,直到成功为止。
__builtin_expect是gcc的内建函数,有两个参数,第一个参数是一个表达式,第二个参数是一个值。表达式的计算结果也是函数的结果。__builtin_expect是用来告诉gcc预测表达式更可能的值是什么,这样gcc会根据预测值来优化代码。代码中表达的含义是预测“status!=0”这个表达式的值为“0”,也就是预测while循环将结束。
内嵌汇编可以参考本人的博文:gcc内嵌汇编介绍
- Android原子操作的实现原理
- Android原子操作的实现原理
- 原子操作的实现原理
- 原子操作的实现原理
- 原子操作的实现原理
- 原子操作的实现原理
- 原子操作的实现原理
- 原子操作的实现原理
- 原子操作的实现原理
- Java实现原子操作的原理
- 原子操作的实现与原理
- Java 并发 ---原子操作的实现原理
- 聊聊并发--原子操作的实现原理
- ARM下的原子操作实现原理
- java原子操作实现原理
- 聊聊并发(五)原子操作的实现原理
- 聊聊并发(五)原子操作的实现原理
- x86平台原子操作API的实现原理
- 汇编语言的种类
- gcc汇编中的伪操作
- AT&T汇编格式介绍
- gcc内嵌汇编介绍
- Android中的编译屏障和内存屏障
- Android原子操作的实现原理
- Bionic中的ptrace函数
- Android利用ptrace实现Hook API
- Android ART模式简介
- Android ART 的初始化和启动
- Android签名漏洞分析
- Android build系统中常用LOCAL_变量
- oracle 备份与恢复系列笔记-1
- Futex同步机制简介