Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_threads.c (38719B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #include "l_cmd.h"
     24 #include "l_threads.h"
     25 #include "l_log.h"
     26 #include "l_mem.h"
     27 
     28 #define	MAX_THREADS	64
     29 
     30 //#define THREAD_DEBUG
     31 
     32 int dispatch;
     33 int workcount;
     34 int oldf;
     35 qboolean pacifier;
     36 qboolean	threaded;
     37 void (*workfunction) (int);
     38 
     39 //===========================================================================
     40 //
     41 // Parameter:				-
     42 // Returns:					-
     43 // Changes Globals:		-
     44 //===========================================================================
     45 int GetThreadWork(void)
     46 {
     47 	int	r;
     48 	int	f;
     49 
     50 	ThreadLock();
     51 
     52 	if (dispatch == workcount)
     53 	{
     54 		ThreadUnlock ();
     55 		return -1;
     56 	}
     57 
     58 	f = 10*dispatch / workcount;
     59 	if (f != oldf)
     60 	{
     61 		oldf = f;
     62 		if (pacifier)
     63 			printf ("%i...", f);
     64 	} //end if
     65 
     66 	r = dispatch;
     67 	dispatch++;
     68 	ThreadUnlock ();
     69 
     70 	return r;
     71 } //end of the function GetThreadWork
     72 //===========================================================================
     73 //
     74 // Parameter:				-
     75 // Returns:					-
     76 // Changes Globals:		-
     77 //===========================================================================
     78 void ThreadWorkerFunction(int threadnum)
     79 {
     80 	int		work;
     81 
     82 	while(1)
     83 	{
     84 		work = GetThreadWork ();
     85 		if (work == -1)
     86 			break;
     87 //printf ("thread %i, work %i\n", threadnum, work);
     88 		workfunction(work);
     89 	} //end while
     90 } //end of the function ThreadWorkerFunction
     91 //===========================================================================
     92 //
     93 // Parameter:				-
     94 // Returns:					-
     95 // Changes Globals:		-
     96 //===========================================================================
     97 void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
     98 {
     99 	if (numthreads == -1)
    100 		ThreadSetDefault ();
    101 	workfunction = func;
    102 	RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
    103 } //end of the function RunThreadsOnIndividual
    104 
    105 
    106 //===================================================================
    107 //
    108 // WIN32
    109 //
    110 //===================================================================
    111 
    112 #if defined(WIN32) || defined(_WIN32)
    113 
    114 #define USED
    115 
    116 #include <windows.h>
    117 
    118 typedef struct thread_s
    119 {
    120 	HANDLE handle;
    121 	int threadid;
    122 	int id;
    123 	struct thread_s *next;
    124 } thread_t;
    125 
    126 thread_t *firstthread;
    127 thread_t *lastthread;
    128 int currentnumthreads;
    129 int currentthreadid;
    130 
    131 int numthreads = 1;
    132 CRITICAL_SECTION crit;
    133 HANDLE semaphore;
    134 static int enter;
    135 static int numwaitingthreads = 0;
    136 
    137 //===========================================================================
    138 //
    139 // Parameter:				-
    140 // Returns:					-
    141 // Changes Globals:		-
    142 //===========================================================================
    143 void ThreadSetDefault(void)
    144 {
    145 	SYSTEM_INFO info;
    146 
    147 	if (numthreads == -1)	// not set manually
    148 	{
    149 		GetSystemInfo (&info);
    150 		numthreads = info.dwNumberOfProcessors;
    151 		if (numthreads < 1 || numthreads > 32)
    152 			numthreads = 1;
    153 	} //end if
    154 	qprintf ("%i threads\n", numthreads);
    155 } //end of the function ThreadSetDefault
    156 //===========================================================================
    157 //
    158 // Parameter:				-
    159 // Returns:					-
    160 // Changes Globals:		-
    161 //===========================================================================
    162 void ThreadLock(void)
    163 {
    164 	if (!threaded)
    165 	{
    166 		Error("ThreadLock: !threaded");
    167 		return;
    168 	} //end if
    169 	EnterCriticalSection(&crit);
    170 	if (enter)
    171 		Error("Recursive ThreadLock\n");
    172 	enter = 1;
    173 } //end of the function ThreadLock
    174 //===========================================================================
    175 //
    176 // Parameter:				-
    177 // Returns:					-
    178 // Changes Globals:		-
    179 //===========================================================================
    180 void ThreadUnlock (void)
    181 {
    182 	if (!threaded)
    183 	{
    184 		Error("ThreadUnlock: !threaded");
    185 		return;
    186 	} //end if
    187 	if (!enter)
    188 		Error("ThreadUnlock without lock\n");
    189 	enter = 0;
    190 	LeaveCriticalSection(&crit);
    191 } //end of the function ThreadUnlock
    192 //===========================================================================
    193 //
    194 // Parameter:				-
    195 // Returns:					-
    196 // Changes Globals:		-
    197 //===========================================================================
    198 void ThreadSetupLock(void)
    199 {
    200 	Log_Print("Win32 multi-threading\n");
    201 	InitializeCriticalSection(&crit);
    202 	threaded = true;	//Stupid me... forgot this!!!
    203 	currentnumthreads = 0;
    204 	currentthreadid = 0;
    205 } //end of the function ThreadInitLock
    206 //===========================================================================
    207 //
    208 // Parameter:				-
    209 // Returns:					-
    210 // Changes Globals:		-
    211 //===========================================================================
    212 void ThreadShutdownLock(void)
    213 {
    214 	DeleteCriticalSection(&crit);
    215 	threaded = false;	//Stupid me... forgot this!!!
    216 } //end of the function ThreadShutdownLock
    217 //===========================================================================
    218 //
    219 // Parameter:				-
    220 // Returns:					-
    221 // Changes Globals:		-
    222 //===========================================================================
    223 void ThreadSetupSemaphore(void)
    224 {
    225 	semaphore = CreateSemaphore(NULL, 0, 99999999, "bspc");
    226 } //end of the function ThreadSetupSemaphore
    227 //===========================================================================
    228 //
    229 // Parameter:			-
    230 // Returns:				-
    231 // Changes Globals:		-
    232 //===========================================================================
    233 void ThreadShutdownSemaphore(void)
    234 {
    235 } //end of the function ThreadShutdownSemaphore
    236 //===========================================================================
    237 //
    238 // Parameter:				-
    239 // Returns:					-
    240 // Changes Globals:		-
    241 //===========================================================================
    242 void ThreadSemaphoreWait(void)
    243 {
    244 	WaitForSingleObject(semaphore, INFINITE);
    245 } //end of the function ThreadSemaphoreWait
    246 //===========================================================================
    247 //
    248 // Parameter:				-
    249 // Returns:					-
    250 // Changes Globals:		-
    251 //===========================================================================
    252 void ThreadSemaphoreIncrease(int count)
    253 {
    254 	ReleaseSemaphore(semaphore, count, NULL);
    255 } //end of the function ThreadSemaphoreIncrease
    256 //===========================================================================
    257 //
    258 // Parameter:				-
    259 // Returns:					-
    260 // Changes Globals:		-
    261 //===========================================================================
    262 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
    263 {
    264 	int		threadid[MAX_THREADS];
    265 	HANDLE	threadhandle[MAX_THREADS];
    266 	int		i;
    267 	int		start, end;
    268 
    269 	Log_Print("Win32 multi-threading\n");
    270 	start = I_FloatTime ();
    271 	dispatch = 0;
    272 	workcount = workcnt;
    273 	oldf = -1;
    274 	pacifier = showpacifier;
    275 	threaded = true;
    276 
    277 	if (numthreads == -1)
    278 		ThreadSetDefault ();
    279 
    280 	if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
    281 	//
    282 	// run threads in parallel
    283 	//
    284 	InitializeCriticalSection (&crit);
    285 
    286 	numwaitingthreads = 0;
    287 
    288 	if (numthreads == 1)
    289 	{	// use same thread
    290 		func (0);
    291 	} //end if
    292 	else
    293 	{
    294 //		printf("starting %d threads\n", numthreads);
    295 		for (i = 0; i < numthreads; i++)
    296 		{
    297 			threadhandle[i] = CreateThread(
    298 			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
    299 			   0,		// DWORD cbStack,
    300 			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
    301 			   (LPVOID)i,	// LPVOID lpvThreadParm,
    302 			   0,			//   DWORD fdwCreate,
    303 			   &threadid[i]);
    304 //			printf("started thread %d\n", i);
    305 		} //end for
    306 
    307 		for (i = 0; i < numthreads; i++)
    308 			WaitForSingleObject (threadhandle[i], INFINITE);
    309 	} //end else
    310 	DeleteCriticalSection (&crit);
    311 
    312 	threaded = false;
    313 	end = I_FloatTime ();
    314 	if (pacifier) printf (" (%i)\n", end-start);
    315 } //end of the function RunThreadsOn
    316 //===========================================================================
    317 //
    318 // Parameter:				-
    319 // Returns:					-
    320 // Changes Globals:		-
    321 //===========================================================================
    322 void AddThread(void (*func)(int))
    323 {
    324 	thread_t *thread;
    325 
    326 	if (numthreads == 1)
    327 	{
    328 		if (currentnumthreads >= numthreads) return;
    329 		currentnumthreads++;
    330 		func(-1);
    331 		currentnumthreads--;
    332 	} //end if
    333 	else
    334 	{
    335 		ThreadLock();
    336 		if (currentnumthreads >= numthreads)
    337 		{
    338 			ThreadUnlock();
    339 			return;
    340 		} //end if
    341 		//allocate new thread
    342 		thread = GetMemory(sizeof(thread_t));
    343 		if (!thread) Error("can't allocate memory for thread\n");
    344 
    345 		//
    346 		thread->threadid = currentthreadid;
    347 		thread->handle = CreateThread(
    348 				   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
    349 				   0,		// DWORD cbStack,
    350 				   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
    351 				   (LPVOID) thread->threadid,			// LPVOID lpvThreadParm,
    352 					0,						// DWORD fdwCreate,
    353 					&thread->id);
    354 
    355 		//add the thread to the end of the list
    356 		thread->next = NULL;
    357 		if (lastthread) lastthread->next = thread;
    358 		else firstthread = thread;
    359 		lastthread = thread;
    360 		//
    361 #ifdef THREAD_DEBUG
    362 		qprintf("added thread with id %d\n", thread->threadid);
    363 #endif //THREAD_DEBUG
    364 		//
    365 		currentnumthreads++;
    366 		currentthreadid++;
    367 		//
    368 		ThreadUnlock();
    369 	} //end else
    370 } //end of the function AddThread
    371 //===========================================================================
    372 //
    373 // Parameter:				-
    374 // Returns:					-
    375 // Changes Globals:		-
    376 //===========================================================================
    377 void RemoveThread(int threadid)
    378 {
    379 	thread_t *thread, *last;
    380 
    381 	//if a single thread
    382 	if (threadid == -1) return;
    383 	//
    384 	ThreadLock();
    385 	last = NULL;
    386 	for (thread = firstthread; thread; thread = thread->next)
    387 	{
    388 		if (thread->threadid == threadid)
    389 		{
    390 			if (last) last->next = thread->next;
    391 			else firstthread = thread->next;
    392 			if (!thread->next) lastthread = last;
    393 			//
    394 			FreeMemory(thread);
    395 			currentnumthreads--;
    396 #ifdef THREAD_DEBUG
    397 			qprintf("removed thread with id %d\n", threadid);
    398 #endif //THREAD_DEBUG
    399 			break;
    400 		} //end if
    401 		last = thread;
    402 	} //end if
    403 	if (!thread) Error("couldn't find thread with id %d", threadid);
    404 	ThreadUnlock();
    405 } //end of the function RemoveThread
    406 //===========================================================================
    407 //
    408 // Parameter:				-
    409 // Returns:					-
    410 // Changes Globals:		-
    411 //===========================================================================
    412 void WaitForAllThreadsFinished(void)
    413 {
    414 	HANDLE handle;
    415 
    416 	ThreadLock();
    417 	while(firstthread)
    418 	{
    419 		handle = firstthread->handle;
    420 		ThreadUnlock();
    421 
    422 		WaitForSingleObject(handle, INFINITE);
    423 
    424 		ThreadLock();
    425 	} //end while
    426 	ThreadUnlock();
    427 } //end of the function WaitForAllThreadsFinished
    428 //===========================================================================
    429 //
    430 // Parameter:				-
    431 // Returns:					-
    432 // Changes Globals:		-
    433 //===========================================================================
    434 int GetNumThreads(void)
    435 {
    436 	return currentnumthreads;
    437 } //end of the function GetNumThreads
    438 
    439 #endif
    440 
    441 
    442 //===================================================================
    443 //
    444 // OSF1
    445 //
    446 //===================================================================
    447 
    448 #if defined(__osf__)
    449 
    450 #define	USED
    451 
    452 #include <pthread.h>
    453 
    454 typedef struct thread_s
    455 {
    456 	pthread_t thread;
    457 	int threadid;
    458 	int id;
    459 	struct thread_s *next;
    460 } thread_t;
    461 
    462 thread_t *firstthread;
    463 thread_t *lastthread;
    464 int currentnumthreads;
    465 int currentthreadid;
    466 
    467 int numthreads = 1;
    468 pthread_mutex_t my_mutex;
    469 pthread_attr_t	attrib;
    470 static int enter;
    471 static int numwaitingthreads = 0;
    472 
    473 
    474 //===========================================================================
    475 //
    476 // Parameter:				-
    477 // Returns:					-
    478 // Changes Globals:		-
    479 //===========================================================================
    480 void ThreadSetDefault(void)
    481 {
    482 	if (numthreads == -1)	// not set manually
    483 	{
    484 		numthreads = 1;
    485 	} //end if
    486 	qprintf("%i threads\n", numthreads);
    487 } //end of the function ThreadSetDefault
    488 //===========================================================================
    489 //
    490 // Parameter:				-
    491 // Returns:					-
    492 // Changes Globals:		-
    493 //===========================================================================
    494 void ThreadLock(void)
    495 {
    496 	if (!threaded)
    497 	{
    498 		Error("ThreadLock: !threaded");
    499 		return;
    500 	} //end if
    501 	if (my_mutex)
    502 	{
    503 		pthread_mutex_lock(my_mutex);
    504 	} //end if
    505 	if (enter)
    506 		Error("Recursive ThreadLock\n");
    507 	enter = 1;
    508 } //end of the function ThreadLock
    509 //===========================================================================
    510 //
    511 // Parameter:				-
    512 // Returns:					-
    513 // Changes Globals:		-
    514 //===========================================================================
    515 void ThreadUnlock(void)
    516 {
    517 	if (!threaded)
    518 	{
    519 		Error("ThreadUnlock: !threaded");
    520 		return;
    521 	} //end if
    522 	if (!enter)
    523 		Error("ThreadUnlock without lock\n");
    524 	enter = 0;
    525 	if (my_mutex)
    526 	{
    527 		pthread_mutex_unlock(my_mutex);
    528 	} //end if
    529 } //end of the function ThreadUnlock
    530 //===========================================================================
    531 //
    532 // Parameter:				-
    533 // Returns:					-
    534 // Changes Globals:		-
    535 //===========================================================================
    536 void ThreadSetupLock(void)
    537 {
    538 	pthread_mutexattr_t mattrib;
    539 
    540 	Log_Print("pthread multi-threading\n");
    541 
    542 	if (!my_mutex)
    543 	{
    544 		my_mutex = GetMemory(sizeof(*my_mutex));
    545 		if (pthread_mutexattr_create (&mattrib) == -1)
    546 			Error ("pthread_mutex_attr_create failed");
    547 		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
    548 			Error ("pthread_mutexattr_setkind_np failed");
    549 		if (pthread_mutex_init (my_mutex, mattrib) == -1)
    550 			Error ("pthread_mutex_init failed");
    551 	}
    552 
    553 	if (pthread_attr_create (&attrib) == -1)
    554 		Error ("pthread_attr_create failed");
    555 	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
    556 		Error ("pthread_attr_setstacksize failed");
    557 
    558 	threaded = true;
    559 	currentnumthreads = 0;
    560 	currentthreadid = 0;
    561 } //end of the function ThreadInitLock
    562 //===========================================================================
    563 //
    564 // Parameter:				-
    565 // Returns:					-
    566 // Changes Globals:		-
    567 //===========================================================================
    568 void ThreadShutdownLock(void)
    569 {
    570 	threaded = false;
    571 } //end of the function ThreadShutdownLock
    572 //===========================================================================
    573 //
    574 // Parameter:				-
    575 // Returns:					-
    576 // Changes Globals:		-
    577 //===========================================================================
    578 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
    579 {
    580 	int		i;
    581 	pthread_t	work_threads[MAX_THREADS];
    582 	pthread_addr_t	status;
    583 	pthread_attr_t	attrib;
    584 	pthread_mutexattr_t	mattrib;
    585 	int		start, end;
    586 
    587 	Log_Print("pthread multi-threading\n");
    588 
    589 	start = I_FloatTime ();
    590 	dispatch = 0;
    591 	workcount = workcnt;
    592 	oldf = -1;
    593 	pacifier = showpacifier;
    594 	threaded = true;
    595 
    596 	if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
    597 
    598 	if (pacifier)
    599 		setbuf (stdout, NULL);
    600 
    601 	if (!my_mutex)
    602 	{
    603 		my_mutex = GetMemory(sizeof(*my_mutex));
    604 		if (pthread_mutexattr_create (&mattrib) == -1)
    605 			Error ("pthread_mutex_attr_create failed");
    606 		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
    607 			Error ("pthread_mutexattr_setkind_np failed");
    608 		if (pthread_mutex_init (my_mutex, mattrib) == -1)
    609 			Error ("pthread_mutex_init failed");
    610 	}
    611 
    612 	if (pthread_attr_create (&attrib) == -1)
    613 		Error ("pthread_attr_create failed");
    614 	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
    615 		Error ("pthread_attr_setstacksize failed");
    616 	
    617 	for (i=0 ; i<numthreads ; i++)
    618 	{
    619   		if (pthread_create(&work_threads[i], attrib
    620 		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
    621 			Error ("pthread_create failed");
    622 	}
    623 		
    624 	for (i=0 ; i<numthreads ; i++)
    625 	{
    626 		if (pthread_join (work_threads[i], &status) == -1)
    627 			Error ("pthread_join failed");
    628 	}
    629 
    630 	threaded = false;
    631 
    632 	end = I_FloatTime ();
    633 	if (pacifier)
    634 		printf (" (%i)\n", end-start);
    635 } //end of the function RunThreadsOn
    636 //===========================================================================
    637 //
    638 // Parameter:				-
    639 // Returns:					-
    640 // Changes Globals:		-
    641 //===========================================================================
    642 void AddThread(void (*func)(int))
    643 {
    644 	thread_t *thread;
    645 
    646 	if (numthreads == 1)
    647 	{
    648 		if (currentnumthreads >= numthreads) return;
    649 		currentnumthreads++;
    650 		func(-1);
    651 		currentnumthreads--;
    652 	} //end if
    653 	else
    654 	{
    655 		ThreadLock();
    656 		if (currentnumthreads >= numthreads)
    657 		{
    658 			ThreadUnlock();
    659 			return;
    660 		} //end if
    661 		//allocate new thread
    662 		thread = GetMemory(sizeof(thread_t));
    663 		if (!thread) Error("can't allocate memory for thread\n");
    664 		//
    665 		thread->threadid = currentthreadid;
    666 
    667 		if (pthread_create(&thread->thread, attrib, (pthread_startroutine_t)func, (pthread_addr_t)thread->threadid) == -1)
    668 			Error ("pthread_create failed");
    669 
    670 		//add the thread to the end of the list
    671 		thread->next = NULL;
    672 		if (lastthread) lastthread->next = thread;
    673 		else firstthread = thread;
    674 		lastthread = thread;
    675 		//
    676 #ifdef THREAD_DEBUG
    677 		qprintf("added thread with id %d\n", thread->threadid);
    678 #endif //THREAD_DEBUG
    679 		//
    680 		currentnumthreads++;
    681 		currentthreadid++;
    682 		//
    683 		ThreadUnlock();
    684 	} //end else
    685 } //end of the function AddThread
    686 //===========================================================================
    687 //
    688 // Parameter:				-
    689 // Returns:					-
    690 // Changes Globals:		-
    691 //===========================================================================
    692 void RemoveThread(int threadid)
    693 {
    694 	thread_t *thread, *last;
    695 
    696 	//if a single thread
    697 	if (threadid == -1) return;
    698 	//
    699 	ThreadLock();
    700 	last = NULL;
    701 	for (thread = firstthread; thread; thread = thread->next)
    702 	{
    703 		if (thread->threadid == threadid)
    704 		{
    705 			if (last) last->next = thread->next;
    706 			else firstthread = thread->next;
    707 			if (!thread->next) lastthread = last;
    708 			//
    709 			FreeMemory(thread);
    710 			currentnumthreads--;
    711 #ifdef THREAD_DEBUG
    712 			qprintf("removed thread with id %d\n", threadid);
    713 #endif //THREAD_DEBUG
    714 			break;
    715 		} //end if
    716 		last = thread;
    717 	} //end if
    718 	if (!thread) Error("couldn't find thread with id %d", threadid);
    719 	ThreadUnlock();
    720 } //end of the function RemoveThread
    721 //===========================================================================
    722 //
    723 // Parameter:				-
    724 // Returns:					-
    725 // Changes Globals:		-
    726 //===========================================================================
    727 void WaitForAllThreadsFinished(void)
    728 {
    729 	pthread_t *thread;
    730 	pthread_addr_t	status;
    731 
    732 	ThreadLock();
    733 	while(firstthread)
    734 	{
    735 		thread = &firstthread->thread;
    736 		ThreadUnlock();
    737 
    738 		if (pthread_join(*thread, &status) == -1)
    739 			Error("pthread_join failed");
    740 
    741 		ThreadLock();
    742 	} //end while
    743 	ThreadUnlock();
    744 } //end of the function WaitForAllThreadsFinished
    745 //===========================================================================
    746 //
    747 // Parameter:				-
    748 // Returns:					-
    749 // Changes Globals:		-
    750 //===========================================================================
    751 int GetNumThreads(void)
    752 {
    753 	return currentnumthreads;
    754 } //end of the function GetNumThreads
    755 
    756 #endif
    757 
    758 //===================================================================
    759 //
    760 // LINUX
    761 //
    762 //===================================================================
    763 
    764 #if defined(LINUX)
    765 
    766 #define	USED
    767 
    768 #include <pthread.h>
    769 #include <semaphore.h>
    770 
    771 typedef struct thread_s
    772 {
    773 	pthread_t thread;
    774 	int threadid;
    775 	int id;
    776 	struct thread_s *next;
    777 } thread_t;
    778 
    779 thread_t *firstthread;
    780 thread_t *lastthread;
    781 int currentnumthreads;
    782 int currentthreadid;
    783 
    784 int numthreads = 1;
    785 pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
    786 pthread_attr_t	attrib;
    787 sem_t semaphore;
    788 static int enter;
    789 static int numwaitingthreads = 0;
    790 
    791 
    792 //===========================================================================
    793 //
    794 // Parameter:				-
    795 // Returns:					-
    796 // Changes Globals:		-
    797 //===========================================================================
    798 void ThreadSetDefault(void)
    799 {
    800 	if (numthreads == -1)	// not set manually
    801 	{
    802 		numthreads = 1;
    803 	} //end if
    804 	qprintf("%i threads\n", numthreads);
    805 } //end of the function ThreadSetDefault
    806 //===========================================================================
    807 //
    808 // Parameter:				-
    809 // Returns:					-
    810 // Changes Globals:		-
    811 //===========================================================================
    812 void ThreadLock(void)
    813 {
    814 	if (!threaded)
    815 	{
    816 		Error("ThreadLock: !threaded");
    817 		return;
    818 	} //end if
    819 	pthread_mutex_lock(&my_mutex);
    820 	if (enter)
    821 		Error("Recursive ThreadLock\n");
    822 	enter = 1;
    823 } //end of the function ThreadLock
    824 //===========================================================================
    825 //
    826 // Parameter:				-
    827 // Returns:					-
    828 // Changes Globals:		-
    829 //===========================================================================
    830 void ThreadUnlock(void)
    831 {
    832 	if (!threaded)
    833 	{
    834 		Error("ThreadUnlock: !threaded");
    835 		return;
    836 	} //end if
    837 	if (!enter)
    838 		Error("ThreadUnlock without lock\n");
    839 	enter = 0;
    840 	pthread_mutex_unlock(&my_mutex);
    841 } //end of the function ThreadUnlock
    842 //===========================================================================
    843 //
    844 // Parameter:				-
    845 // Returns:					-
    846 // Changes Globals:		-
    847 //===========================================================================
    848 void ThreadSetupLock(void)
    849 {
    850 	pthread_mutexattr_t mattrib;
    851 
    852 	Log_Print("pthread multi-threading\n");
    853 
    854 	threaded = true;
    855 	currentnumthreads = 0;
    856 	currentthreadid = 0;
    857 } //end of the function ThreadInitLock
    858 //===========================================================================
    859 //
    860 // Parameter:				-
    861 // Returns:					-
    862 // Changes Globals:		-
    863 //===========================================================================
    864 void ThreadShutdownLock(void)
    865 {
    866 	threaded = false;
    867 } //end of the function ThreadShutdownLock
    868 //===========================================================================
    869 //
    870 // Parameter:			-
    871 // Returns:				-
    872 // Changes Globals:		-
    873 //===========================================================================
    874 void ThreadSetupSemaphore(void)
    875 {
    876 	sem_init(&semaphore, 0, 0);
    877 } //end of the function ThreadSetupSemaphore
    878 //===========================================================================
    879 //
    880 // Parameter:			-
    881 // Returns:				-
    882 // Changes Globals:		-
    883 //===========================================================================
    884 void ThreadShutdownSemaphore(void)
    885 {
    886 	sem_destroy(&semaphore);
    887 } //end of the function ThreadShutdownSemaphore
    888 //===========================================================================
    889 //
    890 // Parameter:			-
    891 // Returns:				-
    892 // Changes Globals:		-
    893 //===========================================================================
    894 void ThreadSemaphoreWait(void)
    895 {
    896 	sem_wait(&semaphore);
    897 } //end of the function ThreadSemaphoreWait
    898 //===========================================================================
    899 //
    900 // Parameter:			-
    901 // Returns:				-
    902 // Changes Globals:		-
    903 //===========================================================================
    904 void ThreadSemaphoreIncrease(int count)
    905 {
    906 	int i;
    907 
    908 	for (i = 0; i < count; i++)
    909 	{
    910 		sem_post(&semaphore);
    911 	} //end for
    912 } //end of the function ThreadSemaphoreIncrease
    913 //===========================================================================
    914 //
    915 // Parameter:				-
    916 // Returns:					-
    917 // Changes Globals:		-
    918 //===========================================================================
    919 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
    920 {
    921 	int		i;
    922 	pthread_t	work_threads[MAX_THREADS];
    923 	void *pthread_return;
    924 	pthread_attr_t	attrib;
    925 	pthread_mutexattr_t	mattrib;
    926 	int		start, end;
    927 
    928 	Log_Print("pthread multi-threading\n");
    929 
    930 	start = I_FloatTime ();
    931 	dispatch = 0;
    932 	workcount = workcnt;
    933 	oldf = -1;
    934 	pacifier = showpacifier;
    935 	threaded = true;
    936 
    937 	if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
    938 
    939 	if (pacifier)
    940 		setbuf (stdout, NULL);
    941 
    942 	for (i=0 ; i<numthreads ; i++)
    943 	{
    944 		if (pthread_create(&work_threads[i], NULL, (void *)func, (void *)i) == -1)
    945 			Error ("pthread_create failed");
    946 	}
    947 		
    948 	for (i=0 ; i<numthreads ; i++)
    949 	{
    950 		if (pthread_join(work_threads[i], &pthread_return) == -1)
    951 			Error ("pthread_join failed");
    952 	}
    953 
    954 	threaded = false;
    955 
    956 	end = I_FloatTime ();
    957 	if (pacifier)
    958 		printf (" (%i)\n", end-start);
    959 } //end of the function RunThreadsOn
    960 //===========================================================================
    961 //
    962 // Parameter:				-
    963 // Returns:					-
    964 // Changes Globals:		-
    965 //===========================================================================
    966 void AddThread(void (*func)(int))
    967 {
    968 	thread_t *thread;
    969 
    970 	if (numthreads == 1)
    971 	{
    972 		if (currentnumthreads >= numthreads) return;
    973 		currentnumthreads++;
    974 		func(-1);
    975 		currentnumthreads--;
    976 	} //end if
    977 	else
    978 	{
    979 		ThreadLock();
    980 		if (currentnumthreads >= numthreads)
    981 		{
    982 			ThreadUnlock();
    983 			return;
    984 		} //end if
    985 		//allocate new thread
    986 		thread = GetMemory(sizeof(thread_t));
    987 		if (!thread) Error("can't allocate memory for thread\n");
    988 		//
    989 		thread->threadid = currentthreadid;
    990 
    991 		if (pthread_create(&thread->thread, NULL, (void *)func, (void *)thread->threadid) == -1)
    992 			Error ("pthread_create failed");
    993 
    994 		//add the thread to the end of the list
    995 		thread->next = NULL;
    996 		if (lastthread) lastthread->next = thread;
    997 		else firstthread = thread;
    998 		lastthread = thread;
    999 		//
   1000 #ifdef THREAD_DEBUG
   1001 		qprintf("added thread with id %d\n", thread->threadid);
   1002 #endif //THREAD_DEBUG
   1003 		//
   1004 		currentnumthreads++;
   1005 		currentthreadid++;
   1006 		//
   1007 		ThreadUnlock();
   1008 	} //end else
   1009 } //end of the function AddThread
   1010 //===========================================================================
   1011 //
   1012 // Parameter:				-
   1013 // Returns:					-
   1014 // Changes Globals:		-
   1015 //===========================================================================
   1016 void RemoveThread(int threadid)
   1017 {
   1018 	thread_t *thread, *last;
   1019 
   1020 	//if a single thread
   1021 	if (threadid == -1) return;
   1022 	//
   1023 	ThreadLock();
   1024 	last = NULL;
   1025 	for (thread = firstthread; thread; thread = thread->next)
   1026 	{
   1027 		if (thread->threadid == threadid)
   1028 		{
   1029 			if (last) last->next = thread->next;
   1030 			else firstthread = thread->next;
   1031 			if (!thread->next) lastthread = last;
   1032 			//
   1033 			FreeMemory(thread);
   1034 			currentnumthreads--;
   1035 #ifdef THREAD_DEBUG
   1036 			qprintf("removed thread with id %d\n", threadid);
   1037 #endif //THREAD_DEBUG
   1038 			break;
   1039 		} //end if
   1040 		last = thread;
   1041 	} //end if
   1042 	if (!thread) Error("couldn't find thread with id %d", threadid);
   1043 	ThreadUnlock();
   1044 } //end of the function RemoveThread
   1045 //===========================================================================
   1046 //
   1047 // Parameter:				-
   1048 // Returns:					-
   1049 // Changes Globals:		-
   1050 //===========================================================================
   1051 void WaitForAllThreadsFinished(void)
   1052 {
   1053 	pthread_t *thread;
   1054 	void *pthread_return;
   1055 
   1056 	ThreadLock();
   1057 	while(firstthread)
   1058 	{
   1059 		thread = &firstthread->thread;
   1060 		ThreadUnlock();
   1061 
   1062 		if (pthread_join(*thread, &pthread_return) == -1)
   1063 			Error("pthread_join failed");
   1064 
   1065 		ThreadLock();
   1066 	} //end while
   1067 	ThreadUnlock();
   1068 } //end of the function WaitForAllThreadsFinished
   1069 //===========================================================================
   1070 //
   1071 // Parameter:				-
   1072 // Returns:					-
   1073 // Changes Globals:		-
   1074 //===========================================================================
   1075 int GetNumThreads(void)
   1076 {
   1077 	return currentnumthreads;
   1078 } //end of the function GetNumThreads
   1079 
   1080 #endif //LINUX
   1081 
   1082 
   1083 //===================================================================
   1084 //
   1085 // IRIX
   1086 //
   1087 //===================================================================
   1088 
   1089 #ifdef _MIPS_ISA 
   1090 
   1091 #define	USED
   1092 
   1093 #include <task.h>
   1094 #include <abi_mutex.h>
   1095 #include <sys/types.h>
   1096 #include <sys/prctl.h>
   1097 
   1098 typedef struct thread_s
   1099 {
   1100 	int threadid;
   1101 	int id;
   1102 	struct thread_s *next;
   1103 } thread_t;
   1104 
   1105 thread_t *firstthread;
   1106 thread_t *lastthread;
   1107 int currentnumthreads;
   1108 int currentthreadid;
   1109 
   1110 int numthreads = 1;
   1111 static int enter;
   1112 static int numwaitingthreads = 0;
   1113 
   1114 abilock_t		lck;
   1115 
   1116 //===========================================================================
   1117 //
   1118 // Parameter:				-
   1119 // Returns:					-
   1120 // Changes Globals:		-
   1121 //===========================================================================
   1122 void ThreadSetDefault (void)
   1123 {
   1124 	if (numthreads == -1)
   1125 		numthreads = prctl(PR_MAXPPROCS);
   1126 	printf ("%i threads\n", numthreads);
   1127 //@@
   1128 	usconfig (CONF_INITUSERS, numthreads);
   1129 } //end of the function ThreadSetDefault
   1130 //===========================================================================
   1131 //
   1132 // Parameter:				-
   1133 // Returns:					-
   1134 // Changes Globals:		-
   1135 //===========================================================================
   1136 void ThreadLock (void)
   1137 {
   1138 	spin_lock (&lck);
   1139 } //end of the function ThreadLock
   1140 //===========================================================================
   1141 //
   1142 // Parameter:				-
   1143 // Returns:					-
   1144 // Changes Globals:		-
   1145 //===========================================================================
   1146 void ThreadUnlock (void)
   1147 {
   1148 	release_lock(&lck);
   1149 } //end of the function ThreadUnlock
   1150 //===========================================================================
   1151 //
   1152 // Parameter:				-
   1153 // Returns:					-
   1154 // Changes Globals:		-
   1155 //===========================================================================
   1156 void ThreadSetupLock(void)
   1157 {
   1158 	init_lock (&lck);
   1159 
   1160 	Log_Print("IRIX multi-threading\n");
   1161 
   1162 	threaded = true;
   1163 	currentnumthreads = 0;
   1164 	currentthreadid = 0;
   1165 } //end of the function ThreadInitLock
   1166 //===========================================================================
   1167 //
   1168 // Parameter:				-
   1169 // Returns:					-
   1170 // Changes Globals:		-
   1171 //===========================================================================
   1172 void ThreadShutdownLock(void)
   1173 {
   1174 	threaded = false;
   1175 } //end of the function ThreadShutdownLock
   1176 //===========================================================================
   1177 //
   1178 // Parameter:				-
   1179 // Returns:					-
   1180 // Changes Globals:		-
   1181 //===========================================================================
   1182 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
   1183 {
   1184 	int		i;
   1185 	int		pid[MAX_THREADS];
   1186 	int		start, end;
   1187 
   1188 	start = I_FloatTime ();
   1189 	dispatch = 0;
   1190 	workcount = workcnt;
   1191 	oldf = -1;
   1192 	pacifier = showpacifier;
   1193 	threaded = true;
   1194 
   1195 	if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
   1196 
   1197 	if (pacifier)
   1198 		setbuf (stdout, NULL);
   1199 
   1200 	init_lock (&lck);
   1201 
   1202 	for (i=0 ; i<numthreads-1 ; i++)
   1203 	{
   1204 		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
   1205 			, NULL, 0x100000);
   1206 //		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
   1207 //			, NULL, 0x80000);
   1208 		if (pid[i] == -1)
   1209 		{
   1210 			perror ("sproc");
   1211 			Error ("sproc failed");
   1212 		}
   1213 	}
   1214 		
   1215 	func(i);
   1216 			
   1217 	for (i=0 ; i<numthreads-1 ; i++)
   1218 		wait (NULL);
   1219 
   1220 	threaded = false;
   1221 
   1222 	end = I_FloatTime ();
   1223 	if (pacifier)
   1224 		printf (" (%i)\n", end-start);
   1225 } //end of the function RunThreadsOn
   1226 //===========================================================================
   1227 //
   1228 // Parameter:				-
   1229 // Returns:					-
   1230 // Changes Globals:		-
   1231 //===========================================================================
   1232 void AddThread(void (*func)(int))
   1233 {
   1234 	thread_t *thread;
   1235 
   1236 	if (numthreads == 1)
   1237 	{
   1238 		if (currentnumthreads >= numthreads) return;
   1239 		currentnumthreads++;
   1240 		func(-1);
   1241 		currentnumthreads--;
   1242 	} //end if
   1243 	else
   1244 	{
   1245 		ThreadLock();
   1246 		if (currentnumthreads >= numthreads)
   1247 		{
   1248 			ThreadUnlock();
   1249 			return;
   1250 		} //end if
   1251 		//allocate new thread
   1252 		thread = GetMemory(sizeof(thread_t));
   1253 		if (!thread) Error("can't allocate memory for thread\n");
   1254 		//
   1255 		thread->threadid = currentthreadid;
   1256 
   1257 		thread->id = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)thread->threadid, NULL, 0x100000);
   1258 		if (thread->id == -1)
   1259 		{
   1260 			perror ("sproc");
   1261 			Error ("sproc failed");
   1262 		}
   1263 
   1264 		//add the thread to the end of the list
   1265 		thread->next = NULL;
   1266 		if (lastthread) lastthread->next = thread;
   1267 		else firstthread = thread;
   1268 		lastthread = thread;
   1269 		//
   1270 #ifdef THREAD_DEBUG
   1271 		qprintf("added thread with id %d\n", thread->threadid);
   1272 #endif //THREAD_DEBUG
   1273 		//
   1274 		currentnumthreads++;
   1275 		currentthreadid++;
   1276 		//
   1277 		ThreadUnlock();
   1278 	} //end else
   1279 } //end of the function AddThread
   1280 //===========================================================================
   1281 //
   1282 // Parameter:				-
   1283 // Returns:					-
   1284 // Changes Globals:		-
   1285 //===========================================================================
   1286 void RemoveThread(int threadid)
   1287 {
   1288 	thread_t *thread, *last;
   1289 
   1290 	//if a single thread
   1291 	if (threadid == -1) return;
   1292 	//
   1293 	ThreadLock();
   1294 	last = NULL;
   1295 	for (thread = firstthread; thread; thread = thread->next)
   1296 	{
   1297 		if (thread->threadid == threadid)
   1298 		{
   1299 			if (last) last->next = thread->next;
   1300 			else firstthread = thread->next;
   1301 			if (!thread->next) lastthread = last;
   1302 			//
   1303 			FreeMemory(thread);
   1304 			currentnumthreads--;
   1305 #ifdef THREAD_DEBUG
   1306 			qprintf("removed thread with id %d\n", threadid);
   1307 #endif //THREAD_DEBUG
   1308 			break;
   1309 		} //end if
   1310 		last = thread;
   1311 	} //end if
   1312 	if (!thread) Error("couldn't find thread with id %d", threadid);
   1313 	ThreadUnlock();
   1314 } //end of the function RemoveThread
   1315 //===========================================================================
   1316 //
   1317 // Parameter:				-
   1318 // Returns:					-
   1319 // Changes Globals:		-
   1320 //===========================================================================
   1321 void WaitForAllThreadsFinished(void)
   1322 {
   1323 	ThreadLock();
   1324 	while(firstthread)
   1325 	{
   1326 		ThreadUnlock();
   1327 
   1328 		//wait (NULL);
   1329 
   1330 		ThreadLock();
   1331 	} //end while
   1332 	ThreadUnlock();
   1333 } //end of the function WaitForAllThreadsFinished
   1334 //===========================================================================
   1335 //
   1336 // Parameter:				-
   1337 // Returns:					-
   1338 // Changes Globals:		-
   1339 //===========================================================================
   1340 int GetNumThreads(void)
   1341 {
   1342 	return currentnumthreads;
   1343 } //end of the function GetNumThreads
   1344 
   1345 #endif //_MIPS_ISA
   1346 
   1347 
   1348 //=======================================================================
   1349 //
   1350 // SINGLE THREAD
   1351 //
   1352 //=======================================================================
   1353 
   1354 #ifndef USED
   1355 
   1356 int numthreads = 1;
   1357 int currentnumthreads = 0;
   1358 
   1359 //===========================================================================
   1360 //
   1361 // Parameter:				-
   1362 // Returns:					-
   1363 // Changes Globals:		-
   1364 //===========================================================================
   1365 void ThreadSetDefault(void)
   1366 {
   1367 	numthreads = 1;
   1368 } //end of the function ThreadSetDefault
   1369 //===========================================================================
   1370 //
   1371 // Parameter:				-
   1372 // Returns:					-
   1373 // Changes Globals:		-
   1374 //===========================================================================
   1375 void ThreadLock(void)
   1376 {
   1377 } //end of the function ThreadLock
   1378 //===========================================================================
   1379 //
   1380 // Parameter:				-
   1381 // Returns:					-
   1382 // Changes Globals:		-
   1383 //===========================================================================
   1384 void ThreadUnlock(void)
   1385 {
   1386 } //end of the function ThreadUnlock
   1387 //===========================================================================
   1388 //
   1389 // Parameter:				-
   1390 // Returns:					-
   1391 // Changes Globals:		-
   1392 //===========================================================================
   1393 void ThreadSetupLock(void)
   1394 {
   1395 	Log_Print("no multi-threading\n");
   1396 } //end of the function ThreadInitLock
   1397 //===========================================================================
   1398 //
   1399 // Parameter:				-
   1400 // Returns:					-
   1401 // Changes Globals:		-
   1402 //===========================================================================
   1403 void ThreadShutdownLock(void)
   1404 {
   1405 } //end of the function ThreadShutdownLock
   1406 //===========================================================================
   1407 //
   1408 // Parameter:				-
   1409 // Returns:					-
   1410 // Changes Globals:		-
   1411 //===========================================================================
   1412 void ThreadSetupSemaphore(void)
   1413 {
   1414 } //end of the function ThreadSetupSemaphore
   1415 //===========================================================================
   1416 //
   1417 // Parameter:			-
   1418 // Returns:				-
   1419 // Changes Globals:		-
   1420 //===========================================================================
   1421 void ThreadShutdownSemaphore(void)
   1422 {
   1423 } //end of the function ThreadShutdownSemaphore
   1424 //===========================================================================
   1425 //
   1426 // Parameter:				-
   1427 // Returns:					-
   1428 // Changes Globals:		-
   1429 //===========================================================================
   1430 void ThreadSemaphoreWait(void)
   1431 {
   1432 } //end of the function ThreadSemaphoreWait
   1433 //===========================================================================
   1434 //
   1435 // Parameter:				-
   1436 // Returns:					-
   1437 // Changes Globals:		-
   1438 //===========================================================================
   1439 void ThreadSemaphoreIncrease(int count)
   1440 {
   1441 } //end of the function ThreadSemaphoreIncrease
   1442 //===========================================================================
   1443 //
   1444 // Parameter:				-
   1445 // Returns:					-
   1446 // Changes Globals:		-
   1447 //===========================================================================
   1448 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
   1449 {
   1450 	int start, end;
   1451 
   1452 	Log_Print("no multi-threading\n");
   1453 	dispatch = 0;
   1454 	workcount = workcnt;
   1455 	oldf = -1;
   1456 	pacifier = showpacifier;
   1457 	start = I_FloatTime (); 
   1458 #ifdef NeXT
   1459 	if (pacifier)
   1460 		setbuf (stdout, NULL);
   1461 #endif
   1462 	func(0);
   1463 
   1464 	end = I_FloatTime ();
   1465 	if (pacifier)
   1466 		printf (" (%i)\n", end-start);
   1467 } //end of the function RunThreadsOn
   1468 //===========================================================================
   1469 //
   1470 // Parameter:				-
   1471 // Returns:					-
   1472 // Changes Globals:		-
   1473 //===========================================================================
   1474 void AddThread(void (*func)(int))
   1475 {
   1476 	if (currentnumthreads >= numthreads) return;
   1477 	currentnumthreads++;
   1478 	func(-1);
   1479 	currentnumthreads--;
   1480 } //end of the function AddThread
   1481 //===========================================================================
   1482 //
   1483 // Parameter:				-
   1484 // Returns:					-
   1485 // Changes Globals:		-
   1486 //===========================================================================
   1487 void RemoveThread(int threadid)
   1488 {
   1489 } //end of the function RemoveThread
   1490 //===========================================================================
   1491 //
   1492 // Parameter:				-
   1493 // Returns:					-
   1494 // Changes Globals:		-
   1495 //===========================================================================
   1496 void WaitForAllThreadsFinished(void)
   1497 {
   1498 } //end of the function WaitForAllThreadsFinished
   1499 //===========================================================================
   1500 //
   1501 // Parameter:				-
   1502 // Returns:					-
   1503 // Changes Globals:		-
   1504 //===========================================================================
   1505 int GetNumThreads(void)
   1506 {
   1507 	return currentnumthreads;
   1508 } //end of the function GetNumThreads
   1509 
   1510 #endif //USED