См .: kernel_user_helpers.txt или entry-arm.c и найдите __kuser_cmpxchg
. Как видно из комментариев других версий 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).
Это для использования с Linux с ARMv3, использующим примитив swp
. Вы должны иметь очень древний ARM, чтобы не поддерживать это. Только прерывание данных или прерывание может привести к сбою вращения, поэтому ядро отслеживает этот адрес ~ 0xffff0fc0 и выполняет пространство пользователя PC
исправление, когда данные прерывают или прерывание . Все библиотеки пользовательского пространства, которые поддерживают ARMv5 и ниже, будут использовать эту возможность.
Например, QtConcurrent использует это.