/* =========================================================================== Return to Castle Wolfenstein single player GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”). RTCW SP 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 3 of the License, or (at your option) any later version. RTCW SP 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 RTCW SP Source Code. If not, see . In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ //=========================================================================== // // Name: l_threads.c // Function: multi-threading // Programmer: Mr Elusive (MrElusive@demigod.demon.nl) // Last update: 1999-05-14 // Tab Size: 3 //=========================================================================== #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 ; i++ ) { if ( pthread_create( &work_threads[i], attrib , (pthread_startroutine_t)func, (pthread_addr_t)i ) == -1 ) { Error( "pthread_create failed" ); } } for ( i = 0 ; i < numthreads ; i++ ) { if ( pthread_join( work_threads[i], &status ) == -1 ) { Error( "pthread_join failed" ); } } 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; 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 ; i++ ) { if ( pthread_create( &work_threads[i], NULL, (void *)func, (void *)i ) == -1 ) { Error( "pthread_create failed" ); } } for ( i = 0 ; i < numthreads ; i++ ) { if ( pthread_join( work_threads[i], &pthread_return ) == -1 ) { Error( "pthread_join failed" ); } } 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; 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 - 1 ; i++ ) { pid[i] = sprocsp( ( void( * ) ( void *, size_t ) )func, PR_SALL, (void *)i , NULL, 0x100000 ); // pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i // , NULL, 0x80000); if ( pid[i] == -1 ) { perror( "sproc" ); Error( "sproc failed" ); } } func( i ); for ( i = 0 ; i < numthreads - 1 ; i++ ) wait( NULL ); 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->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