diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 63096a63d..6e87b8eb2 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -45,6 +45,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __MACOSX__ #include #endif +#ifdef MULTITHREAD +#include +#endif #include "quakedef.h" @@ -582,3 +585,52 @@ void Sys_CloseClipboard(char *bf) void Sys_SaveClipboard(char *text) { Q_strncpyz(clipboard_buffer, text, SYS_CLIPBOARD_SIZE); } + +#ifdef MULTITHREAD +/* Thread creation calls */ +typedef void *(*pfunction_t)(void *); + +qboolean Sys_CreateThread(int (*func)(void *), void *args, int stacksize) +{ + pthread_t thread; + pthread_attr_t attr; + + pthread_attr_init(&attr); + if (stacksize < PTHREAD_STACK_MIN) + stacksize = PTHREAD_STACK_MIN; + pthread_attr_setstacksize(&attr, stacksize); + + return !pthread_create(&thread, &attr, (pfunction_t)func, args); +} + +/* Mutex calls */ +void *Sys_CreateMutex() +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + + if (mutex && !pthread_mutex_init(mutex, NULL)) + return mutex; + return NULL; +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return !pthread_mutex_trylock(mutex); +} + +qboolean Sys_LockMutex(void *mutex) +{ + return !pthread_mutex_lock(mutex); +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !pthread_mutex_unlock(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + pthread_mutex_destroy(mutex); + free(mutex); +} +#endif \ No newline at end of file diff --git a/engine/client/sys_morphos.c b/engine/client/sys_morphos.c index 1488b996d..fb23b4637 100755 --- a/engine/client/sys_morphos.c +++ b/engine/client/sys_morphos.c @@ -434,3 +434,14 @@ void Sys_LowFPPrecision (void) { } +#ifdef MULTITHREAD +/* Everything here is stubbed because I don't know MorphOS */ +/* Thread creation calls */ +qboolean Sys_CreateThread(int (*func)(void *), void *args, int stacksize) { return FALSE; } +/* Mutex calls */ +void *Sys_CreateMutex() { return NULL; } +qboolean Sys_TryLockMutex(void *mutex) { return FALSE; } +qboolean Sys_LockMutex(void *mutex) { return FALSE; } +qboolean Sys_UnlockMutex(void *mutex) { return FALSE; } +void Sys_DestroyMutex(void *mutex) {} +#endif diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index 0ed62aa0b..09cdba907 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -1,6 +1,10 @@ #include "quakedef.h" #include +#ifdef MULTITHREAD +#include +#endif + #ifndef WIN32 #include @@ -345,3 +349,40 @@ void Sys_CloseClipboard(char *bf) void Sys_SaveClipboard(char *text) { } + +#ifdef MULTITHREAD +/* Thread creation calls */ +qboolean Sys_CreateThread(int (*func)(void *), void *args, int stacksize) +{ + // SDL threads do not support setting thread stack size + return SDL_CreateThread(func, args) != NULL; +} + +/* Mutex calls */ +// SDL mutexes don't have try-locks for mutexes in the spec so we stick with 1-value semaphores +void *Sys_CreateMutex() +{ + return (void *)SDL_CreateSemaphore(1); +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return !SDL_SemTryWait(mutex); +} + +qboolean Sys_LockMutex(void *mutex) +{ + return !SDL_SemWait(mutex); +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !SDL_SemPost(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + return SDL_DestroySemaphore(mutex); +} +#endif + diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index c3ed553d6..9d89fbeb5 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -1350,3 +1350,67 @@ void MaskExceptions (void) { } #endif + +#ifdef MULTITHREAD +/* Thread creation calls */ +typedef struct threadwrap_s +{ + void (*func)(void *); + void *args; +} threadwrap_t; + +// the thread call is wrapped so we don't need WINAPI everywhere +DWORD WINAPI threadwrapper(void *args) +{ + threadwrap_t tw; + tw.func = ((threadwrap_t *)args)->func; + tw.args = ((threadwrap_t *)args)->args; + + free(args); + tw.func(tw.args); + + return 0; +} + +qboolean Sys_CreateThread(int (*func)(void *), void *args, int stacksize) +{ + threadwrap_t *tw = (threadwrap_t *)malloc(sizeof(threadwrap_t)); + + stacksize += 128; // wrapper overhead, also prevent default stack size + tw->func = func; + tw->args = args; + if (!CreateThread(NULL, stacksize, &threadwrapper, (void *)tw, 0, NULL)) + { + free(tw); + return FALSE; + } + + return TRUE; +} + +/* Mutex calls */ +void *Sys_CreateMutex() +{ + return (void *)CreateMutex(NULL, 0, NULL); +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0; +} + +qboolean Sys_LockMutex(void *mutex) +{ + return WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0; +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !!ReleaseMutex(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + CloseHandle(mutex); +} +#endif \ No newline at end of file diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index 2dac9bcb8..bd8f3dcf8 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -862,3 +862,52 @@ void Sys_ServerActivity(void) { } +#ifdef MULTITHREAD +/* Thread creation calls */ +typedef void *(*pfunction_t)(void *); + +qboolean Sys_CreateThread(int (*func)(void *), void *args, int stacksize) +{ + pthread_t thread; + pthread_attr_t attr; + + pthread_attr_init(&attr); + if (stacksize < PTHREAD_STACK_MIN) + stacksize = PTHREAD_STACK_MIN; + pthread_attr_setstacksize(&attr, stacksize); + + return !pthread_create(&thread, &attr, (pfunction_t)func, args); +} + +/* Mutex calls */ +void *Sys_CreateMutex() +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + + if (mutex && !pthread_mutex_init(mutex, NULL)) + return mutex; + return NULL; +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return !pthread_mutex_trylock(mutex); +} + +qboolean Sys_LockMutex(void *mutex) +{ + return !pthread_mutex_lock(mutex); +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !pthread_mutex_unlock(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + pthread_mutex_destroy(mutex); + free(mutex); +} +#endif + diff --git a/engine/server/sv_sys_win.c b/engine/server/sv_sys_win.c index fa9454862..1eb943bbd 100644 --- a/engine/server/sv_sys_win.c +++ b/engine/server/sv_sys_win.c @@ -1137,20 +1137,6 @@ int main (int argc, char **argv) return true; } - - - - - - - - - - - - - - #ifdef USESERVICE void CreateSampleService(qboolean create) { @@ -1227,4 +1213,69 @@ void CreateSampleService(qboolean create) } } #endif + +#ifdef MULTITHREAD +/* Thread creation calls */ +typedef struct threadwrap_s +{ + void (*func)(void *); + void *args; +} threadwrap_t; + +// the thread call is wrapped so we don't need WINAPI everywhere +DWORD WINAPI threadwrapper(void *args) +{ + threadwrap_t tw; + tw.func = ((threadwrap_t *)args)->func; + tw.args = ((threadwrap_t *)args)->args; + + free(args); + tw->func(tw->args); + + return 0; +} + +qboolean Sys_CreateThread(int (*func)(void *), void *args, int stacksize) +{ + threadwrap_t *tw = (threadwrap_t *)malloc(sizeof(threadwrap_t)); + + stacksize += 128; // wrapper overhead, also prevent default stack size + tw->func = func; + tw->args = args; + if (!CreateThread(NULL, stacksize, &threadwrapper, (void *)tw, 0, NULL)) + { + free(tw); + return FALSE; + } + + return TRUE; +} + +/* Mutex calls */ +void *Sys_CreateMutex() +{ + return (void *)CreateMutex(NULL, 0, NULL); +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0; +} + +qboolean Sys_LockMutex(void *mutex) +{ + return WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0; +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !!ReleaseMutex(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + CloseHandle(mutex); +} +#endif + #endif