diff --git a/headers/private/kernel/user_atomic.h b/headers/private/kernel/user_atomic.h index 8d498e0d99..f6ee3248cf 100644 --- a/headers/private/kernel/user_atomic.h +++ b/headers/private/kernel/user_atomic.h @@ -13,19 +13,21 @@ extern "C" { #endif -int32 _user_atomic_set(vint32 *value, int32 newValue); -int32 _user_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst); -int32 _user_atomic_add(vint32 *value, int32 addValue); -int32 _user_atomic_and(vint32 *value, int32 andValue); -int32 _user_atomic_or(vint32 *value, int32 orValue); -int32 _user_atomic_get(vint32 *value); +void _user_atomic_set(int32 *value, int32 newValue); +int32 _user_atomic_get_and_set(int32 *value, int32 newValue); +int32 _user_atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst); +int32 _user_atomic_add(int32 *value, int32 addValue); +int32 _user_atomic_and(int32 *value, int32 andValue); +int32 _user_atomic_or(int32 *value, int32 orValue); +int32 _user_atomic_get(int32 *value); -int64 _user_atomic_set64(vint64 *value, int64 newValue); -int64 _user_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst); -int64 _user_atomic_add64(vint64 *value, int64 addValue); -int64 _user_atomic_and64(vint64 *value, int64 andValue); -int64 _user_atomic_or64(vint64 *value, int64 orValue); -int64 _user_atomic_get64(vint64 *value); +void _user_atomic_set64(int64 *value, int64 newValue); +int64 _user_atomic_get_and_set64(int64 *value, int64 newValue); +int64 _user_atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst); +int64 _user_atomic_add64(int64 *value, int64 addValue); +int64 _user_atomic_and64(int64 *value, int64 andValue); +int64 _user_atomic_or64(int64 *value, int64 orValue); +int64 _user_atomic_get64(int64 *value); #ifdef __cplusplus } diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 3f475e7886..86d407bbfe 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -494,23 +494,25 @@ extern status_t _kern_system_profiler_recorded( /* atomic_* ops (needed for CPUs that don't support them directly) */ #ifdef ATOMIC_FUNCS_ARE_SYSCALLS -extern int32 _kern_atomic_set(vint32 *value, int32 newValue); -extern int32 _kern_atomic_test_and_set(vint32 *value, int32 newValue, +extern void _kern_atomic_set(int32 *value, int32 newValue); +extern int32 _kern_atomic_get_and_set(int32 *value, int32 newValue); +extern int32 _kern_atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst); -extern int32 _kern_atomic_add(vint32 *value, int32 addValue); -extern int32 _kern_atomic_and(vint32 *value, int32 andValue); -extern int32 _kern_atomic_or(vint32 *value, int32 orValue); -extern int32 _kern_atomic_get(vint32 *value); +extern int32 _kern_atomic_add(int32 *value, int32 addValue); +extern int32 _kern_atomic_and(int32 *value, int32 andValue); +extern int32 _kern_atomic_or(int32 *value, int32 orValue); +extern int32 _kern_atomic_get(int32 *value); #endif // ATOMIC_FUNCS_ARE_SYSCALLS #ifdef ATOMIC64_FUNCS_ARE_SYSCALLS -extern int64 _kern_atomic_set64(vint64 *value, int64 newValue); -extern int64 _kern_atomic_test_and_set64(vint64 *value, int64 newValue, +extern void _kern_atomic_set64(int64 *value, int64 newValue); +extern int64 _kern_atomic_get_and_set64(int64 *value, int64 newValue); +extern int64 _kern_atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst); -extern int64 _kern_atomic_add64(vint64 *value, int64 addValue); -extern int64 _kern_atomic_and64(vint64 *value, int64 andValue); -extern int64 _kern_atomic_or64(vint64 *value, int64 orValue); -extern int64 _kern_atomic_get64(vint64 *value); +extern int64 _kern_atomic_add64(int64 *value, int64 addValue); +extern int64 _kern_atomic_and64(int64 *value, int64 andValue); +extern int64 _kern_atomic_or64(int64 *value, int64 orValue); +extern int64 _kern_atomic_get64(int64 *value); #endif // ATOMIC64_FUNCS_ARE_SYSCALLS /* System informations */ diff --git a/src/system/kernel/arch/arm/arch_atomic32.cpp b/src/system/kernel/arch/arm/arch_atomic32.cpp index df10e72bed..12038f7506 100644 --- a/src/system/kernel/arch/arm/arch_atomic32.cpp +++ b/src/system/kernel/arch/arm/arch_atomic32.cpp @@ -24,18 +24,24 @@ * this is an acceptable compromise. */ -int32 -atomic_set(vint32 *value, int32 newValue) +void +atomic_set(int32 *value, int32 newValue) { InterruptsLocker locker; - - int32 oldValue = *value; *value = newValue; +} + +int32 +atomic_get_and_set(int32 *value, int32 newValue) +{ + InterruptsLocker locker; + int32 oldValue = *value; + atomic_set(value, newValue); return oldValue; } int32 -atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) +atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst) { InterruptsLocker locker; @@ -46,7 +52,7 @@ atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) } int32 -atomic_add(vint32 *value, int32 addValue) +atomic_add(int32 *value, int32 addValue) { InterruptsLocker locker; @@ -56,7 +62,7 @@ atomic_add(vint32 *value, int32 addValue) } int32 -atomic_and(vint32 *value, int32 andValue) +atomic_and(int32 *value, int32 andValue) { InterruptsLocker locker; @@ -66,7 +72,7 @@ atomic_and(vint32 *value, int32 andValue) } int32 -atomic_or(vint32 *value, int32 orValue) +atomic_or(int32 *value, int32 orValue) { InterruptsLocker locker; @@ -76,7 +82,7 @@ atomic_or(vint32 *value, int32 orValue) } int32 -atomic_get(vint32 *value) +atomic_get(int32 *value) { InterruptsLocker locker; @@ -84,12 +90,27 @@ atomic_get(vint32 *value) return oldValue; } -int32 -_user_atomic_set(vint32 *value, int32 newValue) +void +_user_atomic_set(int32 *value, int32 newValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { - int32 oldValue = atomic_set(value, newValue); + atomic_set(value, newValue); + unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); + return; + } + +access_violation: + // XXX kill application + return; +} + +int32 +_user_atomic_get_and_set(int32 *value, int32 newValue) +{ + if (IS_USER_ADDRESS(value) + && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { + int32 oldValue = atomic_get_and_set(value, newValue); unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); return oldValue; } @@ -100,11 +121,11 @@ access_violation: } int32 -_user_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) +_user_atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { - int32 oldValue = atomic_test_and_set(value, newValue, testAgainst); + int32 oldValue = atomic_test_and_set((int32*)value, newValue, testAgainst); unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE); return oldValue; } @@ -115,7 +136,7 @@ access_violation: } int32 -_user_atomic_add(vint32 *value, int32 addValue) +_user_atomic_add(int32 *value, int32 addValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { @@ -130,7 +151,7 @@ access_violation: } int32 -_user_atomic_and(vint32 *value, int32 andValue) +_user_atomic_and(int32 *value, int32 andValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { @@ -145,7 +166,7 @@ access_violation: } int32 -_user_atomic_or(vint32 *value, int32 orValue) +_user_atomic_or(int32 *value, int32 orValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { @@ -160,7 +181,7 @@ access_violation: } int32 -_user_atomic_get(vint32 *value) +_user_atomic_get(int32 *value) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) { diff --git a/src/system/kernel/arch/arm/arch_atomic64.cpp b/src/system/kernel/arch/arm/arch_atomic64.cpp index a57fd61c6d..371acfb74e 100644 --- a/src/system/kernel/arch/arm/arch_atomic64.cpp +++ b/src/system/kernel/arch/arm/arch_atomic64.cpp @@ -30,8 +30,17 @@ static spinlock atomic_lock = B_SPINLOCK_INITIALIZER; +void +atomic_set64(int64 *value, int64 newValue) +{ + SpinLocker locker(&atomic_lock); + + *value = newValue; +} + + int64 -atomic_set64(vint64 *value, int64 newValue) +atomic_get_and_set64(int64 *value, int64 newValue) { SpinLocker locker(&atomic_lock); @@ -42,7 +51,7 @@ atomic_set64(vint64 *value, int64 newValue) int64 -atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) +atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst) { SpinLocker locker(&atomic_lock); @@ -54,7 +63,7 @@ atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) int64 -atomic_add64(vint64 *value, int64 addValue) +atomic_add64(int64 *value, int64 addValue) { SpinLocker locker(&atomic_lock); @@ -65,7 +74,7 @@ atomic_add64(vint64 *value, int64 addValue) int64 -atomic_and64(vint64 *value, int64 andValue) +atomic_and64(int64 *value, int64 andValue) { SpinLocker locker(&atomic_lock); @@ -76,7 +85,7 @@ atomic_and64(vint64 *value, int64 andValue) int64 -atomic_or64(vint64 *value, int64 orValue) +atomic_or64(int64 *value, int64 orValue) { SpinLocker locker(&atomic_lock); @@ -87,7 +96,7 @@ atomic_or64(vint64 *value, int64 orValue) int64 -atomic_get64(vint64 *value) +atomic_get64(int64 *value) { SpinLocker locker(&atomic_lock); return *value; @@ -95,11 +104,11 @@ atomic_get64(vint64 *value) int64 -_user_atomic_set64(vint64 *value, int64 newValue) +_user_atomic_get_and_set64(int64 *value, int64 newValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { - int64 oldValue = atomic_set64(value, newValue); + int64 oldValue = atomic_get_and_set64(value, newValue); unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); return oldValue; } @@ -110,8 +119,24 @@ access_violation: } +void +_user_atomic_set64(int64 *value, int64 newValue) +{ + if (IS_USER_ADDRESS(value) + && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { + atomic_set64(value, newValue); + unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE); + return; + } + +access_violation: + // XXX kill application + return; +} + + int64 -_user_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) +_user_atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { @@ -127,7 +152,7 @@ access_violation: int64 -_user_atomic_add64(vint64 *value, int64 addValue) +_user_atomic_add64(int64 *value, int64 addValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { @@ -143,7 +168,7 @@ access_violation: int64 -_user_atomic_and64(vint64 *value, int64 andValue) +_user_atomic_and64(int64 *value, int64 andValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { @@ -159,7 +184,7 @@ access_violation: int64 -_user_atomic_or64(vint64 *value, int64 orValue) +_user_atomic_or64(int64 *value, int64 orValue) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { @@ -175,7 +200,7 @@ access_violation: int64 -_user_atomic_get64(vint64 *value) +_user_atomic_get64(int64 *value) { if (IS_USER_ADDRESS(value) && lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) { diff --git a/src/system/libroot/os/arch/arm/atomic.S b/src/system/libroot/os/arch/arm/atomic.S index 838395e51e..56bddd9875 100644 --- a/src/system/libroot/os/arch/arm/atomic.S +++ b/src/system/libroot/os/arch/arm/atomic.S @@ -49,15 +49,22 @@ miss3: ldrex r12, [r0] bx lr FUNCTION_END(atomic_or) -/* int atomic_set(int *value, int setTo) +/* void atomic_set(int *value, int setTo) */ FUNCTION(atomic_set): + str r1, [r0] + bx lr +FUNCTION_END(atomic_set) + +/* int atomic_get_and_set(int *value, int setTo) + */ +FUNCTION(atomic_get_and_set): miss4: ldrex r12, [r0] strex r3, r1, [r0] teq r3, #0 bne miss4 bx lr -FUNCTION_END(atomic_set) +FUNCTION_END(atomic_get_and_set) /* int atomic_test_and_set(int *value, int setTo, int testValue) */ diff --git a/src/system/libroot/os/atomic.c b/src/system/libroot/os/atomic.c index c4f20c1420..f2fff262c9 100644 --- a/src/system/libroot/os/atomic.c +++ b/src/system/libroot/os/atomic.c @@ -18,6 +18,13 @@ atomic_set(int32 *value, int32 newValue) } +int32 +atomic_get_and_set(int32 *value, int32 newValue) +{ + return _kern_atomic_get_and_set(value, newValue); +} + + int32 atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst) {