对于ARM体系结构,每一个由用户态到内核态的中断或异常处理路径都经过kuser_cmpxchg_check,kuser_cmpxchg_check中检查被中断的地址是否大于TASK_SIZE;TASK_SIZE是内核与用户空间的分界点,那么对于ARM体系而言,为什么在用户态时其执行路径会“顺利”地进入内核空间?

 查了下,在Documentation/zh_CN/arm/kernel/kernel_user_helpers.txt中解释了对于ARM体系结构,由于没有类似x86的“比较交换”指令,因此在用户态下完成一些原子操作时需要借助于内核空间的一些操作来完成(此时,仍处于用户态,只是执行的程序地址位于高1G空间),此时发生中断时,内核需要恢复到适当的断点继续执行,因此此时需要修正pt_regs中的返回地址pc值。 

    .macro  kuser_cmpxchg_check
+--- lines: #if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)------------------------
@ Make sure our user space atomic helper is restarted
@ if it was interrupted in a critical region. Here we
@ perform a quick test inline since it should be false
@ 99.9999% of the time. The rest is done out of line.
cmp r4, #TASK_SIZE
blhs kuser_cmpxchg64_fixup
__kuser_cmpxchg64:              @ 0xffff0f60
+-- lines: #if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)-------------------------------------------------------- #ifdef CONFIG_MMU /*
* The only thing that can break atomicity in this cmpxchg64
* implementation is either an IRQ or a data abort exception
* causing another process/thread to be scheduled in the middle of
* the critical sequence. The same strategy as for cmpxchg is used.
*/
stmfd sp!, {r4, r5, r6, lr}
ldmia r0, {r4, r5} @ load old val
ldmia r1, {r6, lr} @ load new val
: ldmia r2, {r0, r1} @ load current val
eors r3, r0, r4 @ compare with oldval ()
eoreqs r3, r1, r5 @ compare with oldval ()
: stmeqia r2, {r6, lr} @ store newval if eq
rsbs r0, r3, # @ set return val and C flag
ldmfd sp!, {r4, r5, r6, pc} .text
kuser_cmpxchg64_fixup:
@ Called from kuser_cmpxchg_fixup.
@ r4 = address of interrupted insn (must be preserved).
@ sp = saved regs. r7 and r8 are clobbered.
@ 1b = first critical insn, 2b = last critical insn.
@ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.
mov r7, #0xffff0fff
sub r7, r7, #(0xffff0fff - (0xffff0f60 + (1b - __kuser_cmpxchg64)))
subs r8, r4, r7
rsbcss r8, r8, #(2b - 1b)
strcs r7, [sp, #S_PC]
+--- lines: #if __LINUX_ARM_ARCH__ < 6--------------------------------------------------------------------------
mov pc, lr

如下内容,部分引述自:http://baike.baidu.com/view/809659.htm

  在单处理器系统(UniProcessor)中,能够在单条指令中完成的操作都可以认为是" 原子操作",因为中断只能发生于指令之间。这也是某些CPU指令系统中引入了test_and_set、test_and_clear等指令用于临界资源互斥的原因。但是,在对称多处理器(Symmetric Multi-Processor)结构中就不同了,由于系统中有多个处理器在独立地运行,即使能在单条指令中完成的操作也有可能受到干扰。

  原子性不可能由软件单独保证--必须需要硬件的支持,因此是和架构相关的。

  在x86 平台上,CPU提供了在指令执行期间对总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。

在ARMv6架构上,引入了ldrex、strex。个人理解,在使用ldrex和strex的过程中总线将会监控有无其它主设备(CPU、DMA等)来访问同样的地址,如果有,则使操作失效,并且在给出的寄存器中置1以示意失败,如果给出的寄存器中置为0则示意成功。

引述自:http://blog.roodo.com/use_the_force/archives/3420371.html

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html

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, see Exclusive monitors. Load-Exclusive and Store-Exclusive must only access memory regions marked as Normal.

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).

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  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  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.

kuser_cmpxchg_check 原子操作的更多相关文章

  1. Linux的原子操作与同步机制

    Linux的原子操作与同步机制   .进程1执行完“mov eax, [count]”后,寄存器eax内保存了count的值0.此时,进程2被调度执行,抢占了进程1的CPU的控制权.进程2执行“cou ...

  2. [转载]C#使用Interlocked进行原子操作

    原文链接:王旭博客 » C# 使用Interlocked进行原子操作 什么是原子操作? 原子(atom)本意是"不能被进一步分割的最小粒子",而原子操作(atomic operat ...

  3. 漫谈C++11 Thread库之原子操作

    我在之前一篇博文<漫谈C++11 Thread库之使写多线程程序>中,着重介绍了<thread>头文件中的std::thread类以及其上的一些基本操作,至此我们动手写多线程程 ...

  4. 原子操作--ARM架构

    说明:内核版本号为3.10.101 一.ARM架构中的原子操作实现 在原子操作(一)中我们已经提到,各个架构组织为“复仇者”联盟,统一了基本的原子变量操作,这里我们就拿atomic_dec(v)来看看 ...

  5. 锁&锁与指令原子操作的关系 & cas_Queue

    锁 锁以及信号量对大部分人来说都是非常熟悉的,特别是常用的mutex.锁有很多种,互斥锁,自旋锁,读写锁,顺序锁,等等,这里就只介绍常见到的, 互斥锁 这个是最常用的,win32:CreateMute ...

  6. Java--如何使用sun.misc.Unsafe完成compareAndSwapObject原子操作

    package com; import sun.misc.Unsafe; import java.lang.reflect.Field; /** * Created by yangyu on 16/1 ...

  7. java并发:线程同步机制之Volatile关键字&原子操作Atomic

    volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ...

  8. gcc提供的原子操作函数

    gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作.其声明如下: type __sync_fetch_and_add (type *ptr, type ...

  9. i++是否原子操作

    i++是否原子操作 不是原子操作.理由: 1.i++分为三个阶段: 内存到寄存器 寄存器自增 回内存 这三个阶段中间都可以被中断分离开.  2.++i首先要看编译器是怎么编译的, 某些编译器比如VC在 ...

随机推荐

  1. laravel iis搭建

    1.urlrewrite https://www.iis.net/downloads/microsoft/url-rewrite 2.安装phpmanager 3.目录定位到public 赋给iuse ...

  2. 出去html中的标签

    C#写法 public static string StripHTML(string strHtml) { string strOutput = strHtml; Regex regex = new ...

  3. Mysql 根据时间统计总数

    代码写法: SELECT date_format(examinee_pay_time, '%Y-%m-%d') as payDate, COUNT(examinee_id) As realityApp ...

  4. 【转】亲测plsql Developer配置免安装oralce客户端步骤

    原文地址:http://blog.csdn.net/bushy0401/article/details/11869461 再次用到Oracle了,机器上面也没有oracle客户端,还得去网上下载,直接 ...

  5. 了解PHP中$_SERVER变量对路径的解析

    1,$_SERVER["QUERY_STRING"]说明:查询(query)的字符串 2,$_SERVER["REQUEST_URI"]说明:访问此页面所需的U ...

  6. Chrome 调用vue.js 记录

    一.今晚遇到一个问题,就是不能直接在 html 直接调用 js 代码的问题 二.会出现如下错误: Refused to execute inline script because it violate ...

  7. Linux排序命令sort详解

    语法格式sort [ -A ] [ -b ] [ -c ] [ -d ] [ -f ] [ -i ] [ -m] [ -n ] [ -r ] [ -u ] [ -o OutFile ][ -t Cha ...

  8. openvpn之安装篇

    之前整过openvpn,现把一些过程记录下来,方便以后查阅. #!/bin/bash cd /usr/local/srcyum install pam-devel.x86_64 -ywget http ...

  9. JavaScript:数据类型

    JavaScript中数据类型分为两种: 1.基本数据类型 string number boolean null undefined 2.引用类型 数组.Object.function 一.基本数据类 ...

  10. Android 开发 打开默认浏览器发生崩溃

    Android 开发 打开默认浏览器发生崩溃. 代码如下: Intent intent = new Intent(); intent.setAction("Android.intent.ac ...