00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "l_cmd.h"
00024 #include "l_threads.h"
00025 #include "l_log.h"
00026 #include "l_mem.h"
00027
00028 #define MAX_THREADS 64
00029
00030
00031
00032 int dispatch;
00033 int workcount;
00034 int oldf;
00035 qboolean pacifier;
00036 qboolean threaded;
00037 void (*workfunction) (int);
00038
00039
00040
00041
00042
00043
00044
00045 int GetThreadWork(void)
00046 {
00047 int r;
00048 int f;
00049
00050 ThreadLock();
00051
00052 if (dispatch == workcount)
00053 {
00054 ThreadUnlock ();
00055 return -1;
00056 }
00057
00058 f = 10*dispatch / workcount;
00059 if (f != oldf)
00060 {
00061 oldf = f;
00062 if (pacifier)
00063 printf ("%i...", f);
00064 }
00065
00066 r = dispatch;
00067 dispatch++;
00068 ThreadUnlock ();
00069
00070 return r;
00071 }
00072
00073
00074
00075
00076
00077
00078 void ThreadWorkerFunction(int threadnum)
00079 {
00080 int work;
00081
00082 while(1)
00083 {
00084 work = GetThreadWork ();
00085 if (work == -1)
00086 break;
00087
00088 workfunction(work);
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097 void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
00098 {
00099 if (numthreads == -1)
00100 ThreadSetDefault ();
00101 workfunction = func;
00102 RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 #if defined(WIN32) || defined(_WIN32)
00113
00114 #define USED
00115
00116 #include <windows.h>
00117
00118 typedef struct thread_s
00119 {
00120 HANDLE handle;
00121 int threadid;
00122 int id;
00123 struct thread_s *next;
00124 } thread_t;
00125
00126 thread_t *firstthread;
00127 thread_t *lastthread;
00128 int currentnumthreads;
00129 int currentthreadid;
00130
00131 int numthreads = 1;
00132 CRITICAL_SECTION crit;
00133 HANDLE semaphore;
00134 static int enter;
00135 static int numwaitingthreads = 0;
00136
00137
00138
00139
00140
00141
00142
00143 void ThreadSetDefault(void)
00144 {
00145 SYSTEM_INFO info;
00146
00147 if (numthreads == -1)
00148 {
00149 GetSystemInfo (&info);
00150 numthreads = info.dwNumberOfProcessors;
00151 if (numthreads < 1 || numthreads > 32)
00152 numthreads = 1;
00153 }
00154 qprintf ("%i threads\n", numthreads);
00155 }
00156
00157
00158
00159
00160
00161
00162 void ThreadLock(void)
00163 {
00164 if (!threaded)
00165 {
00166 Error("ThreadLock: !threaded");
00167 return;
00168 }
00169 EnterCriticalSection(&crit);
00170 if (enter)
00171 Error("Recursive ThreadLock\n");
00172 enter = 1;
00173 }
00174
00175
00176
00177
00178
00179
00180 void ThreadUnlock (void)
00181 {
00182 if (!threaded)
00183 {
00184 Error("ThreadUnlock: !threaded");
00185 return;
00186 }
00187 if (!enter)
00188 Error("ThreadUnlock without lock\n");
00189 enter = 0;
00190 LeaveCriticalSection(&crit);
00191 }
00192
00193
00194
00195
00196
00197
00198 void ThreadSetupLock(void)
00199 {
00200 Log_Print("Win32 multi-threading\n");
00201 InitializeCriticalSection(&crit);
00202 threaded = true;
00203 currentnumthreads = 0;
00204 currentthreadid = 0;
00205 }
00206
00207
00208
00209
00210
00211
00212 void ThreadShutdownLock(void)
00213 {
00214 DeleteCriticalSection(&crit);
00215 threaded = false;
00216 }
00217
00218
00219
00220
00221
00222
00223 void ThreadSetupSemaphore(void)
00224 {
00225 semaphore = CreateSemaphore(NULL, 0, 99999999, "bspc");
00226 }
00227
00228
00229
00230
00231
00232
00233 void ThreadShutdownSemaphore(void)
00234 {
00235 }
00236
00237
00238
00239
00240
00241
00242 void ThreadSemaphoreWait(void)
00243 {
00244 WaitForSingleObject(semaphore, INFINITE);
00245 }
00246
00247
00248
00249
00250
00251
00252 void ThreadSemaphoreIncrease(int count)
00253 {
00254 ReleaseSemaphore(semaphore, count, NULL);
00255 }
00256
00257
00258
00259
00260
00261
00262 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
00263 {
00264 int threadid[MAX_THREADS];
00265 HANDLE threadhandle[MAX_THREADS];
00266 int i;
00267 int start, end;
00268
00269 Log_Print("Win32 multi-threading\n");
00270 start = I_FloatTime ();
00271 dispatch = 0;
00272 workcount = workcnt;
00273 oldf = -1;
00274 pacifier = showpacifier;
00275 threaded = true;
00276
00277 if (numthreads == -1)
00278 ThreadSetDefault ();
00279
00280 if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
00281
00282
00283
00284 InitializeCriticalSection (&crit);
00285
00286 numwaitingthreads = 0;
00287
00288 if (numthreads == 1)
00289 {
00290 func (0);
00291 }
00292 else
00293 {
00294
00295 for (i = 0; i < numthreads; i++)
00296 {
00297 threadhandle[i] = CreateThread(
00298 NULL,
00299 0,
00300 (LPTHREAD_START_ROUTINE)func,
00301 (LPVOID)i,
00302 0,
00303 &threadid[i]);
00304
00305 }
00306
00307 for (i = 0; i < numthreads; i++)
00308 WaitForSingleObject (threadhandle[i], INFINITE);
00309 }
00310 DeleteCriticalSection (&crit);
00311
00312 threaded = false;
00313 end = I_FloatTime ();
00314 if (pacifier) printf (" (%i)\n", end-start);
00315 }
00316
00317
00318
00319
00320
00321
00322 void AddThread(void (*func)(int))
00323 {
00324 thread_t *thread;
00325
00326 if (numthreads == 1)
00327 {
00328 if (currentnumthreads >= numthreads) return;
00329 currentnumthreads++;
00330 func(-1);
00331 currentnumthreads--;
00332 }
00333 else
00334 {
00335 ThreadLock();
00336 if (currentnumthreads >= numthreads)
00337 {
00338 ThreadUnlock();
00339 return;
00340 }
00341
00342 thread = GetMemory(sizeof(thread_t));
00343 if (!thread) Error("can't allocate memory for thread\n");
00344
00345
00346 thread->threadid = currentthreadid;
00347 thread->handle = CreateThread(
00348 NULL,
00349 0,
00350 (LPTHREAD_START_ROUTINE)func,
00351 (LPVOID) thread->threadid,
00352 0,
00353 &thread->id);
00354
00355
00356 thread->next = NULL;
00357 if (lastthread) lastthread->next = thread;
00358 else firstthread = thread;
00359 lastthread = thread;
00360
00361 #ifdef THREAD_DEBUG
00362 qprintf("added thread with id %d\n", thread->threadid);
00363 #endif //THREAD_DEBUG
00364
00365 currentnumthreads++;
00366 currentthreadid++;
00367
00368 ThreadUnlock();
00369 }
00370 }
00371
00372
00373
00374
00375
00376
00377 void RemoveThread(int threadid)
00378 {
00379 thread_t *thread, *last;
00380
00381
00382 if (threadid == -1) return;
00383
00384 ThreadLock();
00385 last = NULL;
00386 for (thread = firstthread; thread; thread = thread->next)
00387 {
00388 if (thread->threadid == threadid)
00389 {
00390 if (last) last->next = thread->next;
00391 else firstthread = thread->next;
00392 if (!thread->next) lastthread = last;
00393
00394 FreeMemory(thread);
00395 currentnumthreads--;
00396 #ifdef THREAD_DEBUG
00397 qprintf("removed thread with id %d\n", threadid);
00398 #endif //THREAD_DEBUG
00399 break;
00400 }
00401 last = thread;
00402 }
00403 if (!thread) Error("couldn't find thread with id %d", threadid);
00404 ThreadUnlock();
00405 }
00406
00407
00408
00409
00410
00411
00412 void WaitForAllThreadsFinished(void)
00413 {
00414 HANDLE handle;
00415
00416 ThreadLock();
00417 while(firstthread)
00418 {
00419 handle = firstthread->handle;
00420 ThreadUnlock();
00421
00422 WaitForSingleObject(handle, INFINITE);
00423
00424 ThreadLock();
00425 }
00426 ThreadUnlock();
00427 }
00428
00429
00430
00431
00432
00433
00434 int GetNumThreads(void)
00435 {
00436 return currentnumthreads;
00437 }
00438
00439 #endif
00440
00441
00442
00443
00444
00445
00446
00447
00448 #if defined(__osf__)
00449
00450 #define USED
00451
00452 #include <pthread.h>
00453
00454 typedef struct thread_s
00455 {
00456 pthread_t thread;
00457 int threadid;
00458 int id;
00459 struct thread_s *next;
00460 } thread_t;
00461
00462 thread_t *firstthread;
00463 thread_t *lastthread;
00464 int currentnumthreads;
00465 int currentthreadid;
00466
00467 int numthreads = 1;
00468 pthread_mutex_t my_mutex;
00469 pthread_attr_t attrib;
00470 static int enter;
00471 static int numwaitingthreads = 0;
00472
00473
00474
00475
00476
00477
00478
00479
00480 void ThreadSetDefault(void)
00481 {
00482 if (numthreads == -1)
00483 {
00484 numthreads = 1;
00485 }
00486 qprintf("%i threads\n", numthreads);
00487 }
00488
00489
00490
00491
00492
00493
00494 void ThreadLock(void)
00495 {
00496 if (!threaded)
00497 {
00498 Error("ThreadLock: !threaded");
00499 return;
00500 }
00501 if (my_mutex)
00502 {
00503 pthread_mutex_lock(my_mutex);
00504 }
00505 if (enter)
00506 Error("Recursive ThreadLock\n");
00507 enter = 1;
00508 }
00509
00510
00511
00512
00513
00514
00515 void ThreadUnlock(void)
00516 {
00517 if (!threaded)
00518 {
00519 Error("ThreadUnlock: !threaded");
00520 return;
00521 }
00522 if (!enter)
00523 Error("ThreadUnlock without lock\n");
00524 enter = 0;
00525 if (my_mutex)
00526 {
00527 pthread_mutex_unlock(my_mutex);
00528 }
00529 }
00530
00531
00532
00533
00534
00535
00536 void ThreadSetupLock(void)
00537 {
00538 pthread_mutexattr_t mattrib;
00539
00540 Log_Print("pthread multi-threading\n");
00541
00542 if (!my_mutex)
00543 {
00544 my_mutex = GetMemory(sizeof(*my_mutex));
00545 if (pthread_mutexattr_create (&mattrib) == -1)
00546 Error ("pthread_mutex_attr_create failed");
00547 if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
00548 Error ("pthread_mutexattr_setkind_np failed");
00549 if (pthread_mutex_init (my_mutex, mattrib) == -1)
00550 Error ("pthread_mutex_init failed");
00551 }
00552
00553 if (pthread_attr_create (&attrib) == -1)
00554 Error ("pthread_attr_create failed");
00555 if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
00556 Error ("pthread_attr_setstacksize failed");
00557
00558 threaded = true;
00559 currentnumthreads = 0;
00560 currentthreadid = 0;
00561 }
00562
00563
00564
00565
00566
00567
00568 void ThreadShutdownLock(void)
00569 {
00570 threaded = false;
00571 }
00572
00573
00574
00575
00576
00577
00578 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
00579 {
00580 int i;
00581 pthread_t work_threads[MAX_THREADS];
00582 pthread_addr_t status;
00583 pthread_attr_t attrib;
00584 pthread_mutexattr_t mattrib;
00585 int start, end;
00586
00587 Log_Print("pthread multi-threading\n");
00588
00589 start = I_FloatTime ();
00590 dispatch = 0;
00591 workcount = workcnt;
00592 oldf = -1;
00593 pacifier = showpacifier;
00594 threaded = true;
00595
00596 if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
00597
00598 if (pacifier)
00599 setbuf (stdout, NULL);
00600
00601 if (!my_mutex)
00602 {
00603 my_mutex = GetMemory(sizeof(*my_mutex));
00604 if (pthread_mutexattr_create (&mattrib) == -1)
00605 Error ("pthread_mutex_attr_create failed");
00606 if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
00607 Error ("pthread_mutexattr_setkind_np failed");
00608 if (pthread_mutex_init (my_mutex, mattrib) == -1)
00609 Error ("pthread_mutex_init failed");
00610 }
00611
00612 if (pthread_attr_create (&attrib) == -1)
00613 Error ("pthread_attr_create failed");
00614 if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
00615 Error ("pthread_attr_setstacksize failed");
00616
00617 for (i=0 ; i<numthreads ; i++)
00618 {
00619 if (pthread_create(&work_threads[i], attrib
00620 , (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
00621 Error ("pthread_create failed");
00622 }
00623
00624 for (i=0 ; i<numthreads ; i++)
00625 {
00626 if (pthread_join (work_threads[i], &status) == -1)
00627 Error ("pthread_join failed");
00628 }
00629
00630 threaded = false;
00631
00632 end = I_FloatTime ();
00633 if (pacifier)
00634 printf (" (%i)\n", end-start);
00635 }
00636
00637
00638
00639
00640
00641
00642 void AddThread(void (*func)(int))
00643 {
00644 thread_t *thread;
00645
00646 if (numthreads == 1)
00647 {
00648 if (currentnumthreads >= numthreads) return;
00649 currentnumthreads++;
00650 func(-1);
00651 currentnumthreads--;
00652 }
00653 else
00654 {
00655 ThreadLock();
00656 if (currentnumthreads >= numthreads)
00657 {
00658 ThreadUnlock();
00659 return;
00660 }
00661
00662 thread = GetMemory(sizeof(thread_t));
00663 if (!thread) Error("can't allocate memory for thread\n");
00664
00665 thread->threadid = currentthreadid;
00666
00667 if (pthread_create(&thread->thread, attrib, (pthread_startroutine_t)func, (pthread_addr_t)thread->threadid) == -1)
00668 Error ("pthread_create failed");
00669
00670
00671 thread->next = NULL;
00672 if (lastthread) lastthread->next = thread;
00673 else firstthread = thread;
00674 lastthread = thread;
00675
00676 #ifdef THREAD_DEBUG
00677 qprintf("added thread with id %d\n", thread->threadid);
00678 #endif //THREAD_DEBUG
00679
00680 currentnumthreads++;
00681 currentthreadid++;
00682
00683 ThreadUnlock();
00684 }
00685 }
00686
00687
00688
00689
00690
00691
00692 void RemoveThread(int threadid)
00693 {
00694 thread_t *thread, *last;
00695
00696
00697 if (threadid == -1) return;
00698
00699 ThreadLock();
00700 last = NULL;
00701 for (thread = firstthread; thread; thread = thread->next)
00702 {
00703 if (thread->threadid == threadid)
00704 {
00705 if (last) last->next = thread->next;
00706 else firstthread = thread->next;
00707 if (!thread->next) lastthread = last;
00708
00709 FreeMemory(thread);
00710 currentnumthreads--;
00711 #ifdef THREAD_DEBUG
00712 qprintf("removed thread with id %d\n", threadid);
00713 #endif //THREAD_DEBUG
00714 break;
00715 }
00716 last = thread;
00717 }
00718 if (!thread) Error("couldn't find thread with id %d", threadid);
00719 ThreadUnlock();
00720 }
00721
00722
00723
00724
00725
00726
00727 void WaitForAllThreadsFinished(void)
00728 {
00729 pthread_t *thread;
00730 pthread_addr_t status;
00731
00732 ThreadLock();
00733 while(firstthread)
00734 {
00735 thread = &firstthread->thread;
00736 ThreadUnlock();
00737
00738 if (pthread_join(*thread, &status) == -1)
00739 Error("pthread_join failed");
00740
00741 ThreadLock();
00742 }
00743 ThreadUnlock();
00744 }
00745
00746
00747
00748
00749
00750
00751 int GetNumThreads(void)
00752 {
00753 return currentnumthreads;
00754 }
00755
00756 #endif
00757
00758
00759
00760
00761
00762
00763
00764 #if defined(LINUX)
00765
00766 #define USED
00767
00768 #include <pthread.h>
00769 #include <semaphore.h>
00770
00771 typedef struct thread_s
00772 {
00773 pthread_t thread;
00774 int threadid;
00775 int id;
00776 struct thread_s *next;
00777 } thread_t;
00778
00779 thread_t *firstthread;
00780 thread_t *lastthread;
00781 int currentnumthreads;
00782 int currentthreadid;
00783
00784 int numthreads = 1;
00785 pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
00786 pthread_attr_t attrib;
00787 sem_t semaphore;
00788 static int enter;
00789 static int numwaitingthreads = 0;
00790
00791
00792
00793
00794
00795
00796
00797
00798 void ThreadSetDefault(void)
00799 {
00800 if (numthreads == -1)
00801 {
00802 numthreads = 1;
00803 }
00804 qprintf("%i threads\n", numthreads);
00805 }
00806
00807
00808
00809
00810
00811
00812 void ThreadLock(void)
00813 {
00814 if (!threaded)
00815 {
00816 Error("ThreadLock: !threaded");
00817 return;
00818 }
00819 pthread_mutex_lock(&my_mutex);
00820 if (enter)
00821 Error("Recursive ThreadLock\n");
00822 enter = 1;
00823 }
00824
00825
00826
00827
00828
00829
00830 void ThreadUnlock(void)
00831 {
00832 if (!threaded)
00833 {
00834 Error("ThreadUnlock: !threaded");
00835 return;
00836 }
00837 if (!enter)
00838 Error("ThreadUnlock without lock\n");
00839 enter = 0;
00840 pthread_mutex_unlock(&my_mutex);
00841 }
00842
00843
00844
00845
00846
00847
00848 void ThreadSetupLock(void)
00849 {
00850 pthread_mutexattr_t mattrib;
00851
00852 Log_Print("pthread multi-threading\n");
00853
00854 threaded = true;
00855 currentnumthreads = 0;
00856 currentthreadid = 0;
00857 }
00858
00859
00860
00861
00862
00863
00864 void ThreadShutdownLock(void)
00865 {
00866 threaded = false;
00867 }
00868
00869
00870
00871
00872
00873
00874 void ThreadSetupSemaphore(void)
00875 {
00876 sem_init(&semaphore, 0, 0);
00877 }
00878
00879
00880
00881
00882
00883
00884 void ThreadShutdownSemaphore(void)
00885 {
00886 sem_destroy(&semaphore);
00887 }
00888
00889
00890
00891
00892
00893
00894 void ThreadSemaphoreWait(void)
00895 {
00896 sem_wait(&semaphore);
00897 }
00898
00899
00900
00901
00902
00903
00904 void ThreadSemaphoreIncrease(int count)
00905 {
00906 int i;
00907
00908 for (i = 0; i < count; i++)
00909 {
00910 sem_post(&semaphore);
00911 }
00912 }
00913
00914
00915
00916
00917
00918
00919 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
00920 {
00921 int i;
00922 pthread_t work_threads[MAX_THREADS];
00923 void *pthread_return;
00924 pthread_attr_t attrib;
00925 pthread_mutexattr_t mattrib;
00926 int start, end;
00927
00928 Log_Print("pthread multi-threading\n");
00929
00930 start = I_FloatTime ();
00931 dispatch = 0;
00932 workcount = workcnt;
00933 oldf = -1;
00934 pacifier = showpacifier;
00935 threaded = true;
00936
00937 if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
00938
00939 if (pacifier)
00940 setbuf (stdout, NULL);
00941
00942 for (i=0 ; i<numthreads ; i++)
00943 {
00944 if (pthread_create(&work_threads[i], NULL, (void *)func, (void *)i) == -1)
00945 Error ("pthread_create failed");
00946 }
00947
00948 for (i=0 ; i<numthreads ; i++)
00949 {
00950 if (pthread_join(work_threads[i], &pthread_return) == -1)
00951 Error ("pthread_join failed");
00952 }
00953
00954 threaded = false;
00955
00956 end = I_FloatTime ();
00957 if (pacifier)
00958 printf (" (%i)\n", end-start);
00959 }
00960
00961
00962
00963
00964
00965
00966 void AddThread(void (*func)(int))
00967 {
00968 thread_t *thread;
00969
00970 if (numthreads == 1)
00971 {
00972 if (currentnumthreads >= numthreads) return;
00973 currentnumthreads++;
00974 func(-1);
00975 currentnumthreads--;
00976 }
00977 else
00978 {
00979 ThreadLock();
00980 if (currentnumthreads >= numthreads)
00981 {
00982 ThreadUnlock();
00983 return;
00984 }
00985
00986 thread = GetMemory(sizeof(thread_t));
00987 if (!thread) Error("can't allocate memory for thread\n");
00988
00989 thread->threadid = currentthreadid;
00990
00991 if (pthread_create(&thread->thread, NULL, (void *)func, (void *)thread->threadid) == -1)
00992 Error ("pthread_create failed");
00993
00994
00995 thread->next = NULL;
00996 if (lastthread) lastthread->next = thread;
00997 else firstthread = thread;
00998 lastthread = thread;
00999
01000 #ifdef THREAD_DEBUG
01001 qprintf("added thread with id %d\n", thread->threadid);
01002 #endif //THREAD_DEBUG
01003
01004 currentnumthreads++;
01005 currentthreadid++;
01006
01007 ThreadUnlock();
01008 }
01009 }
01010
01011
01012
01013
01014
01015
01016 void RemoveThread(int threadid)
01017 {
01018 thread_t *thread, *last;
01019
01020
01021 if (threadid == -1) return;
01022
01023 ThreadLock();
01024 last = NULL;
01025 for (thread = firstthread; thread; thread = thread->next)
01026 {
01027 if (thread->threadid == threadid)
01028 {
01029 if (last) last->next = thread->next;
01030 else firstthread = thread->next;
01031 if (!thread->next) lastthread = last;
01032
01033 FreeMemory(thread);
01034 currentnumthreads--;
01035 #ifdef THREAD_DEBUG
01036 qprintf("removed thread with id %d\n", threadid);
01037 #endif //THREAD_DEBUG
01038 break;
01039 }
01040 last = thread;
01041 }
01042 if (!thread) Error("couldn't find thread with id %d", threadid);
01043 ThreadUnlock();
01044 }
01045
01046
01047
01048
01049
01050
01051 void WaitForAllThreadsFinished(void)
01052 {
01053 pthread_t *thread;
01054 void *pthread_return;
01055
01056 ThreadLock();
01057 while(firstthread)
01058 {
01059 thread = &firstthread->thread;
01060 ThreadUnlock();
01061
01062 if (pthread_join(*thread, &pthread_return) == -1)
01063 Error("pthread_join failed");
01064
01065 ThreadLock();
01066 }
01067 ThreadUnlock();
01068 }
01069
01070
01071
01072
01073
01074
01075 int GetNumThreads(void)
01076 {
01077 return currentnumthreads;
01078 }
01079
01080 #endif //LINUX
01081
01082
01083
01084
01085
01086
01087
01088
01089 #ifdef _MIPS_ISA
01090
01091 #define USED
01092
01093 #include <task.h>
01094 #include <abi_mutex.h>
01095 #include <sys/types.h>
01096 #include <sys/prctl.h>
01097
01098 typedef struct thread_s
01099 {
01100 int threadid;
01101 int id;
01102 struct thread_s *next;
01103 } thread_t;
01104
01105 thread_t *firstthread;
01106 thread_t *lastthread;
01107 int currentnumthreads;
01108 int currentthreadid;
01109
01110 int numthreads = 1;
01111 static int enter;
01112 static int numwaitingthreads = 0;
01113
01114 abilock_t lck;
01115
01116
01117
01118
01119
01120
01121
01122 void ThreadSetDefault (void)
01123 {
01124 if (numthreads == -1)
01125 numthreads = prctl(PR_MAXPPROCS);
01126 printf ("%i threads\n", numthreads);
01127
01128 usconfig (CONF_INITUSERS, numthreads);
01129 }
01130
01131
01132
01133
01134
01135
01136 void ThreadLock (void)
01137 {
01138 spin_lock (&lck);
01139 }
01140
01141
01142
01143
01144
01145
01146 void ThreadUnlock (void)
01147 {
01148 release_lock(&lck);
01149 }
01150
01151
01152
01153
01154
01155
01156 void ThreadSetupLock(void)
01157 {
01158 init_lock (&lck);
01159
01160 Log_Print("IRIX multi-threading\n");
01161
01162 threaded = true;
01163 currentnumthreads = 0;
01164 currentthreadid = 0;
01165 }
01166
01167
01168
01169
01170
01171
01172 void ThreadShutdownLock(void)
01173 {
01174 threaded = false;
01175 }
01176
01177
01178
01179
01180
01181
01182 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
01183 {
01184 int i;
01185 int pid[MAX_THREADS];
01186 int start, end;
01187
01188 start = I_FloatTime ();
01189 dispatch = 0;
01190 workcount = workcnt;
01191 oldf = -1;
01192 pacifier = showpacifier;
01193 threaded = true;
01194
01195 if (numthreads < 1 || numthreads > MAX_THREADS) numthreads = 1;
01196
01197 if (pacifier)
01198 setbuf (stdout, NULL);
01199
01200 init_lock (&lck);
01201
01202 for (i=0 ; i<numthreads-1 ; i++)
01203 {
01204 pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
01205 , NULL, 0x100000);
01206
01207
01208 if (pid[i] == -1)
01209 {
01210 perror ("sproc");
01211 Error ("sproc failed");
01212 }
01213 }
01214
01215 func(i);
01216
01217 for (i=0 ; i<numthreads-1 ; i++)
01218 wait (NULL);
01219
01220 threaded = false;
01221
01222 end = I_FloatTime ();
01223 if (pacifier)
01224 printf (" (%i)\n", end-start);
01225 }
01226
01227
01228
01229
01230
01231
01232 void AddThread(void (*func)(int))
01233 {
01234 thread_t *thread;
01235
01236 if (numthreads == 1)
01237 {
01238 if (currentnumthreads >= numthreads) return;
01239 currentnumthreads++;
01240 func(-1);
01241 currentnumthreads--;
01242 }
01243 else
01244 {
01245 ThreadLock();
01246 if (currentnumthreads >= numthreads)
01247 {
01248 ThreadUnlock();
01249 return;
01250 }
01251
01252 thread = GetMemory(sizeof(thread_t));
01253 if (!thread) Error("can't allocate memory for thread\n");
01254
01255 thread->threadid = currentthreadid;
01256
01257 thread->id = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)thread->threadid, NULL, 0x100000);
01258 if (thread->id == -1)
01259 {
01260 perror ("sproc");
01261 Error ("sproc failed");
01262 }
01263
01264
01265 thread->next = NULL;
01266 if (lastthread) lastthread->next = thread;
01267 else firstthread = thread;
01268 lastthread = thread;
01269
01270 #ifdef THREAD_DEBUG
01271 qprintf("added thread with id %d\n", thread->threadid);
01272 #endif //THREAD_DEBUG
01273
01274 currentnumthreads++;
01275 currentthreadid++;
01276
01277 ThreadUnlock();
01278 }
01279 }
01280
01281
01282
01283
01284
01285
01286 void RemoveThread(int threadid)
01287 {
01288 thread_t *thread, *last;
01289
01290
01291 if (threadid == -1) return;
01292
01293 ThreadLock();
01294 last = NULL;
01295 for (thread = firstthread; thread; thread = thread->next)
01296 {
01297 if (thread->threadid == threadid)
01298 {
01299 if (last) last->next = thread->next;
01300 else firstthread = thread->next;
01301 if (!thread->next) lastthread = last;
01302
01303 FreeMemory(thread);
01304 currentnumthreads--;
01305 #ifdef THREAD_DEBUG
01306 qprintf("removed thread with id %d\n", threadid);
01307 #endif //THREAD_DEBUG
01308 break;
01309 }
01310 last = thread;
01311 }
01312 if (!thread) Error("couldn't find thread with id %d", threadid);
01313 ThreadUnlock();
01314 }
01315
01316
01317
01318
01319
01320
01321 void WaitForAllThreadsFinished(void)
01322 {
01323 ThreadLock();
01324 while(firstthread)
01325 {
01326 ThreadUnlock();
01327
01328
01329
01330 ThreadLock();
01331 }
01332 ThreadUnlock();
01333 }
01334
01335
01336
01337
01338
01339
01340 int GetNumThreads(void)
01341 {
01342 return currentnumthreads;
01343 }
01344
01345 #endif //_MIPS_ISA
01346
01347
01348
01349
01350
01351
01352
01353
01354 #ifndef USED
01355
01356 int numthreads = 1;
01357 int currentnumthreads = 0;
01358
01359
01360
01361
01362
01363
01364
01365 void ThreadSetDefault(void)
01366 {
01367 numthreads = 1;
01368 }
01369
01370
01371
01372
01373
01374
01375 void ThreadLock(void)
01376 {
01377 }
01378
01379
01380
01381
01382
01383
01384 void ThreadUnlock(void)
01385 {
01386 }
01387
01388
01389
01390
01391
01392
01393 void ThreadSetupLock(void)
01394 {
01395 Log_Print("no multi-threading\n");
01396 }
01397
01398
01399
01400
01401
01402
01403 void ThreadShutdownLock(void)
01404 {
01405 }
01406
01407
01408
01409
01410
01411
01412 void ThreadSetupSemaphore(void)
01413 {
01414 }
01415
01416
01417
01418
01419
01420
01421 void ThreadShutdownSemaphore(void)
01422 {
01423 }
01424
01425
01426
01427
01428
01429
01430 void ThreadSemaphoreWait(void)
01431 {
01432 }
01433
01434
01435
01436
01437
01438
01439 void ThreadSemaphoreIncrease(int count)
01440 {
01441 }
01442
01443
01444
01445
01446
01447
01448 void RunThreadsOn(int workcnt, qboolean showpacifier, void(*func)(int))
01449 {
01450 int start, end;
01451
01452 Log_Print("no multi-threading\n");
01453 dispatch = 0;
01454 workcount = workcnt;
01455 oldf = -1;
01456 pacifier = showpacifier;
01457 start = I_FloatTime ();
01458 #ifdef NeXT
01459 if (pacifier)
01460 setbuf (stdout, NULL);
01461 #endif
01462 func(0);
01463
01464 end = I_FloatTime ();
01465 if (pacifier)
01466 printf (" (%i)\n", end-start);
01467 }
01468
01469
01470
01471
01472
01473
01474 void AddThread(void (*func)(int))
01475 {
01476 if (currentnumthreads >= numthreads) return;
01477 currentnumthreads++;
01478 func(-1);
01479 currentnumthreads--;
01480 }
01481
01482
01483
01484
01485
01486
01487 void RemoveThread(int threadid)
01488 {
01489 }
01490
01491
01492
01493
01494
01495
01496 void WaitForAllThreadsFinished(void)
01497 {
01498 }
01499
01500
01501
01502
01503
01504
01505 int GetNumThreads(void)
01506 {
01507 return currentnumthreads;
01508 }
01509
01510 #endif //USED