mirror of https://github.com/libsdl-org/SDL
Use specific acquire and release variants of InterlockedExchange on ARM
_InterlockedExchange_rel() is required for correctness on ARM because the _ReadWriteBarrier() macro is only a compiler memory barrier, not a hardware memory barrier. Due to ARM's relaxed memory model, this means the '*lock = 0' write may be observed before the operations inside the lock, causing possible corruption of data protected by the lock. _InterlockedExchange_acq() is more efficient on ARM because it avoids an expensive full memory barrier that _InterlockedExchange() does.
This commit is contained in:
parent
393c8c1f16
commit
014f507c40
|
@ -72,6 +72,9 @@ SDL_AtomicTryLock(SDL_SpinLock *lock)
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||||
|
return (_InterlockedExchange_acq(lock, 1) == 0);
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
|
SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
|
||||||
return (InterlockedExchange((long*)lock, 1) == 0);
|
return (InterlockedExchange((long*)lock, 1) == 0);
|
||||||
|
@ -173,7 +176,9 @@ SDL_AtomicLock(SDL_SpinLock *lock)
|
||||||
void
|
void
|
||||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||||
|
_InterlockedExchange_rel(lock, 0);
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
*lock = 0;
|
*lock = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue