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