aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-09-11 03:57:40 -0700
committerChris Robinson <[email protected]>2011-09-11 03:57:40 -0700
commit1fdc25df7551c2186704f47fd5eb19485f88edb4 (patch)
treef429b30cd49cad9f135fcaa6d347342e5bb10627
parent4db24af59a87675eae1f3542f81fb3d3de6cb9ac (diff)
Use a RWLock to protect access to a buffer instead of the device lock
-rw-r--r--OpenAL32/Include/alBuffer.h2
-rw-r--r--OpenAL32/alBuffer.c66
-rw-r--r--OpenAL32/alSource.c86
3 files changed, 83 insertions, 71 deletions
diff --git a/OpenAL32/Include/alBuffer.h b/OpenAL32/Include/alBuffer.h
index 8e18732a..6ab25615 100644
--- a/OpenAL32/Include/alBuffer.h
+++ b/OpenAL32/Include/alBuffer.h
@@ -87,6 +87,8 @@ typedef struct ALbuffer
RefCount ref; // Number of sources using this buffer (deletion can only occur when this is 0)
+ RWLock lock;
+
// Index to itself
ALuint buffer;
} ALbuffer;
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
index 040e723d..6347e9d8 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.c
@@ -131,9 +131,6 @@ static const char muLawCompressTable[256] =
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
-/* TODO: These functions shouldn't need to take the device lock, but will need
- * a RWLock to protect from concurrent writes.
- */
/*
* alGenBuffers(ALsizei n, ALuint *buffers)
@@ -167,6 +164,7 @@ AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
alDeleteBuffers(i, buffers);
break;
}
+ RWLockInit(&buffer->lock);
err = NewThunkEntry(&buffer->buffer);
if(err == AL_NO_ERROR)
@@ -309,12 +307,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
if((size%FrameSize) != 0)
err = AL_INVALID_VALUE;
else
- {
- LockDevice(device);
err = LoadData(ALBuf, freq, format, size/FrameSize,
SrcChannels, SrcType, data, AL_TRUE);
- UnlockDevice(device);
- }
if(err != AL_NO_ERROR)
alSetError(Context, err);
} break;
@@ -337,12 +331,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
if((size%FrameSize) != 0)
err = AL_INVALID_VALUE;
else
- {
- LockDevice(device);
err = LoadData(ALBuf, freq, NewFormat, size/FrameSize,
SrcChannels, SrcType, data, AL_TRUE);
- UnlockDevice(device);
- }
if(err != AL_NO_ERROR)
alSetError(Context, err);
} break;
@@ -370,12 +360,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
if((size%FrameSize) != 0)
err = AL_INVALID_VALUE;
else
- {
- LockDevice(device);
err = LoadData(ALBuf, freq, NewFormat, size/FrameSize,
SrcChannels, SrcType, data, AL_TRUE);
- UnlockDevice(device);
- }
if(err != AL_NO_ERROR)
alSetError(Context, err);
} break;
@@ -410,7 +396,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const
alSetError(Context, AL_INVALID_ENUM);
else
{
- LockDevice(device);
+ WriteLock(&ALBuf->lock);
if(SrcChannels != ALBuf->OriginalChannels || SrcType != ALBuf->OriginalType)
alSetError(Context, AL_INVALID_ENUM);
else if(offset > ALBuf->OriginalSize ||
@@ -441,7 +427,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const
ConvertData(&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType,
data, SrcType, Channels, length);
}
- UnlockDevice(device);
+ WriteUnlock(&ALBuf->lock);
}
ALCcontext_DecRef(Context);
@@ -476,12 +462,8 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
else err = AL_INVALID_VALUE;
}
if(err == AL_NO_ERROR)
- {
- LockDevice(device);
err = LoadData(ALBuf, samplerate, internalformat, frames,
channels, type, data, AL_FALSE);
- UnlockDevice(device);
- }
if(err != AL_NO_ERROR)
alSetError(Context, err);
}
@@ -512,7 +494,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
ALuint FrameSize;
ALuint FrameCount;
- LockDevice(device);
+ WriteLock(&ALBuf->lock);
FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
FrameCount = ALBuf->size / FrameSize;
if(channels != (ALenum)ALBuf->FmtChannels)
@@ -531,7 +513,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
data, type,
ChannelsFromFmt(ALBuf->FmtChannels), frames);
}
- UnlockDevice(device);
+ WriteUnlock(&ALBuf->lock);
}
ALCcontext_DecRef(Context);
@@ -560,7 +542,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
ALuint FrameSize;
ALuint FrameCount;
- LockDevice(device);
+ ReadLock(&ALBuf->lock);
FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
FrameCount = ALBuf->size / FrameSize;
if(channels != (ALenum)ALBuf->FmtChannels)
@@ -579,7 +561,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType,
ChannelsFromFmt(ALBuf->FmtChannels), frames);
}
- UnlockDevice(device);
+ ReadUnlock(&ALBuf->lock);
}
ALCcontext_DecRef(Context);
@@ -761,7 +743,7 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* pl
switch(eParam)
{
case AL_LOOP_POINTS_SOFT:
- LockDevice(device);
+ WriteLock(&ALBuf->lock);
if(ALBuf->ref != 0)
alSetError(pContext, AL_INVALID_OPERATION);
else if(plValues[0] < 0 || plValues[1] < 0 ||
@@ -779,7 +761,7 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* pl
ALBuf->LoopEnd = plValues[1];
}
}
- UnlockDevice(device);
+ WriteUnlock(&ALBuf->lock);
break;
default:
@@ -973,10 +955,10 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plVal
switch(eParam)
{
case AL_LOOP_POINTS_SOFT:
- LockDevice(device);
+ ReadLock(&ALBuf->lock);
plValues[0] = ALBuf->LoopStart;
plValues[1] = ALBuf->LoopEnd;
- UnlockDevice(device);
+ ReadUnlock(&ALBuf->lock);
break;
default:
@@ -1808,12 +1790,19 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
ALuint64 newsize;
ALvoid *temp;
+ WriteLock(&ALBuf->lock);
if(ALBuf->ref != 0)
+ {
+ WriteUnlock(&ALBuf->lock);
return AL_INVALID_OPERATION;
+ }
if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
(long)SrcChannels != (long)DstChannels)
+ {
+ WriteUnlock(&ALBuf->lock);
return AL_INVALID_ENUM;
+ }
NewChannels = ChannelsFromFmt(DstChannels);
NewBytes = BytesFromFmt(DstType);
@@ -1827,10 +1816,17 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
newsize *= NewBytes;
newsize *= NewChannels;
if(newsize > INT_MAX)
+ {
+ WriteUnlock(&ALBuf->lock);
return AL_OUT_OF_MEMORY;
+ }
temp = realloc(ALBuf->data, newsize);
- if(!temp && newsize) return AL_OUT_OF_MEMORY;
+ if(!temp && newsize)
+ {
+ WriteUnlock(&ALBuf->lock);
+ return AL_OUT_OF_MEMORY;
+ }
ALBuf->data = temp;
ALBuf->size = newsize;
@@ -1854,10 +1850,17 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
newsize *= NewBytes;
newsize *= NewChannels;
if(newsize > INT_MAX)
+ {
+ WriteUnlock(&ALBuf->lock);
return AL_OUT_OF_MEMORY;
+ }
temp = realloc(ALBuf->data, newsize);
- if(!temp && newsize) return AL_OUT_OF_MEMORY;
+ if(!temp && newsize)
+ {
+ WriteUnlock(&ALBuf->lock);
+ return AL_OUT_OF_MEMORY;
+ }
ALBuf->data = temp;
ALBuf->size = newsize;
@@ -1887,6 +1890,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
ALBuf->LoopStart = 0;
ALBuf->LoopEnd = newsize / NewChannels / NewBytes;
+ WriteUnlock(&ALBuf->lock);
return AL_NO_ERROR;
}
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index 879f4377..68c3e092 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -592,8 +592,10 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
oldlist = ExchangePtr((void**)&Source->queue, BufferListItem);
Source->BuffersInQueue = 1;
+ ReadLock(&buffer->lock);
Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
Source->SampleSize = BytesFromFmt(buffer->FmtType);
+ ReadUnlock(&buffer->lock);
if(buffer->FmtChannels == FmtMono)
Source->Update = CalcSourceParams;
else
@@ -1579,9 +1581,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
ALCcontext *Context;
ALCdevice *device;
ALsource *Source;
- ALbuffer *buffer;
ALsizei i;
- ALbufferlistitem *BufferListStart;
+ ALbufferlistitem *BufferListStart = NULL;
ALbufferlistitem *BufferList;
ALbuffer *BufferFmt;
@@ -1594,7 +1595,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
if(n < 0)
{
alSetError(Context, AL_INVALID_VALUE);
- goto done;
+ goto error;
}
// Check that all buffers are valid or zero and that the source is valid
@@ -1603,7 +1604,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
if((Source=LookupSource(Context->SourceMap, source)) == NULL)
{
alSetError(Context, AL_INVALID_NAME);
- goto done;
+ goto error;
}
// Check that this is not a STATIC Source
@@ -1611,7 +1612,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
{
// Invalid Source Type (can't queue on a Static Source)
alSetError(Context, AL_INVALID_OPERATION);
- goto done;
+ goto error;
}
device = Context->Device;
@@ -1632,15 +1633,34 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
for(i = 0;i < n;i++)
{
- if(!buffers[i])
- continue;
-
- if((buffer=LookupBuffer(device->BufferMap, buffers[i])) == NULL)
+ ALbuffer *buffer = NULL;
+ if(buffers[i] && (buffer=LookupBuffer(device->BufferMap, buffers[i])) == NULL)
{
alSetError(Context, AL_INVALID_NAME);
- goto done;
+ goto error;
+ }
+
+ if(!BufferListStart)
+ {
+ BufferListStart = malloc(sizeof(ALbufferlistitem));
+ BufferListStart->buffer = buffer;
+ BufferListStart->next = NULL;
+ BufferListStart->prev = NULL;
+ BufferList = BufferListStart;
+ }
+ else
+ {
+ BufferList->next = malloc(sizeof(ALbufferlistitem));
+ BufferList->next->buffer = buffer;
+ BufferList->next->next = NULL;
+ BufferList->next->prev = BufferList;
+ BufferList = BufferList->next;
}
+ if(!buffer) continue;
+ // Increment reference counter for buffer
+ IncrementRef(&buffer->ref);
+ ReadLock(&buffer->lock);
if(BufferFmt == NULL)
{
BufferFmt = buffer;
@@ -1658,42 +1678,16 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
BufferFmt->OriginalChannels != buffer->OriginalChannels ||
BufferFmt->OriginalType != buffer->OriginalType)
{
+ ReadUnlock(&buffer->lock);
alSetError(Context, AL_INVALID_OPERATION);
- goto done;
+ goto error;
}
+ ReadUnlock(&buffer->lock);
}
// Change Source Type
Source->lSourceType = AL_STREAMING;
- buffer = LookupBuffer(device->BufferMap, buffers[0]);
-
- // All buffers are valid - so add them to the list
- BufferListStart = malloc(sizeof(ALbufferlistitem));
- BufferListStart->buffer = buffer;
- BufferListStart->next = NULL;
- BufferListStart->prev = NULL;
-
- // Increment reference counter for buffer
- if(buffer) IncrementRef(&buffer->ref);
-
- BufferList = BufferListStart;
-
- for(i = 1;i < n;i++)
- {
- buffer = LookupBuffer(device->BufferMap, buffers[i]);
-
- BufferList->next = malloc(sizeof(ALbufferlistitem));
- BufferList->next->buffer = buffer;
- BufferList->next->next = NULL;
- BufferList->next->prev = BufferList;
-
- // Increment reference counter for buffer
- if(buffer) IncrementRef(&buffer->ref);
-
- BufferList = BufferList->next;
- }
-
if(Source->queue == NULL)
Source->queue = BufferListStart;
else
@@ -1710,7 +1704,19 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A
// Update number of buffers in queue
Source->BuffersInQueue += n;
-done:
+ UnlockContext(Context);
+ return;
+
+error:
+ while(BufferListStart)
+ {
+ BufferList = BufferListStart;
+ BufferListStart = BufferList->next;
+
+ if(BufferList->buffer)
+ DecrementRef(&BufferList->buffer->ref);
+ free(BufferList);
+ }
UnlockContext(Context);
}