Move the threads and mutex wrappers to threads.c
This commit is contained in:
parent
e8517d8600
commit
505ef82246
256
Alc/helpers.c
256
Alc/helpers.c
@ -309,127 +309,8 @@ void RestoreFPUMode(const FPUCtl *ctl)
|
||||
}
|
||||
|
||||
|
||||
extern inline int althrd_equal(althrd_t thr0, althrd_t thr1);
|
||||
extern inline void althrd_exit(int res);
|
||||
extern inline void althrd_yield(void);
|
||||
|
||||
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
|
||||
|
||||
#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
|
||||
|
||||
typedef struct thread_cntr {
|
||||
althrd_start_t func;
|
||||
void *arg;
|
||||
} thread_cntr;
|
||||
|
||||
static DWORD WINAPI thread_starter(void *arg)
|
||||
{
|
||||
thread_cntr cntr;
|
||||
memcpy(&cntr, arg, sizeof(cntr));
|
||||
free(arg);
|
||||
|
||||
return (DWORD)((*cntr.func)(cntr.arg));
|
||||
}
|
||||
|
||||
|
||||
int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
{
|
||||
thread_cntr *cntr;
|
||||
DWORD dummy;
|
||||
HANDLE hdl;
|
||||
|
||||
cntr = malloc(sizeof(*cntr));
|
||||
if(!cntr) return althrd_nomem;
|
||||
|
||||
cntr->func = func;
|
||||
cntr->arg = arg;
|
||||
|
||||
hdl = CreateThread(NULL, THREAD_STACK_SIZE, thread_starter, cntr, 0, &dummy);
|
||||
if(!hdl)
|
||||
{
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
|
||||
*thr = hdl;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_detach(althrd_t thr)
|
||||
{
|
||||
if(!thr) return althrd_error;
|
||||
CloseHandle(thr);
|
||||
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_join(althrd_t thr, int *res)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
if(!thr) return althrd_error;
|
||||
|
||||
WaitForSingleObject(thr, INFINITE);
|
||||
GetExitCodeThread(thr, &code);
|
||||
CloseHandle(thr);
|
||||
|
||||
*res = (int)code;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_sleep(const struct timespec *ts, struct timespec* UNUSED(rem))
|
||||
{
|
||||
DWORD msec;
|
||||
msec = ts->tv_sec * 1000;
|
||||
msec += (ts->tv_nsec+999999) / 1000000;
|
||||
Sleep(msec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 struct timespec *ts)
|
||||
{
|
||||
DWORD start, timelen;
|
||||
int ret;
|
||||
|
||||
if(!mtx || !ts)
|
||||
return althrd_error;
|
||||
|
||||
timelen = ts->tv_sec * 1000;
|
||||
timelen += (ts->tv_nsec+999999) / 1000000;
|
||||
|
||||
start = timeGetTime();
|
||||
while((ret=almtx_trylock(mtx)) == althrd_busy)
|
||||
{
|
||||
DWORD now = timeGetTime();
|
||||
if(now-start >= timelen)
|
||||
break;
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern inline int alsched_yield(void);
|
||||
|
||||
void althread_once(althread_once_t *once, void (*callback)(void))
|
||||
@ -533,148 +414,11 @@ FILE *al_fopen(const char *fname, const char *mode)
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#ifdef HAVE_PTHREAD_NP_H
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
extern inline althrd_t althrd_current(void);
|
||||
extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem);
|
||||
|
||||
|
||||
#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
|
||||
|
||||
typedef struct thread_cntr {
|
||||
althrd_start_t func;
|
||||
void *arg;
|
||||
} thread_cntr;
|
||||
|
||||
static void *thread_starter(void *arg)
|
||||
{
|
||||
thread_cntr cntr;
|
||||
memcpy(&cntr, arg, sizeof(cntr));
|
||||
free(arg);
|
||||
|
||||
return (void*)(intptr_t)((*cntr.func)(cntr.arg));
|
||||
}
|
||||
|
||||
|
||||
int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
{
|
||||
thread_cntr *cntr;
|
||||
pthread_attr_t attr;
|
||||
|
||||
cntr = malloc(sizeof(*cntr));
|
||||
if(!cntr) return althrd_nomem;
|
||||
|
||||
if(pthread_attr_init(&attr) != 0)
|
||||
{
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0)
|
||||
{
|
||||
pthread_attr_destroy(&attr);
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
|
||||
cntr->func = func;
|
||||
cntr->arg = arg;
|
||||
if(pthread_create(thr, &attr, thread_starter, cntr) != 0)
|
||||
{
|
||||
pthread_attr_destroy(&attr);
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_detach(althrd_t thr)
|
||||
{
|
||||
if(pthread_detach(thr) != 0)
|
||||
return althrd_error;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_join(althrd_t thr, int *res)
|
||||
{
|
||||
void *code;
|
||||
|
||||
if(!res) return althrd_error;
|
||||
|
||||
if(pthread_join(thr, &code) != 0)
|
||||
return althrd_error;
|
||||
*res = (int)(intptr_t)code;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
|
||||
int almtx_init(almtx_t *mtx, int type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(!mtx) return althrd_error;
|
||||
if((type&~(almtx_normal|almtx_recursive|almtx_timed|almtx_errorcheck)) != 0)
|
||||
return althrd_error;
|
||||
|
||||
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(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
#endif
|
||||
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 almtx_destroy(almtx_t *mtx)
|
||||
{
|
||||
pthread_mutex_destroy(mtx);
|
||||
}
|
||||
|
||||
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts)
|
||||
{
|
||||
if(!mtx || !ts)
|
||||
return althrd_error;
|
||||
|
||||
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,
|
||||
|
255
Alc/threads.c
255
Alc/threads.c
@ -28,12 +28,23 @@
|
||||
#include "alMain.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
|
||||
extern inline int althrd_equal(althrd_t thr0, althrd_t thr1);
|
||||
extern inline void althrd_exit(int res);
|
||||
extern inline void althrd_yield(void);
|
||||
|
||||
extern inline int almtx_lock(almtx_t *mtx);
|
||||
extern inline int almtx_unlock(almtx_t *mtx);
|
||||
extern inline int almtx_trylock(almtx_t *mtx);
|
||||
|
||||
|
||||
#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
typedef struct althread_info {
|
||||
ALuint (*func)(ALvoid*);
|
||||
@ -115,9 +126,122 @@ void SetThreadName(const char *name)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
typedef struct thread_cntr {
|
||||
althrd_start_t func;
|
||||
void *arg;
|
||||
} thread_cntr;
|
||||
|
||||
static DWORD WINAPI althrd_starter(void *arg)
|
||||
{
|
||||
thread_cntr cntr;
|
||||
memcpy(&cntr, arg, sizeof(cntr));
|
||||
free(arg);
|
||||
|
||||
return (DWORD)((*cntr.func)(cntr.arg));
|
||||
}
|
||||
|
||||
|
||||
int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
{
|
||||
thread_cntr *cntr;
|
||||
DWORD dummy;
|
||||
HANDLE hdl;
|
||||
|
||||
cntr = malloc(sizeof(*cntr));
|
||||
if(!cntr) return althrd_nomem;
|
||||
|
||||
cntr->func = func;
|
||||
cntr->arg = arg;
|
||||
|
||||
hdl = CreateThread(NULL, THREAD_STACK_SIZE, althrd_starter, cntr, 0, &dummy);
|
||||
if(!hdl)
|
||||
{
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
|
||||
*thr = hdl;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_detach(althrd_t thr)
|
||||
{
|
||||
if(!thr) return althrd_error;
|
||||
CloseHandle(thr);
|
||||
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_join(althrd_t thr, int *res)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
if(!thr) return althrd_error;
|
||||
|
||||
WaitForSingleObject(thr, INFINITE);
|
||||
GetExitCodeThread(thr, &code);
|
||||
CloseHandle(thr);
|
||||
|
||||
*res = (int)code;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_sleep(const struct timespec *ts, struct timespec* UNUSED(rem))
|
||||
{
|
||||
DWORD msec;
|
||||
msec = ts->tv_sec * 1000;
|
||||
msec += (ts->tv_nsec+999999) / 1000000;
|
||||
Sleep(msec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 struct timespec *ts)
|
||||
{
|
||||
DWORD start, timelen;
|
||||
int ret;
|
||||
|
||||
if(!mtx || !ts)
|
||||
return althrd_error;
|
||||
|
||||
timelen = ts->tv_sec * 1000;
|
||||
timelen += (ts->tv_nsec+999999) / 1000000;
|
||||
|
||||
start = timeGetTime();
|
||||
while((ret=almtx_trylock(mtx)) == althrd_busy)
|
||||
{
|
||||
DWORD now = timeGetTime();
|
||||
if(now-start >= timelen)
|
||||
break;
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#ifdef HAVE_PTHREAD_NP_H
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
typedef struct althread_info {
|
||||
ALuint (*func)(ALvoid*);
|
||||
@ -197,4 +321,135 @@ void SetThreadName(const char *name)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern inline althrd_t althrd_current(void);
|
||||
extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem);
|
||||
|
||||
|
||||
typedef struct thread_cntr {
|
||||
althrd_start_t func;
|
||||
void *arg;
|
||||
} thread_cntr;
|
||||
|
||||
static void *althrd_starter(void *arg)
|
||||
{
|
||||
thread_cntr cntr;
|
||||
memcpy(&cntr, arg, sizeof(cntr));
|
||||
free(arg);
|
||||
|
||||
return (void*)(intptr_t)((*cntr.func)(cntr.arg));
|
||||
}
|
||||
|
||||
|
||||
int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
{
|
||||
thread_cntr *cntr;
|
||||
pthread_attr_t attr;
|
||||
|
||||
cntr = malloc(sizeof(*cntr));
|
||||
if(!cntr) return althrd_nomem;
|
||||
|
||||
if(pthread_attr_init(&attr) != 0)
|
||||
{
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0)
|
||||
{
|
||||
pthread_attr_destroy(&attr);
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
|
||||
cntr->func = func;
|
||||
cntr->arg = arg;
|
||||
if(pthread_create(thr, &attr, althrd_starter, cntr) != 0)
|
||||
{
|
||||
pthread_attr_destroy(&attr);
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_detach(althrd_t thr)
|
||||
{
|
||||
if(pthread_detach(thr) != 0)
|
||||
return althrd_error;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
int althrd_join(althrd_t thr, int *res)
|
||||
{
|
||||
void *code;
|
||||
|
||||
if(!res) return althrd_error;
|
||||
|
||||
if(pthread_join(thr, &code) != 0)
|
||||
return althrd_error;
|
||||
*res = (int)(intptr_t)code;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
|
||||
int almtx_init(almtx_t *mtx, int type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(!mtx) return althrd_error;
|
||||
if((type&~(almtx_normal|almtx_recursive|almtx_timed|almtx_errorcheck)) != 0)
|
||||
return althrd_error;
|
||||
|
||||
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(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
#endif
|
||||
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 almtx_destroy(almtx_t *mtx)
|
||||
{
|
||||
pthread_mutex_destroy(mtx);
|
||||
}
|
||||
|
||||
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts)
|
||||
{
|
||||
if(!mtx || !ts)
|
||||
return althrd_error;
|
||||
|
||||
if(pthread_mutex_timedlock(mtx, ts) != 0)
|
||||
return althrd_busy;
|
||||
return althrd_success;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user