aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c8
-rw-r--r--Alc/ALu.c4
-rw-r--r--OpenAL32/Include/alMain.h2
-rw-r--r--OpenAL32/Include/alSource.h2
-rw-r--r--OpenAL32/alAuxEffectSlot.c4
-rw-r--r--OpenAL32/alListener.c10
-rw-r--r--OpenAL32/alSource.c54
-rw-r--r--OpenAL32/alState.c16
-rw-r--r--include/atomic.h181
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