From 5a339a2a5b12545c105a2a3dcfb1d8e466b0381f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 21 Jul 2014 23:14:48 -0700 Subject: [PATCH] Add macros for generic atomic functionality --- Alc/ALc.c | 8 +- Alc/ALu.c | 4 +- OpenAL32/Include/alMain.h | 2 +- OpenAL32/Include/alSource.h | 2 +- OpenAL32/alAuxEffectSlot.c | 4 +- OpenAL32/alListener.c | 10 +-- OpenAL32/alSource.c | 54 ++++++------- OpenAL32/alState.c | 16 ++-- include/atomic.h | 181 +++++++++++++++++++++++++++++++++++--------- 9 files changed, 195 insertions(+), 86 deletions(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index b55fda06..2cc40439 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1882,7 +1882,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) { ALsizei pos; - context->UpdateSources = AL_FALSE; + ATOMIC_STORE_UNSAFE(context->UpdateSources, AL_FALSE); LockUIntMapRead(&context->EffectSlotMap); for(pos = 0;pos < context->EffectSlotMap.size;pos++) { @@ -1914,7 +1914,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) source->Send[s].GainHF = 1.0f; s++; } - source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE_UNSAFE(source->NeedsUpdate, AL_TRUE); } UnlockUIntMapRead(&context->SourceMap); @@ -1931,7 +1931,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) } src->Update(src, context); - source->NeedsUpdate = AL_FALSE; + ATOMIC_STORE_UNSAFE(source->NeedsUpdate, AL_FALSE); } context = context->next; @@ -2111,7 +2111,7 @@ static ALvoid InitContext(ALCcontext *Context) //Validate Context Context->LastError = AL_NO_ERROR; - Context->UpdateSources = AL_FALSE; + ATOMIC_STORE_UNSAFE(Context->UpdateSources, AL_FALSE); Context->ActiveSourceCount = 0; InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources); InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax); diff --git a/Alc/ALu.c b/Alc/ALu.c index 2048f5fc..cc08d394 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -1167,7 +1167,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) ALenum UpdateSources = AL_FALSE; if(!DeferUpdates) - UpdateSources = ExchangeInt(&ctx->UpdateSources, AL_FALSE); + UpdateSources = ATOMIC_EXCHANGE(ALenum, ctx->UpdateSources, AL_FALSE); if(UpdateSources) CalcListenerParams(ctx->Listener); @@ -1188,7 +1188,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) continue; } - if(!DeferUpdates && (ExchangeInt(&source->NeedsUpdate, AL_FALSE) || + if(!DeferUpdates && (ATOMIC_EXCHANGE(ALenum, source->NeedsUpdate, AL_FALSE) || UpdateSources)) (*src)->Update(*src, ctx); diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index ba39405e..a444610f 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -748,7 +748,7 @@ struct ALCcontext_struct volatile ALenum LastError; - volatile ALenum UpdateSources; + ATOMIC(ALenum) UpdateSources; volatile enum DistanceModel DistanceModel; volatile ALboolean SourceDistanceModel; diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index e362f096..4b2ffe0b 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -124,7 +124,7 @@ typedef struct ALsource { } Send[MAX_SENDS]; /** Source needs to update its mixing parameters. */ - volatile ALenum NeedsUpdate; + ATOMIC(ALenum) NeedsUpdate; /** Self ID */ ALuint id; diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 08fa5a86..0eb79aec 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -183,7 +183,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param err = InitializeEffect(device, slot, effect); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); break; case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: @@ -191,7 +191,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); slot->AuxSendAuto = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); break; default: diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c index 87cd3c61..b98ea7c2 100644 --- a/OpenAL32/alListener.c +++ b/OpenAL32/alListener.c @@ -40,7 +40,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->Listener->Gain = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); break; case AL_METERS_PER_UNIT: @@ -48,7 +48,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->Listener->MetersPerUnit = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); break; default: @@ -77,7 +77,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val context->Listener->Position[0] = value1; context->Listener->Position[1] = value2; context->Listener->Position[2] = value3; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); UnlockContext(context); break; @@ -89,7 +89,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val context->Listener->Velocity[0] = value1; context->Listener->Velocity[1] = value2; context->Listener->Velocity[2] = value3; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); UnlockContext(context); break; @@ -142,7 +142,7 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) context->Listener->Up[0] = values[3]; context->Listener->Up[1] = values[4]; context->Listener->Up[2] = values[5]; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); UnlockContext(context); break; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 9f6c6a8b..a0a7e504 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -375,98 +375,98 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp CHECKVAL(*values >= 0.0f); Source->Pitch = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_INNER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->InnerAngle = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->OuterAngle = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_GAIN: CHECKVAL(*values >= 0.0f); Source->Gain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MAX_DISTANCE: CHECKVAL(*values >= 0.0f); Source->MaxDistance = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f); Source->RollOffFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_REFERENCE_DISTANCE: CHECKVAL(*values >= 0.0f); Source->RefDistance = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MIN_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MinGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MAX_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MaxGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_GAINHF: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGainHF = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AIR_ABSORPTION_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->AirAbsorptionFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_ROOM_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->RoomRolloffFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DOPPLER_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->DopplerFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_SEC_OFFSET: @@ -505,7 +505,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp Source->Position[1] = values[1]; Source->Position[2] = values[2]; UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_VELOCITY: @@ -516,7 +516,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp Source->Velocity[1] = values[1]; Source->Velocity[2] = values[2]; UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECTION: @@ -527,7 +527,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp Source->Orientation[1] = values[1]; Source->Orientation[2] = values[2]; UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -574,7 +574,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->HeadRelative = (ALboolean)*values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_LOOPING: @@ -692,35 +692,35 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->Direct.LFReference = filter->LFReference; } UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECT_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DryGainHFAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainHFAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECT_CHANNELS_SOFT: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DirectChannels = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DISTANCE_MODEL: @@ -734,7 +734,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->DistanceModel = *values; if(Context->SourceDistanceModel) - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -770,8 +770,8 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->Send[values[1]].GainLF = filter->GainLF; Source->Send[values[1]].LFReference = filter->LFReference; } - Source->NeedsUpdate = AL_TRUE; UnlockContext(Context); + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -2435,7 +2435,7 @@ static ALvoid InitSourceParams(ALsource *Source) Source->Send[i].LFReference = HIGHPASSFREQREF; } - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE_UNSAFE(Source->NeedsUpdate, AL_TRUE); } @@ -2530,7 +2530,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) src->Send[i].Moving = AL_FALSE; } } - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(Source->NeedsUpdate, AL_TRUE); } else if(state == AL_PAUSED) { diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c index d499fcd1..59619b0d 100644 --- a/OpenAL32/alState.c +++ b/OpenAL32/alState.c @@ -56,7 +56,7 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability) { case AL_SOURCE_DISTANCE_MODEL: context->SourceDistanceModel = AL_TRUE; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); break; default: @@ -78,7 +78,7 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability) { case AL_SOURCE_DISTANCE_MODEL: context->SourceDistanceModel = AL_FALSE; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); break; default: @@ -643,7 +643,7 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->DopplerFactor = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -660,7 +660,7 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->DopplerVelocity = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -677,7 +677,7 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->SpeedOfSound = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -698,7 +698,7 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value) context->DistanceModel = value; if(!context->SourceDistanceModel) - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -725,7 +725,7 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) context->DeferUpdates = AL_TRUE; /* Make sure all pending updates are performed */ - UpdateSources = ExchangeInt(&context->UpdateSources, AL_FALSE); + UpdateSources = ATOMIC_EXCHANGE(ALenum, context->UpdateSources, AL_FALSE); src = context->ActiveSources; src_end = src + context->ActiveSourceCount; @@ -742,7 +742,7 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) continue; } - if(ExchangeInt(&source->NeedsUpdate, AL_FALSE) || UpdateSources) + if(ATOMIC_EXCHANGE(ALenum, source->NeedsUpdate, AL_FALSE) || UpdateSources) (*src)->Update(*src, context); src++; diff --git a/include/atomic.h b/include/atomic.h index 4adb7a94..174aebe9 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -40,6 +40,33 @@ inline int CompExchangeInt(volatile int *ptr, int oldval, int newval) inline void *CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval) { return __sync_val_compare_and_swap(ptr, oldval, newval); } + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_INIT_STATIC(_newval) {(_newval)} + +#define ATOMIC_LOAD_UNSAFE(_val) ((_val).value) +#define ATOMIC_STORE_UNSAFE(_val, _newval) do { \ + (_val).value = (_newval); \ +} while(0) + +#define ATOMIC_LOAD(_val) (__sync_synchronize(),(_val).value) +#define ATOMIC_STORE(_val, _newval) do { \ + (_val).value = (_newval); \ + __sync_synchronize(); \ +} while(0) + +#define ATOMIC_EXCHANGE(T, _val, _newval) __extension__({ \ + static_assert(sizeof(T)==sizeof((_val).value), "Type "#T" has incorrect size!"); \ + T _r = __sync_lock_test_and_set(&(_val).value, (_newval)); \ + _r; \ +}) +#define ATOMIC_COMPARE_EXCHANGE(T, _val, _oldval, _newval) __extension__({ \ + static_assert(sizeof(T)==sizeof((_val).value), "Type "#T" has incorrect size!"); \ + T _r = __sync_val_compare_and_swap(&(_val).value, (_oldval), (_newval)); \ + _r; \ +}) + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) inline uint xaddl(volatile uint *dest, int incr) @@ -79,54 +106,91 @@ inline uint CompExchangeRef(volatile RefCount *ptr, uint oldval, uint newval) return ret; } +#define EXCHANGE(S, ret, dest, newval) __asm__ __volatile__( \ + "lock; xchg"S" %0,(%1)" \ + : "=r" (ret) \ + : "r" (dest), "0" (newval) \ + : "memory" \ +) +#define COMP_EXCHANGE(S, ret, dest, oldval, newval) __asm__ __volatile__( \ + "lock; cmpxchg"S" %2,(%1)" \ + : "=a" (ret) \ + : "r" (dest), "r" (newval), "0" (oldval) \ + : "memory" \ +) + + inline int ExchangeInt(volatile int *dest, int newval) { int ret; - __asm__ __volatile__("lock; xchgl %0,(%1)" - : "=r" (ret) - : "r" (dest), "0" (newval) - : "memory"); + EXCHANGE("l", ret, dest, newval); return ret; } +inline int CompExchangeInt(volatile int *dest, int oldval, int newval) +{ + int ret; + COMP_EXCHANGE("l", ret, dest, oldval, newval); + return ret; +} + +#ifdef __i386__ inline void *ExchangePtr(XchgPtr *dest, void *newval) { void *ret; - __asm__ __volatile__( -#ifdef __i386__ - "lock; xchgl %0,(%1)" -#else - "lock; xchgq %0,(%1)" -#endif - : "=r" (ret) - : "r" (dest), "0" (newval) - : "memory" - ); + EXCHANGE("l", ret, dest, newval); return ret; } -inline int CompExchangeInt(volatile int *dest, int oldval, int newval) +inline void *CompExchangePtr(XchgPtr *dest, void *oldval, void *newval) { - int ret; - __asm__ __volatile__("lock; cmpxchgl %2,(%1)" - : "=a" (ret) - : "r" (dest), "r" (newval), "0" (oldval) - : "memory"); + void *ret; + COMP_EXCHANGE("l", ret, dest, oldval, newval); + return ret; +} +#else +inline void *ExchangePtr(XchgPtr *dest, void *newval) +{ + void *ret; + EXCHANGE("q", ret, dest, newval); return ret; } inline void *CompExchangePtr(XchgPtr *dest, void *oldval, void *newval) { void *ret; - __asm__ __volatile__( -#ifdef __i386__ - "lock; cmpxchgl %2,(%1)" -#else - "lock; cmpxchgq %2,(%1)" -#endif - : "=a" (ret) - : "r" (dest), "r" (newval), "0" (oldval) - : "memory" - ); + COMP_EXCHANGE("q", ret, dest, oldval, newval); return ret; } +#endif + + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_INIT_STATIC(_newval) {(_newval)} + +#define ATOMIC_LOAD_UNSAFE(_val) ((_val).value) +#define ATOMIC_STORE_UNSAFE(_val, _newval) do { \ + (_val).value = (_newval); \ +} while(0) + +#define ATOMIC_LOAD(_val) (__asm__ __volatile__("" ::: "memory"),(_val).value) +#define ATOMIC_STORE(_val, _newval) do { \ + (_val).value = (_newval); \ + __asm__ __volatile__("" ::: "memory"); \ +} while(0) + +#define ATOMIC_EXCHANGE(T, _val, _newval) __extension__({ \ + T _r; \ + static_assert(sizeof(T)==sizeof((_val).value), "Type "#T" has incorrect size!"); \ + if(sizeof(T) == 4) EXCHANGE("l", _r, &(_val).value, (_newval)); \ + else if(sizeof(T) == 8) EXCHANGE("q", _r, &(_val).value, (_newval)); \ + _r; \ +}) +#define ATOMIC_COMPARE_EXCHANGE(T, _val, _oldval, _newval) __extension__({ \ + T _r; \ + static_assert(sizeof(T)==sizeof((_val).value), "Type "#T" has incorrect size!"); \ + if(sizeof(T) == 4) COMP_EXCHANGE("l", _r, &(_val).value, (_oldval), (_newval)); \ + else if(sizeof(T) == 8) COMP_EXCHANGE("q", _r, &(_val).value, (_oldval), (_newval)); \ + _r; \ +}) #elif defined(_WIN32) @@ -172,7 +236,7 @@ inline uint CompExchangeRef(volatile RefCount *ptr, uint oldval, uint newval) return InterlockedCompareExchange(u.l, newval, oldval); } -inline int ExchangeInt(volatile int *ptr, int newval) +inline int ExchangeInt32(volatile int *ptr, int newval) { union { volatile int *i; @@ -180,11 +244,7 @@ inline int ExchangeInt(volatile int *ptr, int newval) } u = { ptr }; return InterlockedExchange(u.l, newval); } -inline void *ExchangePtr(XchgPtr *ptr, void *newval) -{ - return InterlockedExchangePointer(ptr, newval); -} -inline int CompExchangeInt(volatile int *ptr, int oldval, int newval) +inline int CompExchangeInt32(volatile int *ptr, int oldval, int newval) { union { volatile int *i; @@ -192,11 +252,60 @@ inline int CompExchangeInt(volatile int *ptr, int oldval, int newval) } u = { ptr }; return InterlockedCompareExchange(u.l, newval, oldval); } +inline __int64 ExchangeInt64(volatile __int64 *ptr, __int64 newval) +{ + union { + volatile __int64 *i; + volatile LONGLONG *l; + } u = { ptr }; + return InterlockedExchange64(u.l, newval); +} +inline __int64 CompExchangeInt64(volatile __int64 *ptr, __int64 oldval, __int64 newval) +{ + union { + volatile __int64 *i; + volatile LONGLONG *l; + } u = { ptr }; + return InterlockedCompareExchange64(u.l, newval, oldval); +} + +inline int ExchangeInt(volatile int *ptr, int newval) +{ return ExchangeInt32(ptr, newval); } +inline int CompExchangeInt(volatile int *ptr, int oldval, int newval) +{ return CompExchangeInt32(ptr, oldval, newval); } + +inline void *ExchangePtr(XchgPtr *ptr, void *newval) +{ + return InterlockedExchangePointer(ptr, newval); +} inline void *CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval) { return InterlockedCompareExchangePointer(ptr, newval, oldval); } + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_INIT_STATIC(_newval) {(_newval)} + +#define ATOMIC_LOAD_UNSAFE(_val) ((_val).value) +#define ATOMIC_STORE_UNSAFE(_val, _newval) do { \ + (_val).value = (_newval); \ +} while(0) + +#define ATOMIC_LOAD(_val) (_ReadBarrier(),(_val).value) +#define ATOMIC_STORE(_val, _newval) do { \ + (_val).value = (_newval); \ + _WriteBarrier(); \ +} while(0) + +int _al_invalid_atomic_size(); /* not defined */ + +#define ATOMIC_FUNC_SELECT(T, C, F32, F64) ((sizeof(T) == 4) ? (C)F32 : ((sizeof(T) == 8) ? (C)F64 : (C)_al_invalid_atomic_size)) + +#define ATOMIC_EXCHANGE(T, _val, _newval) (ATOMIC_FUNC_SELECT(T, T(*)(volatile T*,T), ExchangeInt32, ExchangeInt64)(&(_val).value, (_newval))) +#define ATOMIC_COMPARE_EXCHANGE(T, _val, _oldval, _newval) (ATOMIC_FUNC_SELECT(T, T(*)(volatile T*,T,T), CompExchangeInt32, CompExchangeInt64)(&(_val).value, (_oldval), (_newval))) + #else #error "No atomic functions available on this platform!" #endif -- 2.11.4.GIT