aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-02-13 21:18:18 -0800
committerChris Robinson <[email protected]>2017-02-13 21:18:18 -0800
commit0d19a209014582f1e77ab3b927dfb1af6c307d66 (patch)
tree38d5b06d2003a23175522411bfeeffb8fc252f7a
parent0324712540f88d18f1fa8f18f7a72da06af00d75 (diff)
Make the source state atomic
Since it's modified by the mixer when playback is ended, a plain struct member isn't safe.
-rw-r--r--Alc/ALc.c3
-rw-r--r--Alc/ALu.c10
-rw-r--r--Alc/mixer.c2
-rw-r--r--OpenAL32/Include/alSource.h9
-rw-r--r--OpenAL32/alSource.c46
5 files changed, 36 insertions, 34 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index fcc6d649..69e37540 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1697,8 +1697,7 @@ void ALCcontext_ProcessUpdates(ALCcontext *context)
ALsource *Source = context->SourceMap.values[pos];
ALenum new_state;
- if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
- Source->OffsetType != AL_NONE)
+ if(Source->OffsetType != AL_NONE && IsPlayingOrPaused(Source))
{
WriteLock(&Source->queue_lock);
ApplyOffset(Source);
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 42f229a2..31dd6271 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -1326,7 +1326,7 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
for(;voice != voice_end;++voice)
{
if(!(source=voice->Source)) continue;
- if(source->state != AL_PLAYING && source->state != AL_PAUSED)
+ if(!IsPlayingOrPaused(source))
voice->Source = NULL;
else
CalcSourceParams(voice, ctx, force);
@@ -1449,7 +1449,8 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
{
ALboolean IsVoiceInit = (voice->Step > 0);
source = voice->Source;
- if(source && source->state == AL_PLAYING && IsVoiceInit)
+ if(IsVoiceInit && source &&
+ ATOMIC_LOAD(&source->state, almemory_order_relaxed) == AL_PLAYING)
MixSource(voice, source, device, SamplesToDo);
}
@@ -1614,12 +1615,13 @@ void aluHandleDisconnect(ALCdevice *device)
voice_end = voice + Context->VoiceCount;
while(voice != voice_end)
{
+ ALenum playing = AL_PLAYING;
ALsource *source = voice->Source;
voice->Source = NULL;
- if(source && source->state == AL_PLAYING)
+ if(source &&
+ ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &source->state, &playing, AL_STOPPED))
{
- source->state = AL_STOPPED;
ATOMIC_STORE(&source->current_buffer, NULL, almemory_order_relaxed);
ATOMIC_STORE(&source->position, 0, almemory_order_relaxed);
ATOMIC_STORE(&source->position_fraction, 0, almemory_order_release);
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 592d51d4..179c028e 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -711,7 +711,7 @@ void MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei Samp
voice->Moving = AL_TRUE;
/* Update source info */
- Source->state = State;
+ ATOMIC_STORE(&Source->state, State, almemory_order_relaxed);
ATOMIC_STORE(&Source->current_buffer, BufferListItem, almemory_order_relaxed);
ATOMIC_STORE(&Source->position, DataPosInt, almemory_order_relaxed);
ATOMIC_STORE(&Source->position_fraction, DataPosFrac, almemory_order_release);
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
index 3111a48a..b9479905 100644
--- a/OpenAL32/Include/alSource.h
+++ b/OpenAL32/Include/alSource.h
@@ -175,7 +175,7 @@ typedef struct ALsource {
ALint SourceType;
/** Source state (initial, playing, paused, or stopped) */
- ALenum state;
+ ATOMIC(ALenum) state;
ALenum new_state;
/** Source Buffer Queue info. */
@@ -224,6 +224,13 @@ void UpdateAllSourceProps(ALCcontext *context);
ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state);
ALboolean ApplyOffset(ALsource *Source);
+inline ALboolean IsPlayingOrPaused(ALsource *source)
+{
+ ALenum state = ATOMIC_LOAD_SEQ(&source->state);
+ return state == AL_PLAYING || state == AL_PAUSED;
+}
+
+
ALvoid ReleaseALSources(ALCcontext *Context);
#ifdef __cplusplus
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index c60cd790..edcb49cd 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -46,6 +46,7 @@ extern inline void LockSourcesWrite(ALCcontext *context);
extern inline void UnlockSourcesWrite(ALCcontext *context);
extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id);
extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id);
+extern inline ALboolean IsPlayingOrPaused(ALsource *source);
static void InitSourceParams(ALsource *Source);
static void DeinitSource(ALsource *source);
@@ -524,7 +525,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp p
Source->OffsetType = prop;
Source->Offset = *values;
- if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
+ if(IsPlayingOrPaused(Source) &&
!ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire))
{
ALCdevice_Lock(Context->Device);
@@ -671,7 +672,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
}
WriteLock(&Source->queue_lock);
- if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
+ if(IsPlayingOrPaused(Source))
{
WriteUnlock(&Source->queue_lock);
UnlockBuffersRead(device);
@@ -725,7 +726,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
Source->OffsetType = prop;
Source->Offset = *values;
- if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
+ if(IsPlayingOrPaused(Source) &&
!ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire))
{
ALCdevice_Lock(Context->Device);
@@ -843,8 +844,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
}
UnlockFiltersRead(device);
- if(slot != Source->Send[values[1]].Slot &&
- (Source->state == AL_PLAYING || Source->state == AL_PAUSED))
+ if(slot != Source->Send[values[1]].Slot && IsPlayingOrPaused(Source))
{
/* Add refcount on the new slot, and release the previous slot */
if(slot) IncrementRef(&slot->ref);
@@ -1227,7 +1227,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
return AL_TRUE;
case AL_SOURCE_STATE:
- *values = Source->state;
+ *values = ATOMIC_LOAD_SEQ(&Source->state);
return AL_TRUE;
case AL_BYTE_LENGTH_SOFT:
@@ -2767,7 +2767,7 @@ static void InitSourceParams(ALsource *Source)
Source->Offset = 0.0;
Source->OffsetType = AL_NONE;
Source->SourceType = AL_UNDETERMINED;
- Source->state = AL_INITIAL;
+ ATOMIC_INIT(&Source->state, AL_INITIAL);
Source->new_state = AL_NONE;
ATOMIC_INIT(&Source->queue, NULL);
@@ -2926,9 +2926,7 @@ void UpdateAllSourceProps(ALCcontext *context)
{
ALvoice *voice = &context->Voices[pos];
ALsource *source = voice->Source;
- if(source != NULL && (source->state == AL_PLAYING ||
- source->state == AL_PAUSED) &&
- source->NeedsUpdate)
+ if(source != NULL && source->NeedsUpdate && IsPlayingOrPaused(source))
{
source->NeedsUpdate = AL_FALSE;
UpdateSourceProps(source, num_sends);
@@ -2963,19 +2961,15 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
BufferList = BufferList->next;
}
- if(Source->state != AL_PAUSED)
+ if(ATOMIC_EXCHANGE(ALenum, &Source->state, AL_PLAYING, almemory_order_acq_rel) == AL_PAUSED)
+ discontinuity = AL_FALSE;
+ else
{
- Source->state = AL_PLAYING;
ATOMIC_STORE(&Source->current_buffer, BufferList, almemory_order_relaxed);
ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed);
ATOMIC_STORE(&Source->position_fraction, 0, almemory_order_release);
discontinuity = AL_TRUE;
}
- else
- {
- Source->state = AL_PLAYING;
- discontinuity = AL_FALSE;
- }
// Check if an Offset has been set
if(Source->OffsetType != AL_NONE)
@@ -3041,15 +3035,15 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
}
else if(state == AL_PAUSED)
{
- if(Source->state == AL_PLAYING)
- Source->state = AL_PAUSED;
+ ALenum playing = AL_PLAYING;
+ ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &Source->state, &playing, AL_PAUSED);
}
else if(state == AL_STOPPED)
{
do_stop:
- if(Source->state != AL_INITIAL)
+ if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL)
{
- Source->state = AL_STOPPED;
+ ATOMIC_STORE(&Source->state, AL_STOPPED, almemory_order_relaxed);
ATOMIC_STORE_SEQ(&Source->current_buffer, NULL);
}
Source->OffsetType = AL_NONE;
@@ -3057,9 +3051,9 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
}
else if(state == AL_INITIAL)
{
- if(Source->state != AL_INITIAL)
+ if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL)
{
- Source->state = AL_INITIAL;
+ ATOMIC_STORE(&Source->state, AL_INITIAL, almemory_order_relaxed);
ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD_SEQ(&Source->queue),
almemory_order_relaxed);
ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed);
@@ -3085,7 +3079,7 @@ static ALint64 GetSourceSampleOffset(ALsource *Source, ALCdevice *device, ALuint
ALuint refcount;
ReadLock(&Source->queue_lock);
- if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
+ if(!IsPlayingOrPaused(Source))
{
ReadUnlock(&Source->queue_lock);
do {
@@ -3135,7 +3129,7 @@ static ALdouble GetSourceSecOffset(ALsource *Source, ALCdevice *device, ALuint64
ALuint refcount;
ReadLock(&Source->queue_lock);
- if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
+ if(!IsPlayingOrPaused(Source))
{
ReadUnlock(&Source->queue_lock);
do {
@@ -3200,7 +3194,7 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCdevice *device
ALuint refcount;
ReadLock(&Source->queue_lock);
- if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
+ if(!IsPlayingOrPaused(Source))
{
ReadUnlock(&Source->queue_lock);
return 0.0;