* Copyright 2007, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* FranΓ§ois Revol <revol@free.fr>
*
* Copyright 2003, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <kernel.h>
#include <user_atomic.h>
* Emulation of 64 bit atomic functions.
* Slow, using spinlocks...
*/
#warning M68K: detect 060 here
#if 0
static spinlock atomic_lock = 0;
int64
atomic_set64(vint64 *value, int64 newValue)
{
cpu_status status;
int64 oldValue;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value = newValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
return oldValue;
}
int64
atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst)
{
cpu_status status;
int64 oldValue;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
if (oldValue == testAgainst)
*value = newValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
return oldValue;
}
int64
atomic_add64(vint64 *value, int64 addValue)
{
cpu_status status;
int64 oldValue;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value += addValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
return oldValue;
}
int64
atomic_and64(vint64 *value, int64 andValue)
{
cpu_status status;
int64 oldValue;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value &= andValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
return oldValue;
}
int64
atomic_or64(vint64 *value, int64 orValue)
{
cpu_status status;
int64 oldValue;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value |= orValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
return oldValue;
}
int64
atomic_get64(vint64 *value)
{
cpu_status status;
int64 oldValue;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
release_spinlock(&atomic_lock);
restore_interrupts(status);
return oldValue;
}
int64
_user_atomic_set64(vint64 *value, int64 newValue)
{
cpu_status status;
int64 oldValue;
if (!IS_USER_ADDRESS(value)
|| lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK)
goto access_violation;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value = newValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
unlock_memory((void *)value, 8, B_READ_DEVICE);
return oldValue;
access_violation:
return -1;
}
int64
_user_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst)
{
cpu_status status;
int64 oldValue;
if (!IS_USER_ADDRESS(value)
|| lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK)
goto access_violation;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
if (oldValue == testAgainst)
*value = newValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
unlock_memory((void *)value, 8, B_READ_DEVICE);
return oldValue;
access_violation:
return -1;
}
int64
_user_atomic_add64(vint64 *value, int64 addValue)
{
cpu_status status;
int64 oldValue;
if (!IS_USER_ADDRESS(value)
|| lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK)
goto access_violation;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value += addValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
unlock_memory((void *)value, 8, B_READ_DEVICE);
return oldValue;
access_violation:
return -1;
}
int64
_user_atomic_and64(vint64 *value, int64 andValue)
{
cpu_status status;
int64 oldValue;
if (!IS_USER_ADDRESS(value)
|| lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK)
goto access_violation;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value &= andValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
unlock_memory((void *)value, 8, B_READ_DEVICE);
return oldValue;
access_violation:
return -1;
}
int64
_user_atomic_or64(vint64 *value, int64 orValue)
{
cpu_status status;
int64 oldValue;
if (!IS_USER_ADDRESS(value)
|| lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK)
goto access_violation;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
*value |= orValue;
release_spinlock(&atomic_lock);
restore_interrupts(status);
unlock_memory((void *)value, 8, B_READ_DEVICE);
return oldValue;
access_violation:
return -1;
}
int64
_user_atomic_get64(vint64 *value)
{
cpu_status status;
int64 oldValue;
if (!IS_USER_ADDRESS(value)
|| lock_memory((void *)value, 8, B_READ_DEVICE) != B_OK)
goto access_violation;
status = disable_interrupts();
acquire_spinlock(&atomic_lock);
oldValue = *value;
release_spinlock(&atomic_lock);
restore_interrupts(status);
unlock_memory((void *)value, 8, B_READ_DEVICE);
return oldValue;
access_violation:
return -1;
}
#endif