- Add missing SDL_MemoryBarrierRelease() in the generic codepath
- Remove Watcom and MSVC x86/x64 cases which are now identical to the generic codepath
- Fix Solaris barrier to ensure prior stores are visible before unlocking
__sync_lock_test_and_set() is designed for creating locks, not as
a general atomic exchange function. As a result, it only provides
an acquire memory barrier and isn't guaranteed to actually store
the provided value (though it does on architectures we care about).
__atomic_exchange_n() is supported on GCC/Clang for the last ~10
years, so let's use that instead if available. We will keep the
__sync_lock_test_and_set() fallback around for ancient platforms,
but add a full memory barrier to match the documented behavior.
I updated .clang-format and ran clang-format 14 over the src and test directories to standardize the code base.
In general I let clang-format have it's way, and added markup to prevent formatting of code that would break or be completely unreadable if formatted.
The script I ran for the src directory is added as build-scripts/clang-format-src.sh
This fixes:
#6592#6593#6594
(cherry picked from commit 5750bcb174)
* Add braces after if conditions
* More add braces after if conditions
* Add braces after while() conditions
* Fix compilation because of macro being modified
* Add braces to for loop
* Add braces after if/goto
* Move comments up
* Remove extra () in the 'return ...;' statements
* More remove extra () in the 'return ...;' statements
* More remove extra () in the 'return ...;' statements after merge
* Fix inconsistent patterns are xxx == NULL vs !xxx
* More "{}" for "if() break;" and "if() continue;"
* More "{}" after if() short statement
* More "{}" after "if () return;" statement
* More fix inconsistent patterns are xxx == NULL vs !xxx
* Revert some modificaion on SDL_RLEaccel.c
* SDL_RLEaccel: no short statement
* Cleanup 'if' where the bracket is in a new line
* Cleanup 'while' where the bracket is in a new line
* Cleanup 'for' where the bracket is in a new line
* Cleanup 'else' where the bracket is in a new line
(cherry picked from commit 6a2200823c to reduce conflicts merging between SDL2 and SDL3)
- use _Interlocked(Compare)ExchangePointer in case of _M_IX86 as well
- improve assertions:
1. add assertions to SDL_AtomicAdd/SDL_AtomicSet and SDL_AtomicCAS
2. use sizeof(a->value) instead of sizeof(int)
When building on macOS without gcc (e.g. clang) where HAVE_GCC_ATOMICS
is not defined, `SDL_AtomicTryLock` will call
`OSAtomicCompareAndSwap32Barrier` which is not yet declared.
Including OSAtomic.h on OSX resolves this error/warning:
SDL_spinlock.c:125:12: error: implicit declaration of function
'OSAtomicCompareAndSwap32Barrier' is invalid in
C99 [-Werror,-Wimplicit-function-declaration]
return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
This was reported in issue #3885 but marked Invalid and closed - possibly
because the default CMake build uses gcc instead of clang.
_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.
David Carlier
This form of 'or' provides a hint that performance
will probably be improved if shared resources dedicated
to the executing processor are released for use by other
processors
The real problem is that SDL_atomic.c was built in thumb mode instead of ARM mode, which is required to use the mcr instruction on ARM platforms. Added a compiler error to catch this case so we don't generate code that does infinite recursion.
I also added a potentially better way to handle things on Linux ARM platforms, based on comments in the Chromium headers, which we can try out after 2.0.10 ships.