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