aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c21
-rw-r--r--Alc/alcRing.c19
-rw-r--r--Alc/backends/base.c12
-rw-r--r--Alc/backends/base.h4
-rw-r--r--Alc/compat.h6
-rw-r--r--Alc/helpers.c122
-rw-r--r--OpenAL32/Include/threads.h86
7 files changed, 215 insertions, 55 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index d0847018..14d95023 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -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 */