Fix rare stream deadlock on Windows
This commit is contained in:
parent
179b11151e
commit
49fd99119d
@ -14,9 +14,9 @@ struct CdReadInfo
|
||||
void *pBuffer;
|
||||
char field_C;
|
||||
bool bLocked;
|
||||
bool bInUse;
|
||||
bool bReading;
|
||||
int32 nStatus;
|
||||
HANDLE hSemaphore; // used for CdStreamSync
|
||||
HANDLE pDoneSemaphore; // used for CdStreamSync
|
||||
HANDLE hFile;
|
||||
OVERLAPPED Overlapped;
|
||||
};
|
||||
@ -53,9 +53,9 @@ CdStreamInitThread(void)
|
||||
{
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
{
|
||||
gpReadInfo[i].hSemaphore = CreateSemaphore(nil, 0, 2, nil);
|
||||
gpReadInfo[i].pDoneSemaphore = CreateSemaphore(nil, 0, 2, nil);
|
||||
|
||||
if ( gpReadInfo[i].hSemaphore == nil )
|
||||
if ( gpReadInfo[i].pDoneSemaphore == nil )
|
||||
{
|
||||
printf("%s: failed to create sync semaphore\n", "cdvd_stream");
|
||||
ASSERT(0);
|
||||
@ -183,7 +183,7 @@ CdStreamShutdown(void)
|
||||
CloseHandle(_gCdStreamThread);
|
||||
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
CloseHandle(gpReadInfo[i].hSemaphore);
|
||||
CloseHandle(gpReadInfo[i].pDoneSemaphore);
|
||||
}
|
||||
|
||||
LocalFree(gpReadInfo);
|
||||
@ -213,7 +213,7 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->nSectorsToRead != 0 || pChannel->bInUse )
|
||||
if ( pChannel->nSectorsToRead != 0 || pChannel->bReading )
|
||||
return STREAM_NONE;
|
||||
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
@ -271,7 +271,7 @@ CdStreamGetStatus(int32 channel)
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->bInUse )
|
||||
if ( pChannel->bReading )
|
||||
return STREAM_READING;
|
||||
|
||||
if ( pChannel->nSectorsToRead != 0 )
|
||||
@ -321,12 +321,21 @@ CdStreamSync(int32 channel)
|
||||
{
|
||||
pChannel->bLocked = true;
|
||||
|
||||
ASSERT( pChannel->hSemaphore != nil );
|
||||
ASSERT( pChannel->pDoneSemaphore != nil );
|
||||
|
||||
WaitForSingleObject(pChannel->hSemaphore, INFINITE);
|
||||
// Deadlock fix 1
|
||||
#ifdef FIX_BUGS
|
||||
// This is while loop on Posix streamer, for spurious wakeups
|
||||
if (pChannel->bLocked && pChannel->nSectorsToRead != 0){
|
||||
WaitForSingleObject(pChannel->pDoneSemaphore, INFINITE);
|
||||
}
|
||||
pChannel->bLocked = false;
|
||||
#else
|
||||
WaitForSingleObject(pChannel->pDoneSemaphore, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
pChannel->bInUse = false;
|
||||
pChannel->bReading = false;
|
||||
|
||||
return pChannel->nStatus;
|
||||
}
|
||||
@ -398,7 +407,7 @@ WINAPI CdStreamThread(LPVOID lpThreadParameter)
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != nil );
|
||||
|
||||
pChannel->bInUse = true;
|
||||
pChannel->bReading = true;
|
||||
|
||||
if ( pChannel->nStatus == STREAM_NONE )
|
||||
{
|
||||
@ -455,11 +464,15 @@ WINAPI CdStreamThread(LPVOID lpThreadParameter)
|
||||
|
||||
if ( pChannel->bLocked )
|
||||
{
|
||||
ASSERT( pChannel->hSemaphore != nil );
|
||||
ReleaseSemaphore(pChannel->hSemaphore, 1, NULL);
|
||||
ASSERT( pChannel->pDoneSemaphore != nil );
|
||||
// Deadlock fix 2
|
||||
#ifdef FIX_BUGS
|
||||
pChannel->bLocked = 0;
|
||||
#endif
|
||||
ReleaseSemaphore(pChannel->pDoneSemaphore, 1, NULL);
|
||||
}
|
||||
|
||||
pChannel->bInUse = false;
|
||||
pChannel->bReading = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user