diff options
author | Sergeanur <s.anureev@yandex.ua> | 2021-02-16 18:08:34 +0200 |
---|---|---|
committer | Sergeanur <s.anureev@yandex.ua> | 2021-02-16 18:08:34 +0200 |
commit | 21278356ec282a801c4b89e96dff0fb9c985385b (patch) | |
tree | 91262729a91537296c4c3e6e1c0def10a6b46d77 | |
parent | e38467ef3affef25b83daf0c0c3b8a61f04e8a65 (diff) | |
parent | 1bfd7c034553d29b4b345b3f082662aafb5b55ef (diff) |
Merge remote-tracking branch 'origin/miami' into lcs
* origin/miami:
Fix FindClose->closedir
Only include sys/syscall.h when __linux__ is defined
Add unnamed semaphore define toggle for CdStreamPosix
Fix rare stream deadlock on Windows
-rw-r--r-- | src/core/CdStream.cpp | 41 | ||||
-rw-r--r-- | src/core/CdStreamPosix.cpp | 82 | ||||
-rw-r--r-- | src/skel/crossplatform.h | 7 |
3 files changed, 97 insertions, 33 deletions
diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index da85a238..977f16c2 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -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; } } diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index e18280e5..50d823d2 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -1,8 +1,8 @@ #ifndef _WIN32 #include "common.h" #include "crossplatform.h" -#include <pthread.h> #include <signal.h> +#include <pthread.h> #include <semaphore.h> #include <sys/types.h> #include <unistd.h> @@ -12,7 +12,11 @@ #include <sys/stat.h> #include <fcntl.h> #include <sys/resource.h> +#include <stdarg.h> + +#ifdef __linux__ #include <sys/syscall.h> +#endif #include "CdStream.h" #include "rwcore.h" @@ -25,6 +29,58 @@ bool flushStream[MAX_CDCHANNELS]; #endif +#ifdef USE_UNNAMED_SEM + +#define RE3_SEM_OPEN(name, ...) re3_sem_open() +sem_t* +re3_sem_open(void) +{ + sem_t* sem = (sem_t*)malloc(sizeof(sem_t)); + if (sem_init(sem, 0, 1) == -1) { + sem = SEM_FAILED; + } + + return sem; +} + +#define RE3_SEM_CLOSE(sem, format, ...) re3_sem_close(sem) +void +re3_sem_close(sem_t* sem) +{ + sem_destroy(sem); + free(sem); +} + +#else + +#define RE3_SEM_OPEN re3_sem_open +sem_t* +re3_sem_open(const char* format, ...) +{ + char semName[20]; + va_list va; + va_start(va, format); + vsprintf(semName, format, va); + + return sem_open(semName, O_CREAT, 0644, 1); +} + +#define RE3_SEM_CLOSE re3_sem_close +void +re3_sem_close(sem_t* sem, const char* format, ...) +{ + sem_close(sem); + + char semName[20]; + va_list va; + va_start(va, format); + vsprintf(semName, format, va); + + sem_unlink(semName); +} + +#endif + struct CdReadInfo { uint32 nSectorOffset; @@ -69,14 +125,13 @@ void CdStreamInitThread(void) { int status; - char semName[20]; #ifndef ONE_THREAD_PER_CHANNEL gChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32)); gChannelRequestQ.head = 0; gChannelRequestQ.tail = 0; gChannelRequestQ.size = gNumChannels + 1; ASSERT(gChannelRequestQ.items != nil ); - gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 0); + gCdStreamSema = RE3_SEM_OPEN("/semaphore_cd_stream"); if (gCdStreamSema == SEM_FAILED) { @@ -90,8 +145,7 @@ CdStreamInitThread(void) { for ( int32 i = 0; i < gNumChannels; i++ ) { - sprintf(semName,"/semaphore_done%d",i); - gpReadInfo[i].pDoneSemaphore = sem_open(semName, O_CREAT, 0644, 0); + gpReadInfo[i].pDoneSemaphore = RE3_SEM_OPEN("/semaphore_done%d", i); if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED) { @@ -101,8 +155,7 @@ CdStreamInitThread(void) } #ifdef ONE_THREAD_PER_CHANNEL - sprintf(semName,"/semaphore_start%d",i); - gpReadInfo[i].pStartSemaphore = sem_open(semName, O_CREAT, 0644, 0); + gpReadInfo[i].pStartSemaphore = RE3_SEM_OPEN("/semaphore_start%d", i); if (gpReadInfo[i].pStartSemaphore == SEM_FAILED) { @@ -464,21 +517,14 @@ void *CdStreamThread(void *param) #ifndef ONE_THREAD_PER_CHANNEL for ( int32 i = 0; i < gNumChannels; i++ ) { - sem_close(gpReadInfo[i].pDoneSemaphore); - sprintf(semName,"/semaphore_done%d",i); - sem_unlink(semName); + RE3_SEM_CLOSE(gpReadInfo[i].pDoneSemaphore, "/semaphore_done%d", i); } - sem_close(gCdStreamSema); - sem_unlink("/semaphore_cd_stream"); + RE3_SEM_CLOSE(gCdStreamSema, "/semaphore_cd_stream"); free(gChannelRequestQ.items); #else - sem_close(gpReadInfo[channel].pStartSemaphore); - sprintf(semName,"/semaphore_start%d",channel); - sem_unlink(semName); + RE3_SEM_CLOSE(gpReadInfo[channel].pStartSemaphore, "/semaphore_start%d", channel); - sem_close(gpReadInfo[channel].pDoneSemaphore); - sprintf(semName,"/semaphore_done%d",channel); - sem_unlink(semName); + RE3_SEM_CLOSE(gpReadInfo[channel].pDoneSemaphore, "/semaphore_done%d", channel); #endif if (gpReadInfo) free(gpReadInfo); diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 6ea5b11e..9b43bcaf 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -136,7 +136,12 @@ void GetLocalTime_CP(SYSTEMTIME* out); typedef void* HANDLE; #define INVALID_HANDLE_VALUE NULL -#define FindClose(h) closedir((DIR*)h) +#define FindClose(h) \ + do { \ + if (h != nil) \ + closedir((DIR*)h); \ + } while(0) + #define LOCALE_USER_DEFAULT 0 #define DATE_SHORTDATE 0 |