diff options
-rw-r--r-- | Alc/ALc.c | 36 | ||||
-rw-r--r-- | Alc/ALu.c | 12 | ||||
-rw-r--r-- | Alc/backends/opensl.c | 4 | ||||
-rw-r--r-- | Alc/backends/oss.c | 4 | ||||
-rw-r--r-- | Alc/backends/solaris.c | 2 | ||||
-rw-r--r-- | Alc/helpers.c | 4 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 18 | ||||
-rw-r--r-- | OpenAL32/alError.c | 4 | ||||
-rw-r--r-- | OpenAL32/alListener.c | 7 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 19 | ||||
-rw-r--r-- | include/atomic.h | 133 |
11 files changed, 135 insertions, 108 deletions
@@ -1247,7 +1247,7 @@ static void alc_cleanup(void) free(alcCaptureDefaultDeviceSpecifier); alcCaptureDefaultDeviceSpecifier = NULL; - if((dev=ATOMIC_EXCHANGE_SEQ(ALCdevice*, &DeviceList, NULL)) != NULL) + if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL) { ALCuint num = 0; do { @@ -1678,7 +1678,7 @@ void ALCcontext_DeferUpdates(ALCcontext *context) void ALCcontext_ProcessUpdates(ALCcontext *context) { ReadLock(&context->PropLock); - if(ATOMIC_EXCHANGE_SEQ(ALenum, &context->DeferUpdates, AL_FALSE)) + if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE)) { /* Tell the mixer to stop applying updates, then wait for any active * updating to finish, before providing updates. @@ -2225,11 +2225,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) * number of auxiliary sends changed. Playing (or paused) sources * will have updates respecified in UpdateAllSourceProps. */ - props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL); + props = ATOMIC_EXCHANGE_PTR_SEQ(&source->Update, NULL); al_free(props); - props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL, - almemory_order_relaxed); + props = ATOMIC_EXCHANGE_PTR(&source->FreeList, NULL, almemory_order_relaxed); while(props) { struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); @@ -2489,8 +2488,7 @@ static void FreeContext(ALCcontext *context) TRACE("%p\n", context); - auxslots = ATOMIC_EXCHANGE(struct ALeffectslotArray*, &context->ActiveAuxSlots, - NULL, almemory_order_relaxed); + auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed); al_free(auxslots); if(context->SourceMap.size > 0) @@ -2557,13 +2555,13 @@ static bool ReleaseContext(ALCcontext *context, ALCdevice *device) } origctx = context; - if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL)) + if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL)) ALCcontext_DecRef(context); ALCdevice_Lock(device); origctx = context; newhead = context->next; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList, &origctx, newhead)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead)) { ALCcontext *volatile*list = &origctx->next; while(*list) @@ -2750,11 +2748,11 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) if(VerifyDevice(&device)) { - errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR); + errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR); ALCdevice_DecRef(device); } else - errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR); + errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR); return errorCode; } @@ -3549,8 +3547,8 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList); do { ALContext->next = head; - } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*, - &device->ContextList, &head, ALContext) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head, + ALContext) == 0); } almtx_unlock(&device->BackendLock); @@ -3628,7 +3626,7 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) return ALC_FALSE; } /* context's reference count is already incremented */ - context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context); + context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context); if(context) ALCcontext_DecRef(context); if((context=altss_get(LocalContext)) != NULL) @@ -3937,7 +3935,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList); do { device->next = head; - } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); + } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device)); } TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName)); @@ -3968,7 +3966,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) almtx_lock(&device->BackendLock); origdev = device; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next)) { ALCdevice *volatile*list = &origdev->next; while(*list) @@ -4113,7 +4111,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList); do { device->next = head; - } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); + } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device)); } TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName)); @@ -4138,7 +4136,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) } origdev = device; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next)) { ALCdevice *volatile*list = &origdev->next; while(*list) @@ -4334,7 +4332,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList); do { device->next = head; - } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); + } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device)); } TRACE("Created device %p\n", device); @@ -241,7 +241,7 @@ static ALboolean CalcListenerParams(ALCcontext *Context) struct ALlistenerProps *props; aluVector vel; - props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &Listener->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&Listener->Update, NULL, almemory_order_acq_rel); if(!props) return AL_FALSE; /* AT then UP */ @@ -291,7 +291,7 @@ static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device) struct ALeffectslotProps *props; ALeffectState *state; - props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&slot->Update, NULL, almemory_order_acq_rel); if(!props) return AL_FALSE; slot->Params.Gain = props->Gain; @@ -1252,7 +1252,7 @@ static void CalcSourceParams(ALvoice *voice, ALsource *source, ALCcontext *conte const ALbufferlistitem *BufferListItem; struct ALsourceProps *props; - props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&source->Update, NULL, almemory_order_acq_rel); if(!props && !force) return; if(props) @@ -1607,14 +1607,14 @@ void aluHandleDisconnect(ALCdevice *device) voice_end = voice + Context->VoiceCount; while(voice != voice_end) { - ALsource *source = ATOMIC_EXCHANGE(ALsource*, &(*voice)->Source, NULL, - almemory_order_acq_rel); + ALsource *source = ATOMIC_EXCHANGE_PTR(&(*voice)->Source, NULL, + almemory_order_acq_rel); ATOMIC_STORE(&(*voice)->Playing, false, almemory_order_release); if(source) { ALenum playing = AL_PLAYING; - ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &source->state, &playing, AL_STOPPED); + (void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&source->state, &playing, AL_STOPPED)); } voice++; diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 622437b8..4e295f23 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -149,7 +149,7 @@ typedef struct ALCopenslPlayback { ALsizei mFrameSize; - ATOMIC(ALboolean) mKillNow; + ATOMIC(ALenum) mKillNow; althrd_t mThread; } ALCopenslPlayback; @@ -637,7 +637,7 @@ static void ALCopenslPlayback_stop(ALCopenslPlayback *self) SLresult result; int res; - if(ATOMIC_EXCHANGE_SEQ(ALboolean, &self->mKillNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->mKillNow, AL_TRUE)) return; /* Lock the backend to ensure we don't flag the mixer to die and signal the diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 6774a789..33ea55eb 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -491,7 +491,7 @@ static void ALCplaybackOSS_stop(ALCplaybackOSS *self) { int res; - if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) return; althrd_join(self->thread, &res); @@ -745,7 +745,7 @@ static void ALCcaptureOSS_stop(ALCcaptureOSS *self) { int res; - if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) return; althrd_join(self->thread, &res); diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 5b3f6136..5dfb5084 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -285,7 +285,7 @@ static void ALCsolarisBackend_stop(ALCsolarisBackend *self) { int res; - if(ATOMIC_EXCHANGE_SEQ(int, &self->killNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) return; althrd_join(self->thread, &res); diff --git a/Alc/helpers.c b/Alc/helpers.c index 5d23c3a7..8e685c75 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -564,7 +564,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) vector_al_string results = VECTOR_INIT_STATIC(); size_t i; - while(ATOMIC_EXCHANGE_SEQ(uint, &search_lock, 1) == 1) + while(ATOMIC_EXCHANGE_SEQ(&search_lock, 1) == 1) althrd_yield(); /* If the path is absolute, use it directly. */ @@ -840,7 +840,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) static RefCount search_lock; vector_al_string results = VECTOR_INIT_STATIC(); - while(ATOMIC_EXCHANGE_SEQ(uint, &search_lock, 1) == 1) + while(ATOMIC_EXCHANGE_SEQ(&search_lock, 1) == 1) althrd_yield(); if(subdir[0] == '/') diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 743fac14..de7de943 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -126,9 +126,8 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo if(curarray) memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count); - newarray = ATOMIC_EXCHANGE(struct ALeffectslotArray*, - &context->ActiveAuxSlots, newarray, almemory_order_acq_rel - ); + newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, + almemory_order_acq_rel); device = context->Device; while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1)) althrd_yield(); @@ -187,9 +186,8 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint * newarray->slot[i++] = slot; } - newarray = ATOMIC_EXCHANGE(struct ALeffectslotArray*, - &context->ActiveAuxSlots, newarray, almemory_order_acq_rel - ); + newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, + almemory_order_acq_rel); device = context->Device; while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1)) althrd_yield(); @@ -668,9 +666,8 @@ void UpdateEffectSlotProps(ALeffectslot *slot) struct ALeffectslotProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, - &slot->FreeList, &props, next, almemory_order_seq_cst, - almemory_order_acquire) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next, + almemory_order_seq_cst, almemory_order_acquire) == 0); } /* Copy in current property values. */ @@ -687,8 +684,7 @@ void UpdateEffectSlotProps(ALeffectslot *slot) props->State = slot->Effect.State; /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, props, - almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the diff --git a/OpenAL32/alError.c b/OpenAL32/alError.c index 19fcaa6d..6c953977 100644 --- a/OpenAL32/alError.c +++ b/OpenAL32/alError.c @@ -49,7 +49,7 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode) #endif } - ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &Context->LastError, &curerr, errorCode); + (void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&Context->LastError, &curerr, errorCode)); } AL_API ALenum AL_APIENTRY alGetError(void) @@ -74,7 +74,7 @@ AL_API ALenum AL_APIENTRY alGetError(void) return AL_INVALID_OPERATION; } - errorCode = ATOMIC_EXCHANGE_SEQ(ALenum, &Context->LastError, AL_NO_ERROR); + errorCode = ATOMIC_EXCHANGE_SEQ(&Context->LastError, AL_NO_ERROR); ALCcontext_DecRef(Context); diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c index e3d71435..d117c0ca 100644 --- a/OpenAL32/alListener.c +++ b/OpenAL32/alListener.c @@ -468,9 +468,8 @@ void UpdateListenerProps(ALCcontext *context) struct ALlistenerProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*, - &listener->FreeList, &props, next, almemory_order_seq_cst, - almemory_order_acquire) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&listener->FreeList, &props, next, + almemory_order_seq_cst, almemory_order_acquire) == 0); } /* Copy in current property values. */ @@ -500,7 +499,7 @@ void UpdateListenerProps(ALCcontext *context) props->DistanceModel = context->DistanceModel;; /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &listener->Update, props, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&listener->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index a8c4ce2f..040078df 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -158,7 +158,7 @@ static inline ALenum GetSourceState(ALsource *source, ALvoice *voice) if(!voice) { ALenum state = AL_PLAYING; - if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALenum, &source->state, &state, AL_STOPPED, + if(ATOMIC_COMPARE_EXCHANGE_STRONG(&source->state, &state, AL_STOPPED, almemory_order_acq_rel, almemory_order_acquire)) return AL_STOPPED; return state; @@ -747,7 +747,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->SourceType = AL_UNDETERMINED; newlist = NULL; } - oldlist = ATOMIC_EXCHANGE_SEQ(ALbufferlistitem*, &Source->queue, newlist); + oldlist = ATOMIC_EXCHANGE_PTR_SEQ(&Source->queue, newlist); WriteUnlock(&Source->queue_lock); UnlockBuffersRead(device); @@ -2784,8 +2784,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu source->SourceType = AL_STREAMING; BufferList = NULL; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALbufferlistitem*, &source->queue, - &BufferList, BufferListStart)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&source->queue, &BufferList, + BufferListStart)) { /* Queue head is not NULL, append to the end of the queue */ while(BufferList->next != NULL) @@ -2854,7 +2854,7 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint } /* Swap it, and cut the new head from the old. */ - OldHead = ATOMIC_EXCHANGE_SEQ(ALbufferlistitem*, &source->queue, OldTail->next); + OldHead = ATOMIC_EXCHANGE_PTR_SEQ(&source->queue, OldTail->next); if(OldTail->next) { ALCdevice *device = context->Device; @@ -3003,7 +3003,7 @@ static void DeinitSource(ALsource *source, ALsizei num_sends) if(count > 3) WARN("Freed "SZFMT" Source property objects\n", count); - BufferList = ATOMIC_EXCHANGE_SEQ(ALbufferlistitem*, &source->queue, NULL); + BufferList = ATOMIC_EXCHANGE_PTR_SEQ(&source->queue, NULL); while(BufferList != NULL) { ALbufferlistitem *next = BufferList->next; @@ -3040,9 +3040,8 @@ static void UpdateSourceProps(ALsource *source, ALsizei num_sends) struct ALsourceProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, - &source->FreeList, &props, next, almemory_order_acq_rel, - almemory_order_acquire) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&source->FreeList, &props, next, + almemory_order_acq_rel, almemory_order_acquire) == 0); } /* Copy in current property values. */ @@ -3103,7 +3102,7 @@ static void UpdateSourceProps(ALsource *source, ALsizei num_sends) } /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, props, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&source->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the diff --git a/include/atomic.h b/include/atomic.h index 57609c33..a42cfa4a 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -34,10 +34,10 @@ extern "C" { #define ATOMIC_ADD(_val, _incr, _MO) atomic_fetch_add_explicit(_val, _incr, _MO) #define ATOMIC_SUB(_val, _decr, _MO) atomic_fetch_sub_explicit(_val, _decr, _MO) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) atomic_exchange_explicit(_val, _newval, _MO) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _orig, _newval, _MO1, _MO2) \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) atomic_exchange_explicit(_val, _newval, _MO) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _orig, _newval, _MO1, _MO2) \ atomic_compare_exchange_strong_explicit(_val, _orig, _newval, _MO1, _MO2) -#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _orig, _newval, _MO1, _MO2) \ +#define ATOMIC_COMPARE_EXCHANGE_WEAK(_val, _orig, _newval, _MO1, _MO2) \ atomic_compare_exchange_weak_explicit(_val, _orig, _newval, _MO1, _MO2) #define ATOMIC_FLAG_TEST_AND_SET(_val, _MO) atomic_flag_test_and_set_explicit(_val, _MO) @@ -77,14 +77,12 @@ enum almemory_order { #define ATOMIC_ADD(_val, _incr, _MO) __sync_fetch_and_add(&(_val)->value, (_incr)) #define ATOMIC_SUB(_val, _decr, _MO) __sync_fetch_and_sub(&(_val)->value, (_decr)) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) __extension__({ \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) __extension__({ \ __asm__ __volatile__("" ::: "memory"); \ __sync_lock_test_and_set(&(_val)->value, (_newval)); \ }) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, _MO1, _MO2) __extension__({ \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ - T _o = *(_oldval); \ +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, _MO1, _MO2) __extension__({ \ + __typeof(*(_oldval)) _o = *(_oldval); \ *(_oldval) = __sync_val_compare_and_swap(&(_val)->value, _o, (_newval)); \ *(_oldval) == _o; \ }) @@ -175,20 +173,29 @@ enum almemory_order { _r; \ }) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) __extension__({ \ - static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ - T _r; \ - if(sizeof(T) == 4) WRAP_XCHG("l", _r, &(_val)->value, (T)(_newval)); \ - else if(sizeof(T) == 8) WRAP_XCHG("q", _r, &(_val)->value, (T)(_newval)); \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) __extension__({ \ + __typeof((_val)->value) _r; \ + if(sizeof((_val)->value) == 4) WRAP_XCHG("l", _r, &(_val)->value, (_newval)); \ + else if(sizeof((_val)->value) == 8) WRAP_XCHG("q", _r, &(_val)->value, (_newval)); \ _r; \ }) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, _MO1, _MO2) __extension__({ \ - static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ - T _old = *(_oldval); \ - if(sizeof(T) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (T)(_newval)); \ - else if(sizeof(T) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (T)(_newval)); \ +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, _MO1, _MO2) __extension__({ \ + __typeof(*(_oldval)) _old = *(_oldval); \ + if(sizeof((_val)->value) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (_newval)); \ + else if(sizeof((_val)->value) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (_newval)); \ + *(_oldval) == _old; \ +}) + +#define ATOMIC_EXCHANGE_PTR(_val, _newval, _MO) __extension__({ \ + void *_r; \ + if(sizeof(void*) == 4) WRAP_XCHG("l", _r, &(_val)->value, (_newval)); \ + else if(sizeof(void*) == 8) WRAP_XCHG("q", _r, &(_val)->value, (_newval));\ + _r; \ +}) +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, _MO1, _MO2) __extension__({ \ + void *_old = *(_oldval); \ + if(sizeof(void*) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (_newval)); \ + else if(sizeof(void*) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (_newval)); \ *(_oldval) == _old; \ }) @@ -205,14 +212,13 @@ enum almemory_order { #define WIN32_LEAN_AND_MEAN #include <windows.h> -/* NOTE: This mess is *extremely* noisy, at least on GCC. It works by wrapping - * Windows' 32-bit and 64-bit atomic methods, which are then casted to use the - * given type based on its size (e.g. int and float use 32-bit atomics). This - * is fine for the swap and compare-and-swap methods, although the add and - * subtract methods only work properly for integer types. +/* NOTE: This mess is *extremely* touchy. It lacks quite a bit of safety + * checking due to the lack of multi-statement expressions, typeof(), and C99 + * compound literals. It is incapable of properly exchanging floats, which get + * casted to LONG/int, and could cast away potential warnings. * - * Despite how noisy it is, it's unfortunately the only way that doesn't rely - * on C99 (damn MSVC). + * Unfortunately, it's the only semi-safe way that doesn't rely on C99 (because + * MSVC). */ inline LONG AtomicAdd32(volatile LONG *dest, LONG incr) @@ -240,6 +246,10 @@ inline LONGLONG AtomicSwap64(volatile LONGLONG *dest, LONGLONG newval) { return InterlockedExchange64(dest, newval); } +inline void *AtomicSwapPtr(void *volatile *dest, void *newval) +{ + return InterlockedExchangePointer(dest, newval); +} inline bool CompareAndSwap32(volatile LONG *dest, LONG newval, LONG *oldval) { @@ -253,10 +263,16 @@ inline bool CompareAndSwap64(volatile LONGLONG *dest, LONGLONG newval, LONGLONG *oldval = InterlockedCompareExchange64(dest, newval, *oldval); return old == *oldval; } +inline bool CompareAndSwapPtr(void *volatile *dest, void *newval, void **oldval) +{ + void *old = *oldval; + *oldval = InterlockedCompareExchangePointer(dest, newval, *oldval); + return old == *oldval; +} #define WRAP_ADDSUB(T, _func, _ptr, _amnt) _func((T volatile*)(_ptr), (_amnt)) -#define WRAP_XCHG(T, _func, _ptr, _newval) ((T(*)(T volatile*,T))_func)((_ptr), (_newval)) -#define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) ((bool(*)(T volatile*,T,T*))_func)((_ptr), (_newval), (_oldval)) +#define WRAP_XCHG(T, _func, _ptr, _newval) _func((T volatile*)(_ptr), (_newval)) +#define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) _func((T volatile*)(_ptr), (_newval), (T*)(_oldval)) enum almemory_order { @@ -289,13 +305,20 @@ int _al_invalid_atomic_size(); /* not defined */ (sizeof((_val)->value)==8) ? WRAP_ADDSUB(LONGLONG, AtomicSub64, &(_val)->value, (_decr)) : \ _al_invalid_atomic_size()) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) \ - ((sizeof(T)==4) ? WRAP_XCHG(T, AtomicSwap32, &(_val)->value, (_newval)) : \ - (sizeof(T)==8) ? WRAP_XCHG(T, AtomicSwap64, &(_val)->value, (_newval)) : \ - (T)_al_invalid_atomic_size()) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, _MO1, _MO2) \ - ((sizeof(T)==4) ? WRAP_CMPXCHG(T, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \ - (sizeof(T)==8) ? WRAP_CMPXCHG(T, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) \ + ((sizeof((_val)->value)==4) ? WRAP_XCHG(LONG, AtomicSwap32, &(_val)->value, (_newval)) : \ + (sizeof((_val)->value)==8) ? WRAP_XCHG(LONGLONG, AtomicSwap64, &(_val)->value, (_newval)) : \ + (LONG)_al_invalid_atomic_size()) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, _MO1, _MO2) \ + ((sizeof((_val)->value)==4) ? WRAP_CMPXCHG(LONG, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \ + (sizeof((_val)->value)==8) ? WRAP_CMPXCHG(LONGLONG, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \ + (bool)_al_invalid_atomic_size()) + +#define ATOMIC_EXCHANGE_PTR(_val, _newval, _MO) \ + ((sizeof((_val)->value)==sizeof(void*)) ? AtomicSwapPtr((void*volatile*)&(_val)->value, (_newval)) : \ + (void*)_al_invalid_atomic_size()) +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, _MO1, _MO2)\ + ((sizeof((_val)->value)==sizeof(void*)) ? CompareAndSwapPtr((void*volatile*)&(_val)->value, (_newval), (void**)(_oldval)) : \ (bool)_al_invalid_atomic_size()) #define ATOMIC_THREAD_FENCE(order) do { \ @@ -320,21 +343,27 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC_ADD(...) (0) #define ATOMIC_SUB(...) (0) -#define ATOMIC_EXCHANGE(T, ...) (0) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, ...) (0) -#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, ...) (0) - -#define ATOMIC_FLAG_TEST_AND_SET(...) (0) -#define ATOMIC_FLAG_CLEAR(...) ((void)0) +#define ATOMIC_EXCHANGE(...) (0) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(...) (0) #define ATOMIC_THREAD_FENCE(...) ((void)0) #endif +/* If no PTR xchg variants are provided, the normal ones can handle it. */ +#ifndef ATOMIC_EXCHANGE_PTR +#define ATOMIC_EXCHANGE_PTR ATOMIC_EXCHANGE +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG ATOMIC_COMPARE_EXCHANGE_STRONG +#define ATOMIC_COMPARE_EXCHANGE_PTR_WEAK ATOMIC_COMPARE_EXCHANGE_WEAK +#endif + /* If no weak cmpxchg is provided (not all systems will have one), substitute a * strong cmpxchg. */ #ifndef ATOMIC_COMPARE_EXCHANGE_WEAK #define ATOMIC_COMPARE_EXCHANGE_WEAK ATOMIC_COMPARE_EXCHANGE_STRONG #endif +#ifndef ATOMIC_COMPARE_EXCHANGE_PTR_WEAK +#define ATOMIC_COMPARE_EXCHANGE_PTR_WEAK ATOMIC_COMPARE_EXCHANGE_PTR_STRONG +#endif /* If no ATOMIC_FLAG is defined, simulate one with an atomic int using exchange * and store ops. @@ -342,7 +371,7 @@ int _al_invalid_atomic_size(); /* not defined */ #ifndef ATOMIC_FLAG #define ATOMIC_FLAG ATOMIC(int) #define ATOMIC_FLAG_INIT ATOMIC_INIT_STATIC(0) -#define ATOMIC_FLAG_TEST_AND_SET(_val, _MO) ATOMIC_EXCHANGE(int, _val, 1, _MO) +#define ATOMIC_FLAG_TEST_AND_SET(_val, _MO) ATOMIC_EXCHANGE(_val, 1, _MO) #define ATOMIC_FLAG_CLEAR(_val, _MO) ATOMIC_STORE(_val, 0, _MO) #endif @@ -353,11 +382,17 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC_ADD_SEQ(_val, _incr) ATOMIC_ADD(_val, _incr, almemory_order_seq_cst) #define ATOMIC_SUB_SEQ(_val, _decr) ATOMIC_SUB(_val, _decr, almemory_order_seq_cst) -#define ATOMIC_EXCHANGE_SEQ(T, _val, _newval) ATOMIC_EXCHANGE(T, _val, _newval, almemory_order_seq_cst) -#define ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(T, _val, _oldval, _newval) \ - ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) -#define ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(T, _val, _oldval, _newval) \ - ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) +#define ATOMIC_EXCHANGE_SEQ(_val, _newval) ATOMIC_EXCHANGE(_val, _newval, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_WEAK(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) + +#define ATOMIC_EXCHANGE_PTR_SEQ(_val, _newval) ATOMIC_EXCHANGE_PTR(_val, _newval, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) typedef unsigned int uint; @@ -381,7 +416,7 @@ inline uint DecrementRef(RefCount *ptr) T _first = ATOMIC_LOAD(_head, almemory_order_acquire); \ do { \ ATOMIC_STORE(&(_entry)->next, _first, almemory_order_relaxed); \ - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(T, _head, &_first, _entry, \ + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(_head, &_first, _entry, \ almemory_order_acq_rel, almemory_order_acquire) == 0); \ } while(0) |