diff options
-rw-r--r-- | Alc/ALc.c | 21 | ||||
-rw-r--r-- | Alc/alcRing.c | 19 | ||||
-rw-r--r-- | Alc/backends/base.c | 12 | ||||
-rw-r--r-- | Alc/backends/base.h | 4 | ||||
-rw-r--r-- | Alc/compat.h | 6 | ||||
-rw-r--r-- | Alc/helpers.c | 122 | ||||
-rw-r--r-- | OpenAL32/Include/threads.h | 86 |
7 files changed, 215 insertions, 55 deletions
@@ -39,6 +39,8 @@ #include "bs2b.h" #include "alu.h" +#include "compat.h" +#include "threads.h" #include "alstring.h" #include "backends/base.h" @@ -764,15 +766,16 @@ static const ALCint alcEFXMinorVersion = 0; ************************************************/ static ALCdevice *volatile DeviceList = NULL; -static CRITICAL_SECTION ListLock; - -static void LockLists(void) +static almtx_t ListLock; +static inline void LockLists(void) { - EnterCriticalSection(&ListLock); + int lockret = almtx_lock(&ListLock); + assert(lockret == althrd_success); } -static void UnlockLists(void) +static inline void UnlockLists(void) { - LeaveCriticalSection(&ListLock); + int unlockret = almtx_unlock(&ListLock); + assert(unlockret == althrd_success); } /************************************************ @@ -859,6 +862,7 @@ static void ReleaseThreadCtx(void *ptr); static void alc_init(void) { const char *str; + int ret; LogFile = stderr; @@ -874,7 +878,8 @@ static void alc_init(void) ZScale *= -1.0f; althread_key_create(&LocalContext, ReleaseThreadCtx); - InitializeCriticalSection(&ListLock); + ret = almtx_init(&ListLock, almtx_recursive); + assert(ret == althrd_success); ThunkInit(); } @@ -1185,7 +1190,7 @@ static void alc_deinit_safe(void) FreeALConfig(); ThunkExit(); - DeleteCriticalSection(&ListLock); + almtx_destroy(&ListLock); althread_key_delete(LocalContext); if(LogFile != stderr) diff --git a/Alc/alcRing.c b/Alc/alcRing.c index f831860f..9b5d8214 100644 --- a/Alc/alcRing.c +++ b/Alc/alcRing.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include "alMain.h" +#include "threads.h" #include "compat.h" @@ -35,7 +36,7 @@ struct RingBuffer { ALint read_pos; ALint write_pos; - CRITICAL_SECTION cs; + almtx_t mtx; }; @@ -51,7 +52,7 @@ RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length) ring->read_pos = 0; ring->write_pos = 0; - InitializeCriticalSection(&ring->cs); + almtx_init(&ring->mtx, almtx_plain); } return ring; } @@ -60,7 +61,7 @@ void DestroyRingBuffer(RingBuffer *ring) { if(ring) { - DeleteCriticalSection(&ring->cs); + almtx_destroy(&ring->mtx); free(ring); } } @@ -69,9 +70,9 @@ ALsizei RingBufferSize(RingBuffer *ring) { ALsizei s; - EnterCriticalSection(&ring->cs); + almtx_lock(&ring->mtx); s = (ring->write_pos-ring->read_pos+ring->length) % ring->length; - LeaveCriticalSection(&ring->cs); + almtx_unlock(&ring->mtx); return s; } @@ -80,7 +81,7 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len) { int remain; - EnterCriticalSection(&ring->cs); + almtx_lock(&ring->mtx); remain = (ring->read_pos-ring->write_pos-1+ring->length) % ring->length; if(remain < len) len = remain; @@ -103,14 +104,14 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len) ring->write_pos %= ring->length; } - LeaveCriticalSection(&ring->cs); + almtx_unlock(&ring->mtx); } void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len) { int remain; - EnterCriticalSection(&ring->cs); + almtx_lock(&ring->mtx); remain = ring->length - ring->read_pos; if(remain < len) @@ -124,5 +125,5 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len) ring->read_pos += len; ring->read_pos %= ring->length; - LeaveCriticalSection(&ring->cs); + almtx_unlock(&ring->mtx); } diff --git a/Alc/backends/base.c b/Alc/backends/base.c index 8e59abdf..37e4ccc9 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -11,13 +11,15 @@ /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) { + int ret; self->mDevice = device; - InitializeCriticalSection(&self->mMutex); + ret = almtx_init(&self->mMutex, almtx_recursive); + assert(ret == althrd_success); } void ALCbackend_Destruct(ALCbackend *self) { - DeleteCriticalSection(&self->mMutex); + almtx_destroy(&self->mMutex); } ALCboolean ALCbackend_reset(ALCbackend* UNUSED(self)) @@ -42,12 +44,14 @@ ALint64 ALCbackend_getLatency(ALCbackend* UNUSED(self)) void ALCbackend_lock(ALCbackend *self) { - EnterCriticalSection(&self->mMutex); + int ret = almtx_lock(&self->mMutex); + assert(ret == althrd_success); } void ALCbackend_unlock(ALCbackend *self) { - LeaveCriticalSection(&self->mMutex); + int ret = almtx_unlock(&self->mMutex); + assert(ret == althrd_success); } diff --git a/Alc/backends/base.h b/Alc/backends/base.h index de5809ca..905c3ea4 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -2,7 +2,7 @@ #define AL_BACKENDS_BASE_H #include "alMain.h" -#include "compat.h" +#include "threads.h" struct ALCbackendVtable; @@ -12,7 +12,7 @@ typedef struct ALCbackend { ALCdevice *mDevice; - CRITICAL_SECTION mMutex; + almtx_t mMutex; } ALCbackend; void ALCbackend_Construct(ALCbackend *self, ALCdevice *device); diff --git a/Alc/compat.h b/Alc/compat.h index 426dad9d..9891412d 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -32,12 +32,6 @@ FILE *al_fopen(const char *fname, const char *mode); #include <pthread.h> -typedef pthread_mutex_t CRITICAL_SECTION; -void InitializeCriticalSection(CRITICAL_SECTION *cs); -void DeleteCriticalSection(CRITICAL_SECTION *cs); -void EnterCriticalSection(CRITICAL_SECTION *cs); -void LeaveCriticalSection(CRITICAL_SECTION *cs); - ALuint timeGetTime(void); void Sleep(ALuint t); diff --git a/Alc/helpers.c b/Alc/helpers.c index e9ef72d1..dc8eefaf 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -90,6 +90,7 @@ DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, #include "vector.h" #include "alstring.h" #include "compat.h" +#include "threads.h" extern inline RefCount IncrementRef(volatile RefCount *ptr); @@ -308,7 +309,50 @@ void RestoreFPUMode(const FPUCtl *ctl) } +extern inline int almtx_lock(almtx_t *mtx); +extern inline int almtx_unlock(almtx_t *mtx); +extern inline int almtx_trylock(almtx_t *mtx); + #ifdef _WIN32 +int almtx_init(almtx_t *mtx, int type) +{ + if(!mtx) return althrd_error; + type &= ~(almtx_recursive|almtx_timed|almtx_normal|almtx_errorcheck); + if(type != 0) return althrd_error; + + InitializeCriticalSection(mtx); + return althrd_success; +} + +void almtx_destroy(almtx_t *mtx) +{ + DeleteCriticalSection(mtx); +} + +int almtx_timedlock(almtx_t *mtx, const alxtime *xt) +{ + DWORD expire; + int ret; + + if(!mtx || !xt) + return althrd_error; + + expire = xt->sec * 1000; + expire += (xt->nsec+999999) / 1000000; + expire += timeGetTime(); + + while((ret=almtx_trylock(mtx)) == althrd_busy) + { + DWORD now = timeGetTime(); + if(expire <= now) break; + // busy loop! + SwitchToThread(); + } + + return ret; +} + + extern inline int alsched_yield(void); void althread_once(althread_once_t *once, void (*callback)(void)) @@ -420,44 +464,70 @@ FILE *al_fopen(const char *fname, const char *mode) #include <time.h> #include <sys/time.h> -void InitializeCriticalSection(CRITICAL_SECTION *cs) + +int almtx_init(almtx_t *mtx, int type) { - pthread_mutexattr_t attrib; int ret; - ret = pthread_mutexattr_init(&attrib); - assert(ret == 0); + if(!mtx) return althrd_error; + if((type&~(almtx_normal|almtx_recursive|almtx_timed|almtx_errorcheck)) != 0) + return althrd_error; - ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE); + type &= ~almtx_timed; + if(type == almtx_plain) + ret = pthread_mutex_init(mtx, NULL); + else + { + pthread_mutexattr_t attr; + + ret = pthread_mutexattr_init(&attr); + if(ret) return althrd_error; + + switch(type) + { + case almtx_normal: + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + break; + case almtx_recursive: + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); #ifdef HAVE_PTHREAD_NP_H - if(ret != 0) - ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE); + if(ret != 0) + ret = pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE); #endif - assert(ret == 0); - ret = pthread_mutex_init(cs, &attrib); - assert(ret == 0); - - pthread_mutexattr_destroy(&attrib); -} -void DeleteCriticalSection(CRITICAL_SECTION *cs) -{ - int ret; - ret = pthread_mutex_destroy(cs); - assert(ret == 0); + break; + case almtx_errorcheck: + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + break; + default: + ret = 1; + } + if(ret == 0) + ret = pthread_mutex_init(mtx, &attr); + pthread_mutexattr_destroy(&attr); + } + return ret ? althrd_error : althrd_success; } -void EnterCriticalSection(CRITICAL_SECTION *cs) + +void almtx_destroy(almtx_t *mtx) { - int ret; - ret = pthread_mutex_lock(cs); - assert(ret == 0); + pthread_mutex_destroy(mtx); } -void LeaveCriticalSection(CRITICAL_SECTION *cs) + +int almtx_timedlock(almtx_t *mtx, const alxtime *xt) { - int ret; - ret = pthread_mutex_unlock(cs); - assert(ret == 0); + struct timespec ts; + + if(!mtx || !xt) + return althrd_error; + + ts.tv_sec = xt->sec; + ts.tv_nsec = xt->nsec; + if(pthread_mutex_timedlock(mtx, &ts) != 0) + return althrd_busy; + return althrd_success; } + /* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed * to the expected DWORD. Both are defined as unsigned 32-bit types, however. * Additionally, Win32 is supposed to measure the time since Windows started, diff --git a/OpenAL32/Include/threads.h b/OpenAL32/Include/threads.h index 26493101..03589d15 100644 --- a/OpenAL32/Include/threads.h +++ b/OpenAL32/Include/threads.h @@ -11,4 +11,90 @@ ALuint StopThread(althread_t thread); void SetThreadName(const char *name); + +enum { + althrd_success = 0, + althrd_timeout, + althrd_error, + althrd_busy, + althrd_nomem +}; + +enum { + almtx_plain = 0, + almtx_recursive = 1, + almtx_timed = 2, + almtx_normal = 4, + almtx_errorcheck = 8 +}; + +typedef struct alxtime { + time_t sec; + long nsec; +} alxtime; + + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +typedef CRITICAL_SECTION almtx_t; + +inline int almtx_lock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + EnterCriticalSection(mtx); + return althrd_success; +} + +inline int almtx_unlock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + LeaveCriticalSection(mtx); + return althrd_success; +} + +inline int almtx_trylock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + if(!TryEnterCriticalSection(mtx)) + return althrd_busy; + return althrd_success; +} + +#else + +#include <pthread.h> + + +typedef pthread_mutex_t almtx_t; + +inline int almtx_lock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + pthread_mutex_lock(mtx); + return althrd_success; +} + +inline int almtx_unlock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + pthread_mutex_unlock(mtx); + return althrd_success; +} + +inline int almtx_trylock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + if(pthread_mutex_trylock(mtx) != 0) + return althrd_busy; + return althrd_success; +} + +#endif + +int almtx_init(almtx_t *mtx, int type); +void almtx_destroy(almtx_t *mtx); +int almtx_timedlock(almtx_t *mtx, const alxtime *xt); + #endif /* AL_THREADS_H */ |