diff options
author | Chris Robinson <[email protected]> | 2014-07-31 07:20:36 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-07-31 07:20:36 -0700 |
commit | 15a58eb38375247b6c57a7ceab5aa74895d638cd (patch) | |
tree | 5f546bab5504768356c27903a02b271c619b7d09 | |
parent | cdfc5a4d31d17e156736bb8bdcaf93ea505237ac (diff) |
Make the source's buffer queue head and current queue item atomic
-rw-r--r-- | Alc/ALu.c | 6 | ||||
-rw-r--r-- | Alc/mixer.c | 27 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 10 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 122 |
4 files changed, 89 insertions, 76 deletions
@@ -260,7 +260,7 @@ ALvoid CalcNonAttnSourceParams(ALactivesource *src, const ALCcontext *ALContext) /* Calculate the stepping value */ Channels = FmtMono; - BufferListItem = ALSource->queue; + BufferListItem = ATOMIC_LOAD(&ALSource->queue); while(BufferListItem != NULL) { ALbuffer *ALBuffer; @@ -872,7 +872,7 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f); } - BufferListItem = ALSource->queue; + BufferListItem = ATOMIC_LOAD(&ALSource->queue); while(BufferListItem != NULL) { ALbuffer *ALBuffer; @@ -1308,7 +1308,7 @@ ALvoid aluHandleDisconnect(ALCdevice *device) if(source->state == AL_PLAYING) { source->state = AL_STOPPED; - source->current_buffer = NULL; + ATOMIC_STORE(&source->current_buffer, NULL); source->position = 0; source->position_fraction = 0; } diff --git a/Alc/mixer.c b/Alc/mixer.c index 7141a8ae..f3b8f599 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -198,7 +198,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo) /* Get source info */ State = Source->state; - BufferListItem = Source->current_buffer; + BufferListItem = ATOMIC_LOAD(&Source->current_buffer); DataPosInt = Source->position; DataPosFrac = Source->position_fraction; Looping = Source->Looping; @@ -397,7 +397,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo) } tmpiter = tmpiter->next; if(!tmpiter && Looping) - tmpiter = Source->queue; + tmpiter = ATOMIC_LOAD(&Source->queue); else if(!tmpiter) { SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); @@ -484,17 +484,18 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo) if(DataSize > DataPosInt) break; - if(BufferListItem->next) - BufferListItem = BufferListItem->next; - else if(Looping) - BufferListItem = Source->queue; - else + if(!(BufferListItem=BufferListItem->next)) { - State = AL_STOPPED; - BufferListItem = NULL; - DataPosInt = 0; - DataPosFrac = 0; - break; + if(Looping) + BufferListItem = ATOMIC_LOAD(&Source->queue); + else + { + State = AL_STOPPED; + BufferListItem = NULL; + DataPosInt = 0; + DataPosFrac = 0; + break; + } } DataPosInt -= DataSize; @@ -503,7 +504,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo) /* Update source info */ Source->state = State; - Source->current_buffer = BufferListItem; + ATOMIC_STORE(&Source->current_buffer, BufferListItem); Source->position = DataPosInt; Source->position_fraction = DataPosFrac; } diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 4b2ffe0b..8d74fc54 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -18,9 +18,9 @@ extern const ALsizei ResamplerPrePadding[ResamplerMax]; typedef struct ALbufferlistitem { - struct ALbuffer *buffer; - struct ALbufferlistitem *next; - struct ALbufferlistitem *prev; + struct ALbuffer *buffer; + struct ALbufferlistitem *volatile next; + struct ALbufferlistitem *volatile prev; } ALbufferlistitem; @@ -98,8 +98,8 @@ typedef struct ALsource { ALuint position_fraction; /** Source Buffer Queue info. */ - ALbufferlistitem *volatile queue; - ALbufferlistitem *volatile current_buffer; + ATOMIC(ALbufferlistitem*) queue; + ATOMIC(ALbufferlistitem*) current_buffer; RWLock queue_lock; /** Current buffer sample info. */ diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 9a4088a2..2cfec346 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -566,6 +566,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p ALfilter *filter = NULL; ALeffectslot *slot = NULL; ALbufferlistitem *oldlist; + ALbufferlistitem *newlist; ALfloat fvals[3]; switch(prop) @@ -595,18 +596,15 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p if(buffer != NULL) { - ALbufferlistitem *BufferListItem; - /* Add the selected buffer to a one-item queue */ - BufferListItem = malloc(sizeof(ALbufferlistitem)); - BufferListItem->buffer = buffer; - BufferListItem->next = NULL; - BufferListItem->prev = NULL; + newlist = malloc(sizeof(ALbufferlistitem)); + newlist->buffer = buffer; + newlist->next = NULL; + newlist->prev = NULL; IncrementRef(&buffer->ref); /* Source is now Static */ Source->SourceType = AL_STATIC; - oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem); ReadLock(&buffer->lock); Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); @@ -617,9 +615,10 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p { /* Source is now Undetermined */ Source->SourceType = AL_UNDETERMINED; - oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL); + newlist = NULL; } - Source->current_buffer = Source->queue; + oldlist = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, newlist); + ATOMIC_STORE(&Source->current_buffer, newlist); WriteUnlock(&Source->queue_lock); /* Delete all elements in the previous queue */ @@ -962,7 +961,7 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp case sfSecLength: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1065,8 +1064,8 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case AL_BUFFER: ReadLock(&Source->queue_lock); - BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : - Source->current_buffer; + BufferList = (Source->SourceType == AL_STATIC) ? ATOMIC_LOAD(&Source->queue) : + ATOMIC_LOAD(&Source->current_buffer); *values = (BufferList && BufferList->buffer) ? BufferList->buffer->id : 0; ReadUnlock(&Source->queue_lock); return AL_TRUE; @@ -1077,7 +1076,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case siByteLength: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1116,7 +1115,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case siSampleLength: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1132,7 +1131,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case AL_BUFFERS_QUEUED: ReadLock(&Source->queue_lock); - if(!(BufferList=Source->queue)) + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) *values = 0; else { @@ -1155,9 +1154,10 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p } else { - const ALbufferlistitem *BufferList = Source->queue; + const ALbufferlistitem *BufferList = ATOMIC_LOAD(&Source->queue); + const ALbufferlistitem *Current = ATOMIC_LOAD(&Source->current_buffer); ALsizei played = 0; - while(BufferList && BufferList != Source->current_buffer) + while(BufferList && BufferList != Current) { played++; BufferList = BufferList->next; @@ -1412,14 +1412,14 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) } UnlockContext(context); - while(Source->queue != NULL) + BufferList = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, NULL); + while(BufferList != NULL) { - BufferList = Source->queue; - Source->queue = BufferList->next; - + ALbufferlistitem *next = BufferList->next; if(BufferList->buffer != NULL) DecrementRef(&BufferList->buffer->ref); free(BufferList); + BufferList = next; } for(j = 0;j < MAX_SENDS;++j) @@ -2188,7 +2188,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu } /* Check for a valid Buffer, for its frequency and format */ - BufferList = source->queue; + BufferList = ATOMIC_LOAD(&source->queue); while(BufferList) { if(BufferList->buffer) @@ -2276,7 +2276,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu /* Source is now streaming */ source->SourceType = AL_STREAMING; - if((BufferList=CompExchangePtr((XchgPtr*)&source->queue, NULL, BufferListStart)) != NULL) + BufferList = NULL; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->queue, &BufferList, BufferListStart)) { /* Queue head is not NULL, append to the end of the queue */ while(BufferList->next != NULL) @@ -2285,7 +2286,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferListStart->prev = BufferList; BufferList->next = BufferListStart; } - CompExchangePtr((XchgPtr*)&source->current_buffer, NULL, BufferListStart); + BufferList = NULL; + ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->current_buffer, &BufferList, BufferListStart); WriteUnlock(&source->queue_lock); done: @@ -2296,8 +2298,9 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint { ALCcontext *context; ALsource *source; - ALbufferlistitem *BufferList; + ALbufferlistitem *NewHead; ALbufferlistitem *OldHead; + ALbufferlistitem *Current; ALsizei i; if(nb == 0) @@ -2314,12 +2317,13 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint WriteLock(&source->queue_lock); /* Find the new buffer queue head */ - BufferList = source->queue; - for(i = 0;i < nb && BufferList;i++) + NewHead = ATOMIC_LOAD(&source->queue); + Current = ATOMIC_LOAD(&source->current_buffer); + for(i = 0;i < nb && NewHead;i++) { - if(BufferList == source->current_buffer) + if(NewHead == Current) break; - BufferList = BufferList->next; + NewHead = NewHead->next; } if(source->Looping || source->SourceType != AL_STREAMING || i != nb) { @@ -2329,23 +2333,24 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint } /* Swap it, and cut the new head from the old. */ - OldHead = ExchangePtr((XchgPtr*)&source->queue, BufferList); - if(BufferList) + OldHead = ATOMIC_EXCHANGE(ALbufferlistitem*, &source->queue, NewHead); + if(NewHead) { ALCdevice *device = context->Device; + ALbufferlistitem *OldTail = NewHead->prev; uint count; /* Cut the new head's link back to the old body. The mixer is robust * enough to handle the link back going away. Once the active mix (if * any) is complete, it's safe to finish cutting the old tail from the * new head. */ - BufferList = ExchangePtr((XchgPtr*)&BufferList->prev, NULL); + NewHead->prev = NULL; if(((count=ReadRef(&device->MixCount))&1) != 0) { while(count == ReadRef(&device->MixCount)) althrd_yield(); } - BufferList->next = NULL; + OldTail->next = NULL; } WriteUnlock(&source->queue_lock); @@ -2418,8 +2423,8 @@ static ALvoid InitSourceParams(ALsource *Source) Source->SourceType = AL_UNDETERMINED; Source->Offset = -1.0; - Source->queue = NULL; - Source->current_buffer = NULL; + ATOMIC_STORE_UNSAFE(&Source->queue, NULL); + ATOMIC_STORE_UNSAFE(&Source->current_buffer, NULL); Source->Direct.Gain = 1.0f; Source->Direct.GainHF = 1.0f; @@ -2455,7 +2460,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) /* Check that there is a queue containing at least one valid, non zero * length Buffer. */ - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList) { ALbuffer *buffer; @@ -2469,7 +2474,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) Source->state = AL_PLAYING; Source->position = 0; Source->position_fraction = 0; - Source->current_buffer = BufferList; + ATOMIC_STORE(&Source->current_buffer, BufferList); } else Source->state = AL_PLAYING; @@ -2545,7 +2550,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) if(Source->state != AL_INITIAL) { Source->state = AL_STOPPED; - Source->current_buffer = NULL; + ATOMIC_STORE(&Source->current_buffer, NULL); } Source->Offset = -1.0; } @@ -2556,7 +2561,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) Source->state = AL_INITIAL; Source->position = 0; Source->position_fraction = 0; - Source->current_buffer = Source->queue; + ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD(&Source->queue)); } Source->Offset = -1.0; } @@ -2572,6 +2577,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) static ALint64 GetSourceOffset(const ALsource *Source) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; ALuint64 readPos; if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) @@ -2581,8 +2587,9 @@ static ALint64 GetSourceOffset(const ALsource *Source) * any played buffers */ readPos = (ALuint64)Source->position << 32; readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS); - BufferList = Source->queue; - while(BufferList && BufferList != Source->current_buffer) + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList && BufferList != Current) { if(BufferList->buffer) readPos += (ALuint64)BufferList->buffer->SampleLen << 32; @@ -2600,6 +2607,7 @@ static ALint64 GetSourceOffset(const ALsource *Source) static ALdouble GetSourceSecOffset(const ALsource *Source) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; const ALbuffer *Buffer = NULL; ALuint64 readPos; @@ -2610,8 +2618,9 @@ static ALdouble GetSourceSecOffset(const ALsource *Source) * any played buffers */ readPos = (ALuint64)Source->position << FRACTIONBITS; readPos |= (ALuint64)Source->position_fraction; - BufferList = Source->queue; - while(BufferList && BufferList != Source->current_buffer) + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList && BufferList != Current) { const ALbuffer *buffer = BufferList->buffer; if(buffer != NULL) @@ -2641,6 +2650,7 @@ static ALdouble GetSourceSecOffset(const ALsource *Source) static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; const ALbuffer *Buffer = NULL; ALboolean readFin = AL_FALSE; ALuint readPos, writePos; @@ -2660,11 +2670,12 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of * any played buffers */ totalBufferLen = 0; readPos = Source->position; - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); while(BufferList != NULL) { const ALbuffer *buffer; - readFin = readFin || (BufferList == Source->current_buffer); + readFin = readFin || (BufferList == Current); if((buffer=BufferList->buffer) != NULL) { if(!Buffer) Buffer = buffer; @@ -2772,7 +2783,7 @@ ALboolean ApplyOffset(ALsource *Source) return AL_FALSE; totalBufferLen = 0; - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList && totalBufferLen <= offset) { Buffer = BufferList->buffer; @@ -2781,7 +2792,7 @@ ALboolean ApplyOffset(ALsource *Source) if(bufferLen > offset-totalBufferLen) { /* Offset is in this buffer */ - Source->current_buffer = BufferList; + ATOMIC_STORE(&Source->current_buffer, BufferList); Source->position = offset - totalBufferLen; Source->position_fraction = 0; @@ -2811,7 +2822,7 @@ static ALint GetSampleOffset(ALsource *Source) ALint Offset = -1; /* Find the first valid Buffer in the Queue */ - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList) { if(BufferList->buffer) @@ -2869,6 +2880,7 @@ static ALint GetSampleOffset(ALsource *Source) */ ALvoid ReleaseALSources(ALCcontext *Context) { + ALbufferlistitem *item; ALsizei pos; ALuint j; for(pos = 0;pos < Context->SourceMap.size;pos++) @@ -2876,14 +2888,14 @@ ALvoid ReleaseALSources(ALCcontext *Context) ALsource *temp = Context->SourceMap.array[pos].value; Context->SourceMap.array[pos].value = NULL; - while(temp->queue != NULL) + item = ATOMIC_EXCHANGE(ALbufferlistitem*, &temp->queue, NULL); + while(item != NULL) { - ALbufferlistitem *BufferList = temp->queue; - temp->queue = BufferList->next; - - if(BufferList->buffer != NULL) - DecrementRef(&BufferList->buffer->ref); - free(BufferList); + ALbufferlistitem *next = item->next; + if(item->buffer != NULL) + DecrementRef(&item->buffer->ref); + free(item); + item = next; } for(j = 0;j < MAX_SENDS;++j) |