#ifndef THREAD_H
+// enable Sys_PrintfToTerminal calls on nearly every threading call
//#define THREADDEBUG
+// use recursive mutex (non-posix) extensions in thread_pthread
+#define THREADRECURSIVE
-#define Thread_CreateMutex() (_Thread_CreateMutex(__FILE__, __LINE__))
-#define Thread_DestroyMutex(m) (_Thread_DestroyMutex(m, __FILE__, __LINE__))
-#define Thread_LockMutex(m) (_Thread_LockMutex(m, __FILE__, __LINE__))
-#define Thread_UnlockMutex(m) (_Thread_UnlockMutex(m, __FILE__, __LINE__))
+#define Thread_CreateMutex() (_Thread_CreateMutex(__FILE__, __LINE__))
+#define Thread_DestroyMutex(m) (_Thread_DestroyMutex(m, __FILE__, __LINE__))
+#define Thread_LockMutex(m) (_Thread_LockMutex(m, __FILE__, __LINE__))
+#define Thread_UnlockMutex(m) (_Thread_UnlockMutex(m, __FILE__, __LINE__))
+#define Thread_CreateCond() (_Thread_CreateCond(__FILE__, __LINE__))
+#define Thread_DestroyCond(cond) (_Thread_DestroyCond(cond, __FILE__, __LINE__))
+#define Thread_CondSignal(cond) (_Thread_CondSignal(cond, __FILE__, __LINE__))
+#define Thread_CondBroadcast(cond) (_Thread_CondBroadcast(cond, __FILE__, __LINE__))
+#define Thread_CondWait(cond, mutex) (_Thread_CondWait(cond, mutex, __FILE__, __LINE__))
+#define Thread_CreateThread(fn, data) (_Thread_CreateThread(fn, data, __FILE__, __LINE__))
+#define Thread_WaitThread(thread, retval) (_Thread_WaitThread(thread, retval, __FILE__, __LINE__))
int Thread_Init(void);
void Thread_Shutdown(void);
void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline);
int _Thread_LockMutex(void *mutex, const char *filename, int fileline);
int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline);
-void *Thread_CreateCond(void);
-void Thread_DestroyCond(void *cond);
-int Thread_CondSignal(void *cond);
-int Thread_CondBroadcast(void *cond);
-int Thread_CondWait(void *cond, void *mutex);
-void *Thread_CreateThread(int (*fn)(void *), void *data);
-int Thread_WaitThread(void *thread, int retval);
+void *_Thread_CreateCond(const char *filename, int fileline);
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline);
+int _Thread_CondSignal(void *cond, const char *filename, int fileline);
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline);
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline);
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline);
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline);
#endif
void *_Thread_CreateMutex(const char *filename, int fileline)
{
-#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p create %s:%i\n" , mutex, filename, fileline);
-#endif
return NULL;
}
void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
-#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p destroy %s:%i\n", mutex, filename, fileline);
-#endif
}
int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
-#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p lock %s:%i\n" , mutex, filename, fileline);
-#endif
return -1;
}
int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
-#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p unlock %s:%i\n" , mutex, filename, fileline);
-#endif
return -1;
}
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
return NULL;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
return -1;
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
return -1;
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
return -1;
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
return NULL;
}
-int Thread_WaitThread(void *thread, int retval)
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
{
return retval;
}
-
#include "quakedef.h"
#include "thread.h"
+#ifdef THREADRECURSIVE
+#define __USE_UNIX98
#include <pthread.h>
+#endif
#include <stdint.h>
+
int Thread_Init(void)
{
return 0;
void *_Thread_CreateMutex(const char *filename, int fileline)
{
+#ifdef THREADRECURSIVE
+ pthread_mutexattr_t attr;
+#endif
pthread_mutex_t *mutexp = (pthread_mutex_t *) Z_Malloc(sizeof(pthread_mutex_t));
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p create %s:%i\n" , mutexp, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutexp, filename, fileline);
#endif
+#ifdef THREADRECURSIVE
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(mutexp, &attr);
+#else
pthread_mutex_init(mutexp, NULL);
+#endif
return mutexp;
}
{
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p destroy %s:%i\n", mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
#endif
pthread_mutex_destroy(mutexp);
Z_Free(mutexp);
{
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p lock %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
#endif
return pthread_mutex_lock(mutexp);
}
{
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p unlock %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
#endif
return pthread_mutex_unlock(mutexp);
}
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) Z_Malloc(sizeof(pthread_cond_t));
pthread_cond_init(condp, NULL);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond create %s:%i\n" , condp, filename, fileline);
+#endif
return condp;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
+#endif
pthread_cond_destroy(condp);
Z_Free(condp);
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
+#endif
return pthread_cond_signal(condp);
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
+#endif
return pthread_cond_broadcast(condp);
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
+#endif
return pthread_cond_wait(condp, mutexp);
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
pthread_t *threadp = (pthread_t *) Z_Malloc(sizeof(pthread_t));
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread create %s:%i\n" , threadp, filename, fileline);
+#endif
int r = pthread_create(threadp, NULL, (void * (*) (void *)) fn, data);
if(r)
{
return threadp;
}
-int Thread_WaitThread(void *thread, int retval)
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
{
pthread_t *threadp = (pthread_t *) thread;
void *status = (void *) (intptr_t) retval;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread wait %s:%i\n" , thread, filename, fileline);
+#endif
pthread_join(*threadp, &status);
Z_Free(threadp);
return (int) (intptr_t) status;
{
void *mutex = SDL_CreateMutex();
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p create %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutex, filename, fileline);
#endif
return mutex;
}
void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p destroy %s:%i\n", mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
#endif
SDL_DestroyMutex((SDL_mutex *)mutex);
}
int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p lock %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
#endif
return SDL_LockMutex((SDL_mutex *)mutex);
}
int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p unlock %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
#endif
return SDL_UnlockMutex((SDL_mutex *)mutex);
}
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
- return SDL_CreateCond();
+ void *cond = (void *)SDL_CreateCond();
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond create %s:%i\n" , cond, filename, fileline);
+#endif
+ return cond;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
+#endif
SDL_DestroyCond((SDL_cond *)cond);
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
+#endif
return SDL_CondSignal((SDL_cond *)cond);
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
+#endif
return SDL_CondBroadcast((SDL_cond *)cond);
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
+#endif
return SDL_CondWait((SDL_cond *)cond, (SDL_mutex *)mutex);
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
- return SDL_CreateThread(fn, data);
+ void *thread = (void *)SDL_CreateThread(fn, data);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread create %s:%i\n" , thread, filename, fileline);
+#endif
+ return thread;
}
-int Thread_WaitThread(void *thread, int retval)
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
{
int status = retval;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread wait %s:%i\n" , thread, filename, fileline);
+#endif
SDL_WaitThread((SDL_Thread *)thread, &status);
return status;
}
{
void *mutex = (void *)CreateMutex(NULL, FALSE, NULL);
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p create %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutex, filename, fileline);
#endif
return mutex;
}
void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p destroy %s:%i\n", mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
#endif
CloseHandle(mutex);
}
int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p lock %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
#endif
return (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) ? -1 : 0;
}
int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p unlock %s:%i\n" , mutex, filename, fileline);
+ Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
#endif
return (ReleaseMutex(mutex) == FALSE) ? -1 : 0;
}
}
thread_cond_t;
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)calloc(sizeof(*c), 1);
c->mutex = CreateMutex(NULL, FALSE, NULL);
c->done = Thread_CreateSemaphore(0);
c->waiting = 0;
c->signals = 0;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond create %s:%i\n" , c, filename, fileline);
+#endif
return c;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
+#endif
Thread_DestroySemaphore(c->sem);
Thread_DestroySemaphore(c->done);
CloseHandle(c->mutex);
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
int n;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
+#endif
WaitForSingleObject(c->mutex, INFINITE);
n = c->waiting - c->signals;
if (n > 0)
return 0;
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
int i = 0;
int n = 0;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
+#endif
WaitForSingleObject(c->mutex, INFINITE);
n = c->waiting - c->signals;
if (n > 0)
return 0;
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
int waitresult;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
+#endif
WaitForSingleObject(c->mutex, INFINITE);
c->waiting++;
return w->result;
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
threadwrapper_t *w = (threadwrapper_t *)calloc(sizeof(*w), 1);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread create %s:%i\n" , w, filename, fileline);
+#endif
w->fn = fn;
w->data = data;
w->threadid = 0;
return (void *)w;
}
-int Thread_WaitThread(void *d, int retval)
+int _Thread_WaitThread(void *d, int retval, const char *filename, int fileline)
{
threadwrapper_t *w = (threadwrapper_t *)d;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread wait %s:%i\n" , w, filename, fileline);
+#endif
WaitForSingleObject(w->handle, INFINITE);
CloseHandle(w->handle);
retval = w->result;