aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/helpers.c')
-rw-r--r--Alc/helpers.c122
1 files changed, 96 insertions, 26 deletions
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,