Use a RWLock to protect access to a buffer instead of the device lock
This commit is contained in:
parent
4db24af59a
commit
1fdc25df75
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user