From 42f634ff7a4a653fb8597532cffe5cf9ce1781a6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 27 Aug 2025 06:07:10 -0700 Subject: [PATCH] Added SDL_AddAtomicU32() Fixes https://github.com/libsdl-org/SDL/issues/13496 --- include/SDL3/SDL_atomic.h | 18 ++++++++++++++++++ src/atomic/SDL_atomic.c | 24 ++++++++++++++++++++++++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + 5 files changed, 45 insertions(+) diff --git a/include/SDL3/SDL_atomic.h b/include/SDL3/SDL_atomic.h index 78b5e0fa5b..3d136e79db 100644 --- a/include/SDL3/SDL_atomic.h +++ b/include/SDL3/SDL_atomic.h @@ -596,6 +596,24 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_SetAtomicU32(SDL_AtomicU32 *a, Uint32 v); */ extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetAtomicU32(SDL_AtomicU32 *a); +/** + * Add to an atomic variable. + * + * This function also acts as a full memory barrier. + * + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to an SDL_AtomicU32 variable to be modified. + * \param v the desired value to add or subtract. + * \returns the previous value of the atomic variable. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.2.0. + */ +extern SDL_DECLSPEC Uint32 SDLCALL SDL_AddAtomicU32(SDL_AtomicU32 *a, int v); + /** * Set a pointer to a new value if it is currently an old value. * diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index 7a575ac23a..c51ba710a5 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -298,6 +298,30 @@ int SDL_AddAtomicInt(SDL_AtomicInt *a, int v) #endif } +Uint32 SDL_AddAtomicU32(SDL_AtomicU32 *a, int v) +{ +#ifdef HAVE_MSC_ATOMICS + SDL_COMPILE_TIME_ASSERT(atomic_add, sizeof(long) == sizeof(a->value)); + return (Uint32)_InterlockedExchangeAdd((long *)&a->value, v); +#elif defined(HAVE_WATCOM_ATOMICS) + SDL_COMPILE_TIME_ASSERT(atomic_add, sizeof(int) == sizeof(a->value)); + return (Uint32)_SDL_xadd_watcom((volatile int *)&a->value, v); +#elif defined(HAVE_GCC_ATOMICS) + return __sync_fetch_and_add(&a->value, v); +#elif defined(SDL_PLATFORM_SOLARIS) + Uint32 pv = a->value; + membar_consumer(); + atomic_add_int((volatile uint_t *)&a->value, v); + return pv; +#else + Uint32 value; + do { + value = a->value; + } while (!SDL_CompareAndSwapAtomicU32(a, value, (value + v))); + return value; +#endif +} + int SDL_GetAtomicInt(SDL_AtomicInt *a) { #ifdef HAVE_ATOMIC_LOAD_N diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index c69956e8b0..0419932342 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1253,6 +1253,7 @@ SDL3_0.0.0 { SDL_PutAudioStreamPlanarData; SDL_GetEventDescription; SDL_PutAudioStreamDataNoCopy; + SDL_AddAtomicU32; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 61eb4b956d..3635136817 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1278,3 +1278,4 @@ #define SDL_PutAudioStreamPlanarData SDL_PutAudioStreamPlanarData_REAL #define SDL_GetEventDescription SDL_GetEventDescription_REAL #define SDL_PutAudioStreamDataNoCopy SDL_PutAudioStreamDataNoCopy_REAL +#define SDL_AddAtomicU32 SDL_AddAtomicU32_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 1230d583f0..d5e933534a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1286,3 +1286,4 @@ SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShader SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamPlanarData,(SDL_AudioStream *a,const void * const*b,int c,int d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),(a,b,c),return) SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamDataNoCopy,(SDL_AudioStream *a,const void *b,int c,SDL_AudioStreamDataCompleteCallback d,void *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(Uint32,SDL_AddAtomicU32,(SDL_AtomicU32 *a,int b),(a,b),return)