#endif
#endif /* _MSC_VER */
+#if defined(__arm__) && !defined(FAKE_ATOMIC)
/*
* LDREX without STREX or CLREX may cause problems in environments where the
* context switch may not clear the reference monitor - according ARM manual
* may not like Linux kernel's non-preemptive context switch path. So use of
* ARM routines in kernel code may not be safe.
*/
-#ifdef __arm__
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__)
# define VM_ARM_V7
Atomic_ReadWrite(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ uint32 retval = var->value;
+ var->value = val;
+ return retval;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 retVal;
register volatile uint32 res;
uint32 oldVal, // IN
uint32 newVal) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ uint32 readVal = var->value;
+
+ if (oldVal == readVal) {
+ var->value = newVal;
+ }
+ return oldVal;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register uint32 retVal;
register uint32 res;
Atomic_And(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ var->value &= val;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 res;
register volatile uint32 tmp;
Atomic_Or(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ var->value |= val;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 res;
register volatile uint32 tmp;
Atomic_Xor(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ var->value ^= val;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 res;
register volatile uint32 tmp;
Atomic_Add(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ var->value += val;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 res;
register volatile uint32 tmp;
Atomic_Sub(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ var->value -= val;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 res;
register volatile uint32 tmp;
Atomic_Inc(Atomic_uint32 *var) // IN
{
#ifdef __GNUC__
-#ifdef VM_ARM_V7
+#if defined(VM_ARM_V7) || defined(FAKE_ATOMIC)
Atomic_Add(var, 1);
#else // VM_ARM_V7
/* Checked against the Intel manual and GCC --walken */
Atomic_Dec(Atomic_uint32 *var) // IN
{
#ifdef __GNUC__
-#ifdef VM_ARM_V7
+#if defined(VM_ARM_V7) || defined(FAKE_ATOMIC)
Atomic_Sub(var, 1);
#else // VM_ARM_V7
/* Checked against the Intel manual and GCC --walken */
Atomic_FetchAndAddUnfenced(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ uint32 res = var->value;
+ var->value = res + val;
+ return res;
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
register volatile uint32 res;
register volatile uint32 retVal;
Atomic_FetchAndAdd(Atomic_uint32 *var, // IN
uint32 val) // IN
{
-#if defined(__GNUC__) && !defined(VM_ARM_V7)
+#if defined(__GNUC__) && !defined(VM_ARM_V7) && !defined(FAKE_ATOMIC)
val = Atomic_FetchAndAddUnfenced(var, val);
AtomicEpilogue();
return val;
uint64 const *oldVal, // IN
uint64 const *newVal) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ uint64 readVal = var->value;
+ if (*oldVal == readVal) {
+ var->value = *newVal;
+ }
+ return (*oldVal == readVal);
+#elif defined(__GNUC__)
#if defined(VM_ARM_V7)
return (Atomic_ReadIfEqualWrite64(var, *oldVal, *newVal) == *oldVal);
uint32 oldVal, // IN
uint32 newVal) // IN
{
-#ifdef __GNUC__
+#ifdef FAKE_ATOMIC
+ uint32 readVal = var->value;
+
+ if (oldVal == readVal) {
+ var->value = newVal;
+ }
+ return (oldVal == readVal);
+#elif defined(__GNUC__)
#ifdef VM_ARM_V7
return (Atomic_ReadIfEqualWrite(var, oldVal, newVal) == oldVal);
#else // VM_ARM_V7
static INLINE uint64
Atomic_Read64(Atomic_uint64 const *var) // IN
{
-#if defined(__GNUC__) && defined(__x86_64__)
+#ifdef FAKE_ATOMIC
+ return var->value;
+#elif defined(__GNUC__) && defined(__x86_64__)
uint64 value;
#ifdef VMM