From 6bf20c78f5b69d40bcc4931df93d29198435ab67 Mon Sep 17 00:00:00 2001 From: zakk Date: Fri, 26 Aug 2005 17:39:27 +0000 Subject: newlines fixed git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/bspc/l_threads.c | 3020 ++++++++++++++++++++++++------------------------- 1 file changed, 1510 insertions(+), 1510 deletions(-) (limited to 'code/bspc/l_threads.c') diff --git a/code/bspc/l_threads.c b/code/bspc/l_threads.c index bc4b998..94e641a 100755 --- a/code/bspc/l_threads.c +++ b/code/bspc/l_threads.c @@ -1,1510 +1,1510 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "l_cmd.h" -#include "l_threads.h" -#include "l_log.h" -#include "l_mem.h" - -#define MAX_THREADS 64 - -//#define THREAD_DEBUG - -int dispatch; -int workcount; -int oldf; -qboolean pacifier; -qboolean threaded; -void (*workfunction) (int); - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int GetThreadWork(void) -{ - int r; - int f; - - ThreadLock(); - - if (dispatch == workcount) - { - ThreadUnlock (); - return -1; - } - - f = 10*dispatch / workcount; - if (f != oldf) - { - oldf = f; - if (pacifier) - printf ("%i...", f); - } //end if - - r = dispatch; - dispatch++; - ThreadUnlock (); - - return r; -} //end of the function GetThreadWork -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadWorkerFunction(int threadnum) -{ - int work; - - while(1) - { - work = GetThreadWork (); - if (work == -1) - break; -//printf ("thread %i, work %i\n", threadnum, work); - workfunction(work); - } //end while -} //end of the function ThreadWorkerFunction -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - if (numthreads == -1) - ThreadSetDefault (); - workfunction = func; - RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); -} //end of the function RunThreadsOnIndividual - - -//=================================================================== -// -// WIN32 -// -//=================================================================== - -#if defined(WIN32) || defined(_WIN32) - -#define USED - -#include - -typedef struct thread_s -{ - HANDLE handle; - int threadid; - int id; - struct thread_s *next; -} thread_t; - -thread_t *firstthread; -thread_t *lastthread; -int currentnumthreads; -int currentthreadid; - -int numthreads = 1; -CRITICAL_SECTION crit; -HANDLE semaphore; -static int enter; -static int numwaitingthreads = 0; - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetDefault(void) -{ - SYSTEM_INFO info; - - if (numthreads == -1) // not set manually - { - GetSystemInfo (&info); - numthreads = info.dwNumberOfProcessors; - if (numthreads < 1 || numthreads > 32) - numthreads = 1; - } //end if - qprintf ("%i threads\n", numthreads); -} //end of the function ThreadSetDefault -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadLock(void) -{ - if (!threaded) - { - Error("ThreadLock: !threaded"); - return; - } //end if - EnterCriticalSection(&crit); - if (enter) - Error("Recursive ThreadLock\n"); - enter = 1; -} //end of the function ThreadLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadUnlock (void) -{ - if (!threaded) - { - Error("ThreadUnlock: !threaded"); - return; - } //end if - if (!enter) - Error("ThreadUnlock without lock\n"); - enter = 0; - LeaveCriticalSection(&crit); -} //end of the function ThreadUnlock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupLock(void) -{ - Log_Print("Win32 multi-threading\n"); - InitializeCriticalSection(&crit); - threaded = true; //Stupid me... forgot this!!! - currentnumthreads = 0; - currentthreadid = 0; -} //end of the function ThreadInitLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownLock(void) -{ - DeleteCriticalSection(&crit); - threaded = false; //Stupid me... forgot this!!! -} //end of the function ThreadShutdownLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupSemaphore(void) -{ - semaphore = CreateSemaphore(NULL, 0, 99999999, "bspc"); -} //end of the function ThreadSetupSemaphore -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownSemaphore(void) -{ -} //end of the function ThreadShutdownSemaphore -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSemaphoreWait(void) -{ - WaitForSingleObject(semaphore, INFINITE); -} //end of the function ThreadSemaphoreWait -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSemaphoreIncrease(int count) -{ - ReleaseSemaphore(semaphore, count, NULL); -} //end of the function ThreadSemaphoreIncrease -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int threadid[MAX_THREADS]; - HANDLE threadhandle[MAX_THREADS]; - int i; - int start, end; - - Log_Print("Win32 multi-threading\n"); - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = true; - - if (numthreads == -1) - ThreadSetDefault (); - - if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; - // - // run threads in parallel - // - InitializeCriticalSection (&crit); - - numwaitingthreads = 0; - - if (numthreads == 1) - { // use same thread - func (0); - } //end if - else - { -// printf("starting %d threads\n", numthreads); - for (i = 0; i < numthreads; i++) - { - threadhandle[i] = CreateThread( - NULL, // LPSECURITY_ATTRIBUTES lpsa, - 0, // DWORD cbStack, - (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr, - (LPVOID)i, // LPVOID lpvThreadParm, - 0, // DWORD fdwCreate, - &threadid[i]); -// printf("started thread %d\n", i); - } //end for - - for (i = 0; i < numthreads; i++) - WaitForSingleObject (threadhandle[i], INFINITE); - } //end else - DeleteCriticalSection (&crit); - - threaded = false; - end = I_FloatTime (); - if (pacifier) printf (" (%i)\n", end-start); -} //end of the function RunThreadsOn -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AddThread(void (*func)(int)) -{ - thread_t *thread; - - if (numthreads == 1) - { - if (currentnumthreads >= numthreads) return; - currentnumthreads++; - func(-1); - currentnumthreads--; - } //end if - else - { - ThreadLock(); - if (currentnumthreads >= numthreads) - { - ThreadUnlock(); - return; - } //end if - //allocate new thread - thread = GetMemory(sizeof(thread_t)); - if (!thread) Error("can't allocate memory for thread\n"); - - // - thread->threadid = currentthreadid; - thread->handle = CreateThread( - NULL, // LPSECURITY_ATTRIBUTES lpsa, - 0, // DWORD cbStack, - (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr, - (LPVOID) thread->threadid, // LPVOID lpvThreadParm, - 0, // DWORD fdwCreate, - &thread->id); - - //add the thread to the end of the list - thread->next = NULL; - if (lastthread) lastthread->next = thread; - else firstthread = thread; - lastthread = thread; - // -#ifdef THREAD_DEBUG - qprintf("added thread with id %d\n", thread->threadid); -#endif //THREAD_DEBUG - // - currentnumthreads++; - currentthreadid++; - // - ThreadUnlock(); - } //end else -} //end of the function AddThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RemoveThread(int threadid) -{ - thread_t *thread, *last; - - //if a single thread - if (threadid == -1) return; - // - ThreadLock(); - last = NULL; - for (thread = firstthread; thread; thread = thread->next) - { - if (thread->threadid == threadid) - { - if (last) last->next = thread->next; - else firstthread = thread->next; - if (!thread->next) lastthread = last; - // - FreeMemory(thread); - currentnumthreads--; -#ifdef THREAD_DEBUG - qprintf("removed thread with id %d\n", threadid); -#endif //THREAD_DEBUG - break; - } //end if - last = thread; - } //end if - if (!thread) Error("couldn't find thread with id %d", threadid); - ThreadUnlock(); -} //end of the function RemoveThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void WaitForAllThreadsFinished(void) -{ - HANDLE handle; - - ThreadLock(); - while(firstthread) - { - handle = firstthread->handle; - ThreadUnlock(); - - WaitForSingleObject(handle, INFINITE); - - ThreadLock(); - } //end while - ThreadUnlock(); -} //end of the function WaitForAllThreadsFinished -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int GetNumThreads(void) -{ - return currentnumthreads; -} //end of the function GetNumThreads - -#endif - - -//=================================================================== -// -// OSF1 -// -//=================================================================== - -#if defined(__osf__) - -#define USED - -#include - -typedef struct thread_s -{ - pthread_t thread; - int threadid; - int id; - struct thread_s *next; -} thread_t; - -thread_t *firstthread; -thread_t *lastthread; -int currentnumthreads; -int currentthreadid; - -int numthreads = 1; -pthread_mutex_t my_mutex; -pthread_attr_t attrib; -static int enter; -static int numwaitingthreads = 0; - - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetDefault(void) -{ - if (numthreads == -1) // not set manually - { - numthreads = 1; - } //end if - qprintf("%i threads\n", numthreads); -} //end of the function ThreadSetDefault -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadLock(void) -{ - if (!threaded) - { - Error("ThreadLock: !threaded"); - return; - } //end if - if (my_mutex) - { - pthread_mutex_lock(my_mutex); - } //end if - if (enter) - Error("Recursive ThreadLock\n"); - enter = 1; -} //end of the function ThreadLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadUnlock(void) -{ - if (!threaded) - { - Error("ThreadUnlock: !threaded"); - return; - } //end if - if (!enter) - Error("ThreadUnlock without lock\n"); - enter = 0; - if (my_mutex) - { - pthread_mutex_unlock(my_mutex); - } //end if -} //end of the function ThreadUnlock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupLock(void) -{ - pthread_mutexattr_t mattrib; - - Log_Print("pthread multi-threading\n"); - - if (!my_mutex) - { - my_mutex = GetMemory(sizeof(*my_mutex)); - if (pthread_mutexattr_create (&mattrib) == -1) - Error ("pthread_mutex_attr_create failed"); - if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) - Error ("pthread_mutexattr_setkind_np failed"); - if (pthread_mutex_init (my_mutex, mattrib) == -1) - Error ("pthread_mutex_init failed"); - } - - if (pthread_attr_create (&attrib) == -1) - Error ("pthread_attr_create failed"); - if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) - Error ("pthread_attr_setstacksize failed"); - - threaded = true; - currentnumthreads = 0; - currentthreadid = 0; -} //end of the function ThreadInitLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownLock(void) -{ - threaded = false; -} //end of the function ThreadShutdownLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - pthread_t work_threads[MAX_THREADS]; - pthread_addr_t status; - pthread_attr_t attrib; - pthread_mutexattr_t mattrib; - int start, end; - - Log_Print("pthread multi-threading\n"); - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = true; - - if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; - - if (pacifier) - setbuf (stdout, NULL); - - if (!my_mutex) - { - my_mutex = GetMemory(sizeof(*my_mutex)); - if (pthread_mutexattr_create (&mattrib) == -1) - Error ("pthread_mutex_attr_create failed"); - if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) - Error ("pthread_mutexattr_setkind_np failed"); - if (pthread_mutex_init (my_mutex, mattrib) == -1) - Error ("pthread_mutex_init failed"); - } - - if (pthread_attr_create (&attrib) == -1) - Error ("pthread_attr_create failed"); - if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) - Error ("pthread_attr_setstacksize failed"); - - for (i=0 ; i= numthreads) return; - currentnumthreads++; - func(-1); - currentnumthreads--; - } //end if - else - { - ThreadLock(); - if (currentnumthreads >= numthreads) - { - ThreadUnlock(); - return; - } //end if - //allocate new thread - thread = GetMemory(sizeof(thread_t)); - if (!thread) Error("can't allocate memory for thread\n"); - // - thread->threadid = currentthreadid; - - if (pthread_create(&thread->thread, attrib, (pthread_startroutine_t)func, (pthread_addr_t)thread->threadid) == -1) - Error ("pthread_create failed"); - - //add the thread to the end of the list - thread->next = NULL; - if (lastthread) lastthread->next = thread; - else firstthread = thread; - lastthread = thread; - // -#ifdef THREAD_DEBUG - qprintf("added thread with id %d\n", thread->threadid); -#endif //THREAD_DEBUG - // - currentnumthreads++; - currentthreadid++; - // - ThreadUnlock(); - } //end else -} //end of the function AddThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RemoveThread(int threadid) -{ - thread_t *thread, *last; - - //if a single thread - if (threadid == -1) return; - // - ThreadLock(); - last = NULL; - for (thread = firstthread; thread; thread = thread->next) - { - if (thread->threadid == threadid) - { - if (last) last->next = thread->next; - else firstthread = thread->next; - if (!thread->next) lastthread = last; - // - FreeMemory(thread); - currentnumthreads--; -#ifdef THREAD_DEBUG - qprintf("removed thread with id %d\n", threadid); -#endif //THREAD_DEBUG - break; - } //end if - last = thread; - } //end if - if (!thread) Error("couldn't find thread with id %d", threadid); - ThreadUnlock(); -} //end of the function RemoveThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void WaitForAllThreadsFinished(void) -{ - pthread_t *thread; - pthread_addr_t status; - - ThreadLock(); - while(firstthread) - { - thread = &firstthread->thread; - ThreadUnlock(); - - if (pthread_join(*thread, &status) == -1) - Error("pthread_join failed"); - - ThreadLock(); - } //end while - ThreadUnlock(); -} //end of the function WaitForAllThreadsFinished -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int GetNumThreads(void) -{ - return currentnumthreads; -} //end of the function GetNumThreads - -#endif - -//=================================================================== -// -// LINUX -// -//=================================================================== - -#if defined(LINUX) - -#define USED - -#include -#include - -typedef struct thread_s -{ - pthread_t thread; - int threadid; - int id; - struct thread_s *next; -} thread_t; - -thread_t *firstthread; -thread_t *lastthread; -int currentnumthreads; -int currentthreadid; - -int numthreads = 1; -pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_attr_t attrib; -sem_t semaphore; -static int enter; -static int numwaitingthreads = 0; - - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetDefault(void) -{ - if (numthreads == -1) // not set manually - { - numthreads = 1; - } //end if - qprintf("%i threads\n", numthreads); -} //end of the function ThreadSetDefault -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadLock(void) -{ - if (!threaded) - { - Error("ThreadLock: !threaded"); - return; - } //end if - pthread_mutex_lock(&my_mutex); - if (enter) - Error("Recursive ThreadLock\n"); - enter = 1; -} //end of the function ThreadLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadUnlock(void) -{ - if (!threaded) - { - Error("ThreadUnlock: !threaded"); - return; - } //end if - if (!enter) - Error("ThreadUnlock without lock\n"); - enter = 0; - pthread_mutex_unlock(&my_mutex); -} //end of the function ThreadUnlock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupLock(void) -{ - pthread_mutexattr_t mattrib; - - Log_Print("pthread multi-threading\n"); - - threaded = true; - currentnumthreads = 0; - currentthreadid = 0; -} //end of the function ThreadInitLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownLock(void) -{ - threaded = false; -} //end of the function ThreadShutdownLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupSemaphore(void) -{ - sem_init(&semaphore, 0, 0); -} //end of the function ThreadSetupSemaphore -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownSemaphore(void) -{ - sem_destroy(&semaphore); -} //end of the function ThreadShutdownSemaphore -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSemaphoreWait(void) -{ - sem_wait(&semaphore); -} //end of the function ThreadSemaphoreWait -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSemaphoreIncrease(int count) -{ - int i; - - for (i = 0; i < count; i++) - { - sem_post(&semaphore); - } //end for -} //end of the function ThreadSemaphoreIncrease -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - pthread_t work_threads[MAX_THREADS]; - void *pthread_return; - pthread_attr_t attrib; - pthread_mutexattr_t mattrib; - int start, end; - - Log_Print("pthread multi-threading\n"); - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = true; - - if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; - - if (pacifier) - setbuf (stdout, NULL); - - for (i=0 ; i= numthreads) return; - currentnumthreads++; - func(-1); - currentnumthreads--; - } //end if - else - { - ThreadLock(); - if (currentnumthreads >= numthreads) - { - ThreadUnlock(); - return; - } //end if - //allocate new thread - thread = GetMemory(sizeof(thread_t)); - if (!thread) Error("can't allocate memory for thread\n"); - // - thread->threadid = currentthreadid; - - if (pthread_create(&thread->thread, NULL, (void *)func, (void *)thread->threadid) == -1) - Error ("pthread_create failed"); - - //add the thread to the end of the list - thread->next = NULL; - if (lastthread) lastthread->next = thread; - else firstthread = thread; - lastthread = thread; - // -#ifdef THREAD_DEBUG - qprintf("added thread with id %d\n", thread->threadid); -#endif //THREAD_DEBUG - // - currentnumthreads++; - currentthreadid++; - // - ThreadUnlock(); - } //end else -} //end of the function AddThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RemoveThread(int threadid) -{ - thread_t *thread, *last; - - //if a single thread - if (threadid == -1) return; - // - ThreadLock(); - last = NULL; - for (thread = firstthread; thread; thread = thread->next) - { - if (thread->threadid == threadid) - { - if (last) last->next = thread->next; - else firstthread = thread->next; - if (!thread->next) lastthread = last; - // - FreeMemory(thread); - currentnumthreads--; -#ifdef THREAD_DEBUG - qprintf("removed thread with id %d\n", threadid); -#endif //THREAD_DEBUG - break; - } //end if - last = thread; - } //end if - if (!thread) Error("couldn't find thread with id %d", threadid); - ThreadUnlock(); -} //end of the function RemoveThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void WaitForAllThreadsFinished(void) -{ - pthread_t *thread; - void *pthread_return; - - ThreadLock(); - while(firstthread) - { - thread = &firstthread->thread; - ThreadUnlock(); - - if (pthread_join(*thread, &pthread_return) == -1) - Error("pthread_join failed"); - - ThreadLock(); - } //end while - ThreadUnlock(); -} //end of the function WaitForAllThreadsFinished -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int GetNumThreads(void) -{ - return currentnumthreads; -} //end of the function GetNumThreads - -#endif //LINUX - - -//=================================================================== -// -// IRIX -// -//=================================================================== - -#ifdef _MIPS_ISA - -#define USED - -#include -#include -#include -#include - -typedef struct thread_s -{ - int threadid; - int id; - struct thread_s *next; -} thread_t; - -thread_t *firstthread; -thread_t *lastthread; -int currentnumthreads; -int currentthreadid; - -int numthreads = 1; -static int enter; -static int numwaitingthreads = 0; - -abilock_t lck; - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetDefault (void) -{ - if (numthreads == -1) - numthreads = prctl(PR_MAXPPROCS); - printf ("%i threads\n", numthreads); -//@@ - usconfig (CONF_INITUSERS, numthreads); -} //end of the function ThreadSetDefault -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadLock (void) -{ - spin_lock (&lck); -} //end of the function ThreadLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadUnlock (void) -{ - release_lock(&lck); -} //end of the function ThreadUnlock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupLock(void) -{ - init_lock (&lck); - - Log_Print("IRIX multi-threading\n"); - - threaded = true; - currentnumthreads = 0; - currentthreadid = 0; -} //end of the function ThreadInitLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownLock(void) -{ - threaded = false; -} //end of the function ThreadShutdownLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - int pid[MAX_THREADS]; - int start, end; - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = true; - - if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; - - if (pacifier) - setbuf (stdout, NULL); - - init_lock (&lck); - - for (i=0 ; i= numthreads) return; - currentnumthreads++; - func(-1); - currentnumthreads--; - } //end if - else - { - ThreadLock(); - if (currentnumthreads >= numthreads) - { - ThreadUnlock(); - return; - } //end if - //allocate new thread - thread = GetMemory(sizeof(thread_t)); - if (!thread) Error("can't allocate memory for thread\n"); - // - thread->threadid = currentthreadid; - - thread->id = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)thread->threadid, NULL, 0x100000); - if (thread->id == -1) - { - perror ("sproc"); - Error ("sproc failed"); - } - - //add the thread to the end of the list - thread->next = NULL; - if (lastthread) lastthread->next = thread; - else firstthread = thread; - lastthread = thread; - // -#ifdef THREAD_DEBUG - qprintf("added thread with id %d\n", thread->threadid); -#endif //THREAD_DEBUG - // - currentnumthreads++; - currentthreadid++; - // - ThreadUnlock(); - } //end else -} //end of the function AddThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RemoveThread(int threadid) -{ - thread_t *thread, *last; - - //if a single thread - if (threadid == -1) return; - // - ThreadLock(); - last = NULL; - for (thread = firstthread; thread; thread = thread->next) - { - if (thread->threadid == threadid) - { - if (last) last->next = thread->next; - else firstthread = thread->next; - if (!thread->next) lastthread = last; - // - FreeMemory(thread); - currentnumthreads--; -#ifdef THREAD_DEBUG - qprintf("removed thread with id %d\n", threadid); -#endif //THREAD_DEBUG - break; - } //end if - last = thread; - } //end if - if (!thread) Error("couldn't find thread with id %d", threadid); - ThreadUnlock(); -} //end of the function RemoveThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void WaitForAllThreadsFinished(void) -{ - ThreadLock(); - while(firstthread) - { - ThreadUnlock(); - - //wait (NULL); - - ThreadLock(); - } //end while - ThreadUnlock(); -} //end of the function WaitForAllThreadsFinished -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int GetNumThreads(void) -{ - return currentnumthreads; -} //end of the function GetNumThreads - -#endif //_MIPS_ISA - - -//======================================================================= -// -// SINGLE THREAD -// -//======================================================================= - -#ifndef USED - -int numthreads = 1; -int currentnumthreads = 0; - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetDefault(void) -{ - numthreads = 1; -} //end of the function ThreadSetDefault -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadLock(void) -{ -} //end of the function ThreadLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadUnlock(void) -{ -} //end of the function ThreadUnlock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupLock(void) -{ - Log_Print("no multi-threading\n"); -} //end of the function ThreadInitLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownLock(void) -{ -} //end of the function ThreadShutdownLock -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSetupSemaphore(void) -{ -} //end of the function ThreadSetupSemaphore -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadShutdownSemaphore(void) -{ -} //end of the function ThreadShutdownSemaphore -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSemaphoreWait(void) -{ -} //end of the function ThreadSemaphoreWait -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void ThreadSemaphoreIncrease(int count) -{ -} //end of the function ThreadSemaphoreIncrease -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int start, end; - - Log_Print("no multi-threading\n"); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - start = I_FloatTime (); -#ifdef NeXT - if (pacifier) - setbuf (stdout, NULL); -#endif - func(0); - - end = I_FloatTime (); - if (pacifier) - printf (" (%i)\n", end-start); -} //end of the function RunThreadsOn -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AddThread(void (*func)(int)) -{ - if (currentnumthreads >= numthreads) return; - currentnumthreads++; - func(-1); - currentnumthreads--; -} //end of the function AddThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RemoveThread(int threadid) -{ -} //end of the function RemoveThread -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void WaitForAllThreadsFinished(void) -{ -} //end of the function WaitForAllThreadsFinished -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int GetNumThreads(void) -{ - return currentnumthreads; -} //end of the function GetNumThreads - -#endif //USED +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "l_cmd.h" +#include "l_threads.h" +#include "l_log.h" +#include "l_mem.h" + +#define MAX_THREADS 64 + +//#define THREAD_DEBUG + +int dispatch; +int workcount; +int oldf; +qboolean pacifier; +qboolean threaded; +void (*workfunction) (int); + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +int GetThreadWork(void) +{ + int r; + int f; + + ThreadLock(); + + if (dispatch == workcount) + { + ThreadUnlock (); + return -1; + } + + f = 10*dispatch / workcount; + if (f != oldf) + { + oldf = f; + if (pacifier) + printf ("%i...", f); + } //end if + + r = dispatch; + dispatch++; + ThreadUnlock (); + + return r; +} //end of the function GetThreadWork +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadWorkerFunction(int threadnum) +{ + int work; + + while(1) + { + work = GetThreadWork (); + if (work == -1) + break; +//printf ("thread %i, work %i\n", threadnum, work); + workfunction(work); + } //end while +} //end of the function ThreadWorkerFunction +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + if (numthreads == -1) + ThreadSetDefault (); + workfunction = func; + RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); +} //end of the function RunThreadsOnIndividual + + +//=================================================================== +// +// WIN32 +// +//=================================================================== + +#if defined(WIN32) || defined(_WIN32) + +#define USED + +#include + +typedef struct thread_s +{ + HANDLE handle; + int threadid; + int id; + struct thread_s *next; +} thread_t; + +thread_t *firstthread; +thread_t *lastthread; +int currentnumthreads; +int currentthreadid; + +int numthreads = 1; +CRITICAL_SECTION crit; +HANDLE semaphore; +static int enter; +static int numwaitingthreads = 0; + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetDefault(void) +{ + SYSTEM_INFO info; + + if (numthreads == -1) // not set manually + { + GetSystemInfo (&info); + numthreads = info.dwNumberOfProcessors; + if (numthreads < 1 || numthreads > 32) + numthreads = 1; + } //end if + qprintf ("%i threads\n", numthreads); +} //end of the function ThreadSetDefault +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadLock(void) +{ + if (!threaded) + { + Error("ThreadLock: !threaded"); + return; + } //end if + EnterCriticalSection(&crit); + if (enter) + Error("Recursive ThreadLock\n"); + enter = 1; +} //end of the function ThreadLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadUnlock (void) +{ + if (!threaded) + { + Error("ThreadUnlock: !threaded"); + return; + } //end if + if (!enter) + Error("ThreadUnlock without lock\n"); + enter = 0; + LeaveCriticalSection(&crit); +} //end of the function ThreadUnlock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupLock(void) +{ + Log_Print("Win32 multi-threading\n"); + InitializeCriticalSection(&crit); + threaded = true; //Stupid me... forgot this!!! + currentnumthreads = 0; + currentthreadid = 0; +} //end of the function ThreadInitLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownLock(void) +{ + DeleteCriticalSection(&crit); + threaded = false; //Stupid me... forgot this!!! +} //end of the function ThreadShutdownLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupSemaphore(void) +{ + semaphore = CreateSemaphore(NULL, 0, 99999999, "bspc"); +} //end of the function ThreadSetupSemaphore +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownSemaphore(void) +{ +} //end of the function ThreadShutdownSemaphore +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSemaphoreWait(void) +{ + WaitForSingleObject(semaphore, INFINITE); +} //end of the function ThreadSemaphoreWait +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSemaphoreIncrease(int count) +{ + ReleaseSemaphore(semaphore, count, NULL); +} //end of the function ThreadSemaphoreIncrease +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int threadid[MAX_THREADS]; + HANDLE threadhandle[MAX_THREADS]; + int i; + int start, end; + + Log_Print("Win32 multi-threading\n"); + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (numthreads == -1) + ThreadSetDefault (); + + if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; + // + // run threads in parallel + // + InitializeCriticalSection (&crit); + + numwaitingthreads = 0; + + if (numthreads == 1) + { // use same thread + func (0); + } //end if + else + { +// printf("starting %d threads\n", numthreads); + for (i = 0; i < numthreads; i++) + { + threadhandle[i] = CreateThread( + NULL, // LPSECURITY_ATTRIBUTES lpsa, + 0, // DWORD cbStack, + (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr, + (LPVOID)i, // LPVOID lpvThreadParm, + 0, // DWORD fdwCreate, + &threadid[i]); +// printf("started thread %d\n", i); + } //end for + + for (i = 0; i < numthreads; i++) + WaitForSingleObject (threadhandle[i], INFINITE); + } //end else + DeleteCriticalSection (&crit); + + threaded = false; + end = I_FloatTime (); + if (pacifier) printf (" (%i)\n", end-start); +} //end of the function RunThreadsOn +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void AddThread(void (*func)(int)) +{ + thread_t *thread; + + if (numthreads == 1) + { + if (currentnumthreads >= numthreads) return; + currentnumthreads++; + func(-1); + currentnumthreads--; + } //end if + else + { + ThreadLock(); + if (currentnumthreads >= numthreads) + { + ThreadUnlock(); + return; + } //end if + //allocate new thread + thread = GetMemory(sizeof(thread_t)); + if (!thread) Error("can't allocate memory for thread\n"); + + // + thread->threadid = currentthreadid; + thread->handle = CreateThread( + NULL, // LPSECURITY_ATTRIBUTES lpsa, + 0, // DWORD cbStack, + (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr, + (LPVOID) thread->threadid, // LPVOID lpvThreadParm, + 0, // DWORD fdwCreate, + &thread->id); + + //add the thread to the end of the list + thread->next = NULL; + if (lastthread) lastthread->next = thread; + else firstthread = thread; + lastthread = thread; + // +#ifdef THREAD_DEBUG + qprintf("added thread with id %d\n", thread->threadid); +#endif //THREAD_DEBUG + // + currentnumthreads++; + currentthreadid++; + // + ThreadUnlock(); + } //end else +} //end of the function AddThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RemoveThread(int threadid) +{ + thread_t *thread, *last; + + //if a single thread + if (threadid == -1) return; + // + ThreadLock(); + last = NULL; + for (thread = firstthread; thread; thread = thread->next) + { + if (thread->threadid == threadid) + { + if (last) last->next = thread->next; + else firstthread = thread->next; + if (!thread->next) lastthread = last; + // + FreeMemory(thread); + currentnumthreads--; +#ifdef THREAD_DEBUG + qprintf("removed thread with id %d\n", threadid); +#endif //THREAD_DEBUG + break; + } //end if + last = thread; + } //end if + if (!thread) Error("couldn't find thread with id %d", threadid); + ThreadUnlock(); +} //end of the function RemoveThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void WaitForAllThreadsFinished(void) +{ + HANDLE handle; + + ThreadLock(); + while(firstthread) + { + handle = firstthread->handle; + ThreadUnlock(); + + WaitForSingleObject(handle, INFINITE); + + ThreadLock(); + } //end while + ThreadUnlock(); +} //end of the function WaitForAllThreadsFinished +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +int GetNumThreads(void) +{ + return currentnumthreads; +} //end of the function GetNumThreads + +#endif + + +//=================================================================== +// +// OSF1 +// +//=================================================================== + +#if defined(__osf__) + +#define USED + +#include + +typedef struct thread_s +{ + pthread_t thread; + int threadid; + int id; + struct thread_s *next; +} thread_t; + +thread_t *firstthread; +thread_t *lastthread; +int currentnumthreads; +int currentthreadid; + +int numthreads = 1; +pthread_mutex_t my_mutex; +pthread_attr_t attrib; +static int enter; +static int numwaitingthreads = 0; + + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetDefault(void) +{ + if (numthreads == -1) // not set manually + { + numthreads = 1; + } //end if + qprintf("%i threads\n", numthreads); +} //end of the function ThreadSetDefault +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadLock(void) +{ + if (!threaded) + { + Error("ThreadLock: !threaded"); + return; + } //end if + if (my_mutex) + { + pthread_mutex_lock(my_mutex); + } //end if + if (enter) + Error("Recursive ThreadLock\n"); + enter = 1; +} //end of the function ThreadLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadUnlock(void) +{ + if (!threaded) + { + Error("ThreadUnlock: !threaded"); + return; + } //end if + if (!enter) + Error("ThreadUnlock without lock\n"); + enter = 0; + if (my_mutex) + { + pthread_mutex_unlock(my_mutex); + } //end if +} //end of the function ThreadUnlock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupLock(void) +{ + pthread_mutexattr_t mattrib; + + Log_Print("pthread multi-threading\n"); + + if (!my_mutex) + { + my_mutex = GetMemory(sizeof(*my_mutex)); + if (pthread_mutexattr_create (&mattrib) == -1) + Error ("pthread_mutex_attr_create failed"); + if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) + Error ("pthread_mutexattr_setkind_np failed"); + if (pthread_mutex_init (my_mutex, mattrib) == -1) + Error ("pthread_mutex_init failed"); + } + + if (pthread_attr_create (&attrib) == -1) + Error ("pthread_attr_create failed"); + if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) + Error ("pthread_attr_setstacksize failed"); + + threaded = true; + currentnumthreads = 0; + currentthreadid = 0; +} //end of the function ThreadInitLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownLock(void) +{ + threaded = false; +} //end of the function ThreadShutdownLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int i; + pthread_t work_threads[MAX_THREADS]; + pthread_addr_t status; + pthread_attr_t attrib; + pthread_mutexattr_t mattrib; + int start, end; + + Log_Print("pthread multi-threading\n"); + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; + + if (pacifier) + setbuf (stdout, NULL); + + if (!my_mutex) + { + my_mutex = GetMemory(sizeof(*my_mutex)); + if (pthread_mutexattr_create (&mattrib) == -1) + Error ("pthread_mutex_attr_create failed"); + if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) + Error ("pthread_mutexattr_setkind_np failed"); + if (pthread_mutex_init (my_mutex, mattrib) == -1) + Error ("pthread_mutex_init failed"); + } + + if (pthread_attr_create (&attrib) == -1) + Error ("pthread_attr_create failed"); + if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) + Error ("pthread_attr_setstacksize failed"); + + for (i=0 ; i= numthreads) return; + currentnumthreads++; + func(-1); + currentnumthreads--; + } //end if + else + { + ThreadLock(); + if (currentnumthreads >= numthreads) + { + ThreadUnlock(); + return; + } //end if + //allocate new thread + thread = GetMemory(sizeof(thread_t)); + if (!thread) Error("can't allocate memory for thread\n"); + // + thread->threadid = currentthreadid; + + if (pthread_create(&thread->thread, attrib, (pthread_startroutine_t)func, (pthread_addr_t)thread->threadid) == -1) + Error ("pthread_create failed"); + + //add the thread to the end of the list + thread->next = NULL; + if (lastthread) lastthread->next = thread; + else firstthread = thread; + lastthread = thread; + // +#ifdef THREAD_DEBUG + qprintf("added thread with id %d\n", thread->threadid); +#endif //THREAD_DEBUG + // + currentnumthreads++; + currentthreadid++; + // + ThreadUnlock(); + } //end else +} //end of the function AddThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RemoveThread(int threadid) +{ + thread_t *thread, *last; + + //if a single thread + if (threadid == -1) return; + // + ThreadLock(); + last = NULL; + for (thread = firstthread; thread; thread = thread->next) + { + if (thread->threadid == threadid) + { + if (last) last->next = thread->next; + else firstthread = thread->next; + if (!thread->next) lastthread = last; + // + FreeMemory(thread); + currentnumthreads--; +#ifdef THREAD_DEBUG + qprintf("removed thread with id %d\n", threadid); +#endif //THREAD_DEBUG + break; + } //end if + last = thread; + } //end if + if (!thread) Error("couldn't find thread with id %d", threadid); + ThreadUnlock(); +} //end of the function RemoveThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void WaitForAllThreadsFinished(void) +{ + pthread_t *thread; + pthread_addr_t status; + + ThreadLock(); + while(firstthread) + { + thread = &firstthread->thread; + ThreadUnlock(); + + if (pthread_join(*thread, &status) == -1) + Error("pthread_join failed"); + + ThreadLock(); + } //end while + ThreadUnlock(); +} //end of the function WaitForAllThreadsFinished +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +int GetNumThreads(void) +{ + return currentnumthreads; +} //end of the function GetNumThreads + +#endif + +//=================================================================== +// +// LINUX +// +//=================================================================== + +#if defined(LINUX) + +#define USED + +#include +#include + +typedef struct thread_s +{ + pthread_t thread; + int threadid; + int id; + struct thread_s *next; +} thread_t; + +thread_t *firstthread; +thread_t *lastthread; +int currentnumthreads; +int currentthreadid; + +int numthreads = 1; +pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_attr_t attrib; +sem_t semaphore; +static int enter; +static int numwaitingthreads = 0; + + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetDefault(void) +{ + if (numthreads == -1) // not set manually + { + numthreads = 1; + } //end if + qprintf("%i threads\n", numthreads); +} //end of the function ThreadSetDefault +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadLock(void) +{ + if (!threaded) + { + Error("ThreadLock: !threaded"); + return; + } //end if + pthread_mutex_lock(&my_mutex); + if (enter) + Error("Recursive ThreadLock\n"); + enter = 1; +} //end of the function ThreadLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadUnlock(void) +{ + if (!threaded) + { + Error("ThreadUnlock: !threaded"); + return; + } //end if + if (!enter) + Error("ThreadUnlock without lock\n"); + enter = 0; + pthread_mutex_unlock(&my_mutex); +} //end of the function ThreadUnlock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupLock(void) +{ + pthread_mutexattr_t mattrib; + + Log_Print("pthread multi-threading\n"); + + threaded = true; + currentnumthreads = 0; + currentthreadid = 0; +} //end of the function ThreadInitLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownLock(void) +{ + threaded = false; +} //end of the function ThreadShutdownLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupSemaphore(void) +{ + sem_init(&semaphore, 0, 0); +} //end of the function ThreadSetupSemaphore +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownSemaphore(void) +{ + sem_destroy(&semaphore); +} //end of the function ThreadShutdownSemaphore +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSemaphoreWait(void) +{ + sem_wait(&semaphore); +} //end of the function ThreadSemaphoreWait +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSemaphoreIncrease(int count) +{ + int i; + + for (i = 0; i < count; i++) + { + sem_post(&semaphore); + } //end for +} //end of the function ThreadSemaphoreIncrease +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int i; + pthread_t work_threads[MAX_THREADS]; + void *pthread_return; + pthread_attr_t attrib; + pthread_mutexattr_t mattrib; + int start, end; + + Log_Print("pthread multi-threading\n"); + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; + + if (pacifier) + setbuf (stdout, NULL); + + for (i=0 ; i= numthreads) return; + currentnumthreads++; + func(-1); + currentnumthreads--; + } //end if + else + { + ThreadLock(); + if (currentnumthreads >= numthreads) + { + ThreadUnlock(); + return; + } //end if + //allocate new thread + thread = GetMemory(sizeof(thread_t)); + if (!thread) Error("can't allocate memory for thread\n"); + // + thread->threadid = currentthreadid; + + if (pthread_create(&thread->thread, NULL, (void *)func, (void *)thread->threadid) == -1) + Error ("pthread_create failed"); + + //add the thread to the end of the list + thread->next = NULL; + if (lastthread) lastthread->next = thread; + else firstthread = thread; + lastthread = thread; + // +#ifdef THREAD_DEBUG + qprintf("added thread with id %d\n", thread->threadid); +#endif //THREAD_DEBUG + // + currentnumthreads++; + currentthreadid++; + // + ThreadUnlock(); + } //end else +} //end of the function AddThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RemoveThread(int threadid) +{ + thread_t *thread, *last; + + //if a single thread + if (threadid == -1) return; + // + ThreadLock(); + last = NULL; + for (thread = firstthread; thread; thread = thread->next) + { + if (thread->threadid == threadid) + { + if (last) last->next = thread->next; + else firstthread = thread->next; + if (!thread->next) lastthread = last; + // + FreeMemory(thread); + currentnumthreads--; +#ifdef THREAD_DEBUG + qprintf("removed thread with id %d\n", threadid); +#endif //THREAD_DEBUG + break; + } //end if + last = thread; + } //end if + if (!thread) Error("couldn't find thread with id %d", threadid); + ThreadUnlock(); +} //end of the function RemoveThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void WaitForAllThreadsFinished(void) +{ + pthread_t *thread; + void *pthread_return; + + ThreadLock(); + while(firstthread) + { + thread = &firstthread->thread; + ThreadUnlock(); + + if (pthread_join(*thread, &pthread_return) == -1) + Error("pthread_join failed"); + + ThreadLock(); + } //end while + ThreadUnlock(); +} //end of the function WaitForAllThreadsFinished +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +int GetNumThreads(void) +{ + return currentnumthreads; +} //end of the function GetNumThreads + +#endif //LINUX + + +//=================================================================== +// +// IRIX +// +//=================================================================== + +#ifdef _MIPS_ISA + +#define USED + +#include +#include +#include +#include + +typedef struct thread_s +{ + int threadid; + int id; + struct thread_s *next; +} thread_t; + +thread_t *firstthread; +thread_t *lastthread; +int currentnumthreads; +int currentthreadid; + +int numthreads = 1; +static int enter; +static int numwaitingthreads = 0; + +abilock_t lck; + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetDefault (void) +{ + if (numthreads == -1) + numthreads = prctl(PR_MAXPPROCS); + printf ("%i threads\n", numthreads); +//@@ + usconfig (CONF_INITUSERS, numthreads); +} //end of the function ThreadSetDefault +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadLock (void) +{ + spin_lock (&lck); +} //end of the function ThreadLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadUnlock (void) +{ + release_lock(&lck); +} //end of the function ThreadUnlock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupLock(void) +{ + init_lock (&lck); + + Log_Print("IRIX multi-threading\n"); + + threaded = true; + currentnumthreads = 0; + currentthreadid = 0; +} //end of the function ThreadInitLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownLock(void) +{ + threaded = false; +} //end of the function ThreadShutdownLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int i; + int pid[MAX_THREADS]; + int start, end; + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1; + + if (pacifier) + setbuf (stdout, NULL); + + init_lock (&lck); + + for (i=0 ; i= numthreads) return; + currentnumthreads++; + func(-1); + currentnumthreads--; + } //end if + else + { + ThreadLock(); + if (currentnumthreads >= numthreads) + { + ThreadUnlock(); + return; + } //end if + //allocate new thread + thread = GetMemory(sizeof(thread_t)); + if (!thread) Error("can't allocate memory for thread\n"); + // + thread->threadid = currentthreadid; + + thread->id = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)thread->threadid, NULL, 0x100000); + if (thread->id == -1) + { + perror ("sproc"); + Error ("sproc failed"); + } + + //add the thread to the end of the list + thread->next = NULL; + if (lastthread) lastthread->next = thread; + else firstthread = thread; + lastthread = thread; + // +#ifdef THREAD_DEBUG + qprintf("added thread with id %d\n", thread->threadid); +#endif //THREAD_DEBUG + // + currentnumthreads++; + currentthreadid++; + // + ThreadUnlock(); + } //end else +} //end of the function AddThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RemoveThread(int threadid) +{ + thread_t *thread, *last; + + //if a single thread + if (threadid == -1) return; + // + ThreadLock(); + last = NULL; + for (thread = firstthread; thread; thread = thread->next) + { + if (thread->threadid == threadid) + { + if (last) last->next = thread->next; + else firstthread = thread->next; + if (!thread->next) lastthread = last; + // + FreeMemory(thread); + currentnumthreads--; +#ifdef THREAD_DEBUG + qprintf("removed thread with id %d\n", threadid); +#endif //THREAD_DEBUG + break; + } //end if + last = thread; + } //end if + if (!thread) Error("couldn't find thread with id %d", threadid); + ThreadUnlock(); +} //end of the function RemoveThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void WaitForAllThreadsFinished(void) +{ + ThreadLock(); + while(firstthread) + { + ThreadUnlock(); + + //wait (NULL); + + ThreadLock(); + } //end while + ThreadUnlock(); +} //end of the function WaitForAllThreadsFinished +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +int GetNumThreads(void) +{ + return currentnumthreads; +} //end of the function GetNumThreads + +#endif //_MIPS_ISA + + +//======================================================================= +// +// SINGLE THREAD +// +//======================================================================= + +#ifndef USED + +int numthreads = 1; +int currentnumthreads = 0; + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetDefault(void) +{ + numthreads = 1; +} //end of the function ThreadSetDefault +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadLock(void) +{ +} //end of the function ThreadLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadUnlock(void) +{ +} //end of the function ThreadUnlock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupLock(void) +{ + Log_Print("no multi-threading\n"); +} //end of the function ThreadInitLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownLock(void) +{ +} //end of the function ThreadShutdownLock +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSetupSemaphore(void) +{ +} //end of the function ThreadSetupSemaphore +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadShutdownSemaphore(void) +{ +} //end of the function ThreadShutdownSemaphore +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSemaphoreWait(void) +{ +} //end of the function ThreadSemaphoreWait +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void ThreadSemaphoreIncrease(int count) +{ +} //end of the function ThreadSemaphoreIncrease +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int start, end; + + Log_Print("no multi-threading\n"); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + start = I_FloatTime (); +#ifdef NeXT + if (pacifier) + setbuf (stdout, NULL); +#endif + func(0); + + end = I_FloatTime (); + if (pacifier) + printf (" (%i)\n", end-start); +} //end of the function RunThreadsOn +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void AddThread(void (*func)(int)) +{ + if (currentnumthreads >= numthreads) return; + currentnumthreads++; + func(-1); + currentnumthreads--; +} //end of the function AddThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void RemoveThread(int threadid) +{ +} //end of the function RemoveThread +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void WaitForAllThreadsFinished(void) +{ +} //end of the function WaitForAllThreadsFinished +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +int GetNumThreads(void) +{ + return currentnumthreads; +} //end of the function GetNumThreads + +#endif //USED -- cgit v1.2.3