请参阅:kernel_user_helpers.txt或entry-arm.c并查找swp。如其他ARM Linux版本的注释所示,
kuser cmpxchg
Location: 0xffff0fc0
Reference prototype:
int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
Input:
r0 = oldval
r1 = newval
r2 = ptr
lr = return address
Output:
r0 = success code (zero or non-zero)
C flag = set if r0 == 0, clear if r0 != 0
Clobbered registers:
r3, ip, flags
Definition:
Atomically store newval in *ptr only if *ptr is equal to oldval.
Return zero if *ptr was changed or non-zero if no exchange happened.
The C flag is also set if *ptr was changed to allow for assembly
optimization in the calling code.
Usage example:
typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
int atomic_add(volatile int *ptr, int val)
{
int old, new;
do {
old = *ptr;
new = old + val;
} while(__kuser_cmpxchg(old, new, ptr));
return new;
}
笔记:
该例程已根据需要包含内存屏障。
仅当__kuser_helper_version> = 2(从内核版本2.6.12开始)时才有效。
这用于带有2679766789885885789184原语的带ARMv3的Linux。 您必须有一个非常古老的ARM,不支持此功能。 只有数据中止或中断会导致旋转失败,因此内核会监视该地址〜0xffff0fc0并在发生数据中止或中断时执行用户空间PC修复。 所有支持ARMv5及更低版本的用户空间库都将使用此功能。
例如,QtConcurrent使用此方法。