#include <KernelExport.h>
#include <kernel.h>
#include <user_atomic.h>
#include <util/AutoLock.h>
#ifdef ATOMIC64_FUNCS_ARE_SYSCALLS
static spinlock atomic_lock = B_SPINLOCK_INITIALIZER;
void
atomic_set64(int64 *value, int64 newValue)
{
SpinLocker locker(&atomic_lock);
*value = newValue;
}
int64
atomic_get_and_set64(int64 *value, int64 newValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value = newValue;
return oldValue;
}
int64
atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
if (oldValue == testAgainst)
*value = newValue;
return oldValue;
}
int64
atomic_add64(int64 *value, int64 addValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value += addValue;
return oldValue;
}
int64
atomic_and64(int64 *value, int64 andValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value &= andValue;
return oldValue;
}
int64
atomic_or64(int64 *value, int64 orValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value |= orValue;
return oldValue;
}
int64
atomic_get64(int64 *value)
{
SpinLocker locker(&atomic_lock);
return *value;
}
int64
_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_get_and_set64(value, newValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
return -1;
}
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:
return;
}
int64
_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) {
int64 oldValue = atomic_test_and_set64(value, newValue, testAgainst);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
return -1;
}
int64
_user_atomic_add64(int64 *value, int64 addValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_add64(value, addValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
return -1;
}
int64
_user_atomic_and64(int64 *value, int64 andValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_and64(value, andValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
return -1;
}
int64
_user_atomic_or64(int64 *value, int64 orValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_or64(value, orValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
return -1;
}
int64
_user_atomic_get64(int64 *value)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_get64(value);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
return -1;
}
#endif