Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

threads.c (7661B)


      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 "cmdlib.h"
     24 #include "threads.h"
     25 
     26 #define	MAX_THREADS	64
     27 
     28 int		dispatch;
     29 int		workcount;
     30 int		oldf;
     31 qboolean		pacifier;
     32 
     33 qboolean	threaded;
     34 
     35 /*
     36 =============
     37 GetThreadWork
     38 
     39 =============
     40 */
     41 int	GetThreadWork (void)
     42 {
     43 	int	r;
     44 	int	f;
     45 
     46 	ThreadLock ();
     47 
     48 	if (dispatch == workcount)
     49 	{
     50 		ThreadUnlock ();
     51 		return -1;
     52 	}
     53 
     54 	f = 10*dispatch / workcount;
     55 	if (f != oldf)
     56 	{
     57 		oldf = f;
     58 		if (pacifier)
     59 			_printf ("%i...", f);
     60 	}
     61 
     62 	r = dispatch;
     63 	dispatch++;
     64 	ThreadUnlock ();
     65 
     66 	return r;
     67 }
     68 
     69 
     70 void (*workfunction) (int);
     71 
     72 void ThreadWorkerFunction (int threadnum)
     73 {
     74 	int		work;
     75 
     76 	while (1)
     77 	{
     78 		work = GetThreadWork ();
     79 		if (work == -1)
     80 			break;
     81 //_printf ("thread %i, work %i\n", threadnum, work);
     82 		workfunction(work);
     83 	}
     84 }
     85 
     86 void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
     87 {
     88 	if (numthreads == -1)
     89 		ThreadSetDefault ();
     90 	workfunction = func;
     91 	RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
     92 }
     93 
     94 
     95 /*
     96 ===================================================================
     97 
     98 WIN32
     99 
    100 ===================================================================
    101 */
    102 #ifdef WIN32
    103 
    104 #define	USED
    105 
    106 #include <windows.h>
    107 
    108 int		numthreads = -1;
    109 CRITICAL_SECTION		crit;
    110 static int enter;
    111 
    112 void ThreadSetDefault (void)
    113 {
    114 	SYSTEM_INFO info;
    115 
    116 	if (numthreads == -1)	// not set manually
    117 	{
    118 		GetSystemInfo (&info);
    119 		numthreads = info.dwNumberOfProcessors;
    120 		if (numthreads < 1 || numthreads > 32)
    121 			numthreads = 1;
    122 	}
    123 
    124 	qprintf ("%i threads\n", numthreads);
    125 }
    126 
    127 
    128 void ThreadLock (void)
    129 {
    130 	if (!threaded)
    131 		return;
    132 	EnterCriticalSection (&crit);
    133 	if (enter)
    134 		Error ("Recursive ThreadLock\n");
    135 	enter = 1;
    136 }
    137 
    138 void ThreadUnlock (void)
    139 {
    140 	if (!threaded)
    141 		return;
    142 	if (!enter)
    143 		Error ("ThreadUnlock without lock\n");
    144 	enter = 0;
    145 	LeaveCriticalSection (&crit);
    146 }
    147 
    148 /*
    149 =============
    150 RunThreadsOn
    151 =============
    152 */
    153 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
    154 {
    155 	int		threadid[MAX_THREADS];
    156 	HANDLE	threadhandle[MAX_THREADS];
    157 	int		i;
    158 	int		start, end;
    159 
    160 	start = I_FloatTime ();
    161 	dispatch = 0;
    162 	workcount = workcnt;
    163 	oldf = -1;
    164 	pacifier = showpacifier;
    165 	threaded = qtrue;
    166 
    167 	//
    168 	// run threads in parallel
    169 	//
    170 	InitializeCriticalSection (&crit);
    171 
    172 	if (numthreads == 1)
    173 	{	// use same thread
    174 		func (0);
    175 	}
    176 	else
    177 	{
    178 		for (i=0 ; i<numthreads ; i++)
    179 		{
    180 			threadhandle[i] = CreateThread(
    181 			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
    182 			   0,		// DWORD cbStack,
    183 			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
    184 			   (LPVOID)i,	// LPVOID lpvThreadParm,
    185 			   0,			//   DWORD fdwCreate,
    186 			   &threadid[i]);
    187 		}
    188 
    189 		for (i=0 ; i<numthreads ; i++)
    190 			WaitForSingleObject (threadhandle[i], INFINITE);
    191 	}
    192 	DeleteCriticalSection (&crit);
    193 
    194 	threaded = qfalse;
    195 	end = I_FloatTime ();
    196 	if (pacifier)
    197 		_printf (" (%i)\n", end-start);
    198 }
    199 
    200 
    201 #endif
    202 
    203 /*
    204 ===================================================================
    205 
    206 OSF1
    207 
    208 ===================================================================
    209 */
    210 
    211 #ifdef __osf__
    212 #define	USED
    213 
    214 int		numthreads = 4;
    215 
    216 void ThreadSetDefault (void)
    217 {
    218 	if (numthreads == -1)	// not set manually
    219 	{
    220 		numthreads = 4;
    221 	}
    222 }
    223 
    224 
    225 #include <pthread.h>
    226 
    227 pthread_mutex_t	*my_mutex;
    228 
    229 void ThreadLock (void)
    230 {
    231 	if (my_mutex)
    232 		pthread_mutex_lock (my_mutex);
    233 }
    234 
    235 void ThreadUnlock (void)
    236 {
    237 	if (my_mutex)
    238 		pthread_mutex_unlock (my_mutex);
    239 }
    240 
    241 
    242 /*
    243 =============
    244 RunThreadsOn
    245 =============
    246 */
    247 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
    248 {
    249 	int		i;
    250 	pthread_t	work_threads[MAX_THREADS];
    251 	pthread_addr_t	status;
    252 	pthread_attr_t	attrib;
    253 	pthread_mutexattr_t	mattrib;
    254 	int		start, end;
    255 
    256 	start = I_FloatTime ();
    257 	dispatch = 0;
    258 	workcount = workcnt;
    259 	oldf = -1;
    260 	pacifier = showpacifier;
    261 	threaded = qtrue;
    262 
    263 	if (pacifier)
    264 		setbuf (stdout, NULL);
    265 
    266 	if (!my_mutex)
    267 	{
    268 		my_mutex = malloc (sizeof(*my_mutex));
    269 		if (pthread_mutexattr_create (&mattrib) == -1)
    270 			Error ("pthread_mutex_attr_create failed");
    271 		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
    272 			Error ("pthread_mutexattr_setkind_np failed");
    273 		if (pthread_mutex_init (my_mutex, mattrib) == -1)
    274 			Error ("pthread_mutex_init failed");
    275 	}
    276 
    277 	if (pthread_attr_create (&attrib) == -1)
    278 		Error ("pthread_attr_create failed");
    279 	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
    280 		Error ("pthread_attr_setstacksize failed");
    281 	
    282 	for (i=0 ; i<numthreads ; i++)
    283 	{
    284   		if (pthread_create(&work_threads[i], attrib
    285 		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
    286 			Error ("pthread_create failed");
    287 	}
    288 		
    289 	for (i=0 ; i<numthreads ; i++)
    290 	{
    291 		if (pthread_join (work_threads[i], &status) == -1)
    292 			Error ("pthread_join failed");
    293 	}
    294 
    295 	threaded = qfalse;
    296 
    297 	end = I_FloatTime ();
    298 	if (pacifier)
    299 		_printf (" (%i)\n", end-start);
    300 }
    301 
    302 
    303 #endif
    304 
    305 /*
    306 ===================================================================
    307 
    308 IRIX
    309 
    310 ===================================================================
    311 */
    312 
    313 #ifdef _MIPS_ISA 
    314 #define	USED
    315 
    316 #include <task.h>
    317 #include <abi_mutex.h>
    318 #include <sys/types.h>
    319 #include <sys/prctl.h>
    320 
    321 
    322 int		numthreads = -1;
    323 abilock_t		lck;
    324 
    325 void ThreadSetDefault (void)
    326 {
    327 	if (numthreads == -1)
    328 		numthreads = prctl(PR_MAXPPROCS);
    329 	_printf ("%i threads\n", numthreads);
    330 	usconfig (CONF_INITUSERS, numthreads);
    331 }
    332 
    333 
    334 void ThreadLock (void)
    335 {
    336 	spin_lock (&lck);
    337 }
    338 
    339 void ThreadUnlock (void)
    340 {
    341 	release_lock (&lck);
    342 }
    343 
    344 
    345 /*
    346 =============
    347 RunThreadsOn
    348 =============
    349 */
    350 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
    351 {
    352 	int		i;
    353 	int		pid[MAX_THREADS];
    354 	int		start, end;
    355 
    356 	start = I_FloatTime ();
    357 	dispatch = 0;
    358 	workcount = workcnt;
    359 	oldf = -1;
    360 	pacifier = showpacifier;
    361 	threaded = qtrue;
    362 
    363 	if (pacifier)
    364 		setbuf (stdout, NULL);
    365 
    366 	init_lock (&lck);
    367 
    368 	for (i=0 ; i<numthreads-1 ; i++)
    369 	{
    370 		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
    371 			, NULL, 0x200000);		// 2 meg stacks
    372 		if (pid[i] == -1)
    373 		{
    374 			perror ("sproc");
    375 			Error ("sproc failed");
    376 		}
    377 	}
    378 		
    379 	func(i);
    380 			
    381 	for (i=0 ; i<numthreads-1 ; i++)
    382 		wait (NULL);
    383 
    384 	threaded = qfalse;
    385 
    386 	end = I_FloatTime ();
    387 	if (pacifier)
    388 		_printf (" (%i)\n", end-start);
    389 }
    390 
    391 
    392 #endif
    393 
    394 /*
    395 =======================================================================
    396 
    397   SINGLE THREAD
    398 
    399 =======================================================================
    400 */
    401 
    402 #ifndef USED
    403 
    404 int		numthreads = 1;
    405 
    406 void ThreadSetDefault (void)
    407 {
    408 	numthreads = 1;
    409 }
    410 
    411 void ThreadLock (void)
    412 {
    413 }
    414 
    415 void ThreadUnlock (void)
    416 {
    417 }
    418 
    419 /*
    420 =============
    421 RunThreadsOn
    422 =============
    423 */
    424 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
    425 {
    426 	int		i;
    427 	int		start, end;
    428 
    429 	dispatch = 0;
    430 	workcount = workcnt;
    431 	oldf = -1;
    432 	pacifier = showpacifier;
    433 	start = I_FloatTime (); 
    434 	func(0);
    435 
    436 	end = I_FloatTime ();
    437 	if (pacifier)
    438 		_printf (" (%i)\n", end-start);
    439 }
    440 
    441 #endif