Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

l_threads.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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 //#define THREAD_DEBUG
00031 
00032 int dispatch;
00033 int workcount;
00034 int oldf;
00035 qboolean pacifier;
00036 qboolean    threaded;
00037 void (*workfunction) (int);
00038 
00039 //===========================================================================
00040 //
00041 // Parameter:               -
00042 // Returns:                 -
00043 // Changes Globals:     -
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     } //end if
00065 
00066     r = dispatch;
00067     dispatch++;
00068     ThreadUnlock ();
00069 
00070     return r;
00071 } //end of the function GetThreadWork
00072 //===========================================================================
00073 //
00074 // Parameter:               -
00075 // Returns:                 -
00076 // Changes Globals:     -
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 //printf ("thread %i, work %i\n", threadnum, work);
00088         workfunction(work);
00089     } //end while
00090 } //end of the function ThreadWorkerFunction
00091 //===========================================================================
00092 //
00093 // Parameter:               -
00094 // Returns:                 -
00095 // Changes Globals:     -
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 } //end of the function RunThreadsOnIndividual
00104 
00105 
00106 //===================================================================
00107 //
00108 // WIN32
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 // Parameter:               -
00140 // Returns:                 -
00141 // Changes Globals:     -
00142 //===========================================================================
00143 void ThreadSetDefault(void)
00144 {
00145     SYSTEM_INFO info;
00146 
00147     if (numthreads == -1)   // not set manually
00148     {
00149         GetSystemInfo (&info);
00150         numthreads = info.dwNumberOfProcessors;
00151         if (numthreads < 1 || numthreads > 32)
00152             numthreads = 1;
00153     } //end if
00154     qprintf ("%i threads\n", numthreads);
00155 } //end of the function ThreadSetDefault
00156 //===========================================================================
00157 //
00158 // Parameter:               -
00159 // Returns:                 -
00160 // Changes Globals:     -
00161 //===========================================================================
00162 void ThreadLock(void)
00163 {
00164     if (!threaded)
00165     {
00166         Error("ThreadLock: !threaded");
00167         return;
00168     } //end if
00169     EnterCriticalSection(&crit);
00170     if (enter)
00171         Error("Recursive ThreadLock\n");
00172     enter = 1;
00173 } //end of the function ThreadLock
00174 //===========================================================================
00175 //
00176 // Parameter:               -
00177 // Returns:                 -
00178 // Changes Globals:     -
00179 //===========================================================================
00180 void ThreadUnlock (void)
00181 {
00182     if (!threaded)
00183     {
00184         Error("ThreadUnlock: !threaded");
00185         return;
00186     } //end if
00187     if (!enter)
00188         Error("ThreadUnlock without lock\n");
00189     enter = 0;
00190     LeaveCriticalSection(&crit);
00191 } //end of the function ThreadUnlock
00192 //===========================================================================
00193 //
00194 // Parameter:               -
00195 // Returns:                 -
00196 // Changes Globals:     -
00197 //===========================================================================
00198 void ThreadSetupLock(void)
00199 {
00200     Log_Print("Win32 multi-threading\n");
00201     InitializeCriticalSection(&crit);
00202     threaded = true;    //Stupid me... forgot this!!!
00203     currentnumthreads = 0;
00204     currentthreadid = 0;
00205 } //end of the function ThreadInitLock
00206 //===========================================================================
00207 //
00208 // Parameter:               -
00209 // Returns:                 -
00210 // Changes Globals:     -
00211 //===========================================================================
00212 void ThreadShutdownLock(void)
00213 {
00214     DeleteCriticalSection(&crit);
00215     threaded = false;   //Stupid me... forgot this!!!
00216 } //end of the function ThreadShutdownLock
00217 //===========================================================================
00218 //
00219 // Parameter:               -
00220 // Returns:                 -
00221 // Changes Globals:     -
00222 //===========================================================================
00223 void ThreadSetupSemaphore(void)
00224 {
00225     semaphore = CreateSemaphore(NULL, 0, 99999999, "bspc");
00226 } //end of the function ThreadSetupSemaphore
00227 //===========================================================================
00228 //
00229 // Parameter:           -
00230 // Returns:             -
00231 // Changes Globals:     -
00232 //===========================================================================
00233 void ThreadShutdownSemaphore(void)
00234 {
00235 } //end of the function ThreadShutdownSemaphore
00236 //===========================================================================
00237 //
00238 // Parameter:               -
00239 // Returns:                 -
00240 // Changes Globals:     -
00241 //===========================================================================
00242 void ThreadSemaphoreWait(void)
00243 {
00244     WaitForSingleObject(semaphore, INFINITE);
00245 } //end of the function ThreadSemaphoreWait
00246 //===========================================================================
00247 //
00248 // Parameter:               -
00249 // Returns:                 -
00250 // Changes Globals:     -
00251 //===========================================================================
00252 void ThreadSemaphoreIncrease(int count)
00253 {
00254     ReleaseSemaphore(semaphore, count, NULL);
00255 } //end of the function ThreadSemaphoreIncrease
00256 //===========================================================================
00257 //
00258 // Parameter:               -
00259 // Returns:                 -
00260 // Changes Globals:     -
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     // run threads in parallel
00283     //
00284     InitializeCriticalSection (&crit);
00285 
00286     numwaitingthreads = 0;
00287 
00288     if (numthreads == 1)
00289     {   // use same thread
00290         func (0);
00291     } //end if
00292     else
00293     {
00294 //      printf("starting %d threads\n", numthreads);
00295         for (i = 0; i < numthreads; i++)
00296         {
00297             threadhandle[i] = CreateThread(
00298                NULL,    // LPSECURITY_ATTRIBUTES lpsa,
00299                0,       // DWORD cbStack,
00300                (LPTHREAD_START_ROUTINE)func,    // LPTHREAD_START_ROUTINE lpStartAddr,
00301                (LPVOID)i,   // LPVOID lpvThreadParm,
00302                0,           //   DWORD fdwCreate,
00303                &threadid[i]);
00304 //          printf("started thread %d\n", i);
00305         } //end for
00306 
00307         for (i = 0; i < numthreads; i++)
00308             WaitForSingleObject (threadhandle[i], INFINITE);
00309     } //end else
00310     DeleteCriticalSection (&crit);
00311 
00312     threaded = false;
00313     end = I_FloatTime ();
00314     if (pacifier) printf (" (%i)\n", end-start);
00315 } //end of the function RunThreadsOn
00316 //===========================================================================
00317 //
00318 // Parameter:               -
00319 // Returns:                 -
00320 // Changes Globals:     -
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     } //end if
00333     else
00334     {
00335         ThreadLock();
00336         if (currentnumthreads >= numthreads)
00337         {
00338             ThreadUnlock();
00339             return;
00340         } //end if
00341         //allocate new thread
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,    // LPSECURITY_ATTRIBUTES lpsa,
00349                    0,       // DWORD cbStack,
00350                    (LPTHREAD_START_ROUTINE)func,    // LPTHREAD_START_ROUTINE lpStartAddr,
00351                    (LPVOID) thread->threadid,           // LPVOID lpvThreadParm,
00352                     0,                      // DWORD fdwCreate,
00353                     &thread->id);
00354 
00355         //add the thread to the end of the list
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     } //end else
00370 } //end of the function AddThread
00371 //===========================================================================
00372 //
00373 // Parameter:               -
00374 // Returns:                 -
00375 // Changes Globals:     -
00376 //===========================================================================
00377 void RemoveThread(int threadid)
00378 {
00379     thread_t *thread, *last;
00380 
00381     //if a single thread
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         } //end if
00401         last = thread;
00402     } //end if
00403     if (!thread) Error("couldn't find thread with id %d", threadid);
00404     ThreadUnlock();
00405 } //end of the function RemoveThread
00406 //===========================================================================
00407 //
00408 // Parameter:               -
00409 // Returns:                 -
00410 // Changes Globals:     -
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     } //end while
00426     ThreadUnlock();
00427 } //end of the function WaitForAllThreadsFinished
00428 //===========================================================================
00429 //
00430 // Parameter:               -
00431 // Returns:                 -
00432 // Changes Globals:     -
00433 //===========================================================================
00434 int GetNumThreads(void)
00435 {
00436     return currentnumthreads;
00437 } //end of the function GetNumThreads
00438 
00439 #endif
00440 
00441 
00442 //===================================================================
00443 //
00444 // OSF1
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 // Parameter:               -
00477 // Returns:                 -
00478 // Changes Globals:     -
00479 //===========================================================================
00480 void ThreadSetDefault(void)
00481 {
00482     if (numthreads == -1)   // not set manually
00483     {
00484         numthreads = 1;
00485     } //end if
00486     qprintf("%i threads\n", numthreads);
00487 } //end of the function ThreadSetDefault
00488 //===========================================================================
00489 //
00490 // Parameter:               -
00491 // Returns:                 -
00492 // Changes Globals:     -
00493 //===========================================================================
00494 void ThreadLock(void)
00495 {
00496     if (!threaded)
00497     {
00498         Error("ThreadLock: !threaded");
00499         return;
00500     } //end if
00501     if (my_mutex)
00502     {
00503         pthread_mutex_lock(my_mutex);
00504     } //end if
00505     if (enter)
00506         Error("Recursive ThreadLock\n");
00507     enter = 1;
00508 } //end of the function ThreadLock
00509 //===========================================================================
00510 //
00511 // Parameter:               -
00512 // Returns:                 -
00513 // Changes Globals:     -
00514 //===========================================================================
00515 void ThreadUnlock(void)
00516 {
00517     if (!threaded)
00518     {
00519         Error("ThreadUnlock: !threaded");
00520         return;
00521     } //end if
00522     if (!enter)
00523         Error("ThreadUnlock without lock\n");
00524     enter = 0;
00525     if (my_mutex)
00526     {
00527         pthread_mutex_unlock(my_mutex);
00528     } //end if
00529 } //end of the function ThreadUnlock
00530 //===========================================================================
00531 //
00532 // Parameter:               -
00533 // Returns:                 -
00534 // Changes Globals:     -
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 } //end of the function ThreadInitLock
00562 //===========================================================================
00563 //
00564 // Parameter:               -
00565 // Returns:                 -
00566 // Changes Globals:     -
00567 //===========================================================================
00568 void ThreadShutdownLock(void)
00569 {
00570     threaded = false;
00571 } //end of the function ThreadShutdownLock
00572 //===========================================================================
00573 //
00574 // Parameter:               -
00575 // Returns:                 -
00576 // Changes Globals:     -
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 } //end of the function RunThreadsOn
00636 //===========================================================================
00637 //
00638 // Parameter:               -
00639 // Returns:                 -
00640 // Changes Globals:     -
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     } //end if
00653     else
00654     {
00655         ThreadLock();
00656         if (currentnumthreads >= numthreads)
00657         {
00658             ThreadUnlock();
00659             return;
00660         } //end if
00661         //allocate new thread
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         //add the thread to the end of the list
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     } //end else
00685 } //end of the function AddThread
00686 //===========================================================================
00687 //
00688 // Parameter:               -
00689 // Returns:                 -
00690 // Changes Globals:     -
00691 //===========================================================================
00692 void RemoveThread(int threadid)
00693 {
00694     thread_t *thread, *last;
00695 
00696     //if a single thread
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         } //end if
00716         last = thread;
00717     } //end if
00718     if (!thread) Error("couldn't find thread with id %d", threadid);
00719     ThreadUnlock();
00720 } //end of the function RemoveThread
00721 //===========================================================================
00722 //
00723 // Parameter:               -
00724 // Returns:                 -
00725 // Changes Globals:     -
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     } //end while
00743     ThreadUnlock();
00744 } //end of the function WaitForAllThreadsFinished
00745 //===========================================================================
00746 //
00747 // Parameter:               -
00748 // Returns:                 -
00749 // Changes Globals:     -
00750 //===========================================================================
00751 int GetNumThreads(void)
00752 {
00753     return currentnumthreads;
00754 } //end of the function GetNumThreads
00755 
00756 #endif
00757 
00758 //===================================================================
00759 //
00760 // LINUX
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 // Parameter:               -
00795 // Returns:                 -
00796 // Changes Globals:     -
00797 //===========================================================================
00798 void ThreadSetDefault(void)
00799 {
00800     if (numthreads == -1)   // not set manually
00801     {
00802         numthreads = 1;
00803     } //end if
00804     qprintf("%i threads\n", numthreads);
00805 } //end of the function ThreadSetDefault
00806 //===========================================================================
00807 //
00808 // Parameter:               -
00809 // Returns:                 -
00810 // Changes Globals:     -
00811 //===========================================================================
00812 void ThreadLock(void)
00813 {
00814     if (!threaded)
00815     {
00816         Error("ThreadLock: !threaded");
00817         return;
00818     } //end if
00819     pthread_mutex_lock(&my_mutex);
00820     if (enter)
00821         Error("Recursive ThreadLock\n");
00822     enter = 1;
00823 } //end of the function ThreadLock
00824 //===========================================================================
00825 //
00826 // Parameter:               -
00827 // Returns:                 -
00828 // Changes Globals:     -
00829 //===========================================================================
00830 void ThreadUnlock(void)
00831 {
00832     if (!threaded)
00833     {
00834         Error("ThreadUnlock: !threaded");
00835         return;
00836     } //end if
00837     if (!enter)
00838         Error("ThreadUnlock without lock\n");
00839     enter = 0;
00840     pthread_mutex_unlock(&my_mutex);
00841 } //end of the function ThreadUnlock
00842 //===========================================================================
00843 //
00844 // Parameter:               -
00845 // Returns:                 -
00846 // Changes Globals:     -
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 } //end of the function ThreadInitLock
00858 //===========================================================================
00859 //
00860 // Parameter:               -
00861 // Returns:                 -
00862 // Changes Globals:     -
00863 //===========================================================================
00864 void ThreadShutdownLock(void)
00865 {
00866     threaded = false;
00867 } //end of the function ThreadShutdownLock
00868 //===========================================================================
00869 //
00870 // Parameter:           -
00871 // Returns:             -
00872 // Changes Globals:     -
00873 //===========================================================================
00874 void ThreadSetupSemaphore(void)
00875 {
00876     sem_init(&semaphore, 0, 0);
00877 } //end of the function ThreadSetupSemaphore
00878 //===========================================================================
00879 //
00880 // Parameter:           -
00881 // Returns:             -
00882 // Changes Globals:     -
00883 //===========================================================================
00884 void ThreadShutdownSemaphore(void)
00885 {
00886     sem_destroy(&semaphore);
00887 } //end of the function ThreadShutdownSemaphore
00888 //===========================================================================
00889 //
00890 // Parameter:           -
00891 // Returns:             -
00892 // Changes Globals:     -
00893 //===========================================================================
00894 void ThreadSemaphoreWait(void)
00895 {
00896     sem_wait(&semaphore);
00897 } //end of the function ThreadSemaphoreWait
00898 //===========================================================================
00899 //
00900 // Parameter:           -
00901 // Returns:             -
00902 // Changes Globals:     -
00903 //===========================================================================
00904 void ThreadSemaphoreIncrease(int count)
00905 {
00906     int i;
00907 
00908     for (i = 0; i < count; i++)
00909     {
00910         sem_post(&semaphore);
00911     } //end for
00912 } //end of the function ThreadSemaphoreIncrease
00913 //===========================================================================
00914 //
00915 // Parameter:               -
00916 // Returns:                 -
00917 // Changes Globals:     -
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 } //end of the function RunThreadsOn
00960 //===========================================================================
00961 //
00962 // Parameter:               -
00963 // Returns:                 -
00964 // Changes Globals:     -
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     } //end if
00977     else
00978     {
00979         ThreadLock();
00980         if (currentnumthreads >= numthreads)
00981         {
00982             ThreadUnlock();
00983             return;
00984         } //end if
00985         //allocate new thread
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         //add the thread to the end of the list
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     } //end else
01009 } //end of the function AddThread
01010 //===========================================================================
01011 //
01012 // Parameter:               -
01013 // Returns:                 -
01014 // Changes Globals:     -
01015 //===========================================================================
01016 void RemoveThread(int threadid)
01017 {
01018     thread_t *thread, *last;
01019 
01020     //if a single thread
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         } //end if
01040         last = thread;
01041     } //end if
01042     if (!thread) Error("couldn't find thread with id %d", threadid);
01043     ThreadUnlock();
01044 } //end of the function RemoveThread
01045 //===========================================================================
01046 //
01047 // Parameter:               -
01048 // Returns:                 -
01049 // Changes Globals:     -
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     } //end while
01067     ThreadUnlock();
01068 } //end of the function WaitForAllThreadsFinished
01069 //===========================================================================
01070 //
01071 // Parameter:               -
01072 // Returns:                 -
01073 // Changes Globals:     -
01074 //===========================================================================
01075 int GetNumThreads(void)
01076 {
01077     return currentnumthreads;
01078 } //end of the function GetNumThreads
01079 
01080 #endif //LINUX
01081 
01082 
01083 //===================================================================
01084 //
01085 // IRIX
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 // Parameter:               -
01119 // Returns:                 -
01120 // Changes Globals:     -
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 } //end of the function ThreadSetDefault
01130 //===========================================================================
01131 //
01132 // Parameter:               -
01133 // Returns:                 -
01134 // Changes Globals:     -
01135 //===========================================================================
01136 void ThreadLock (void)
01137 {
01138     spin_lock (&lck);
01139 } //end of the function ThreadLock
01140 //===========================================================================
01141 //
01142 // Parameter:               -
01143 // Returns:                 -
01144 // Changes Globals:     -
01145 //===========================================================================
01146 void ThreadUnlock (void)
01147 {
01148     release_lock(&lck);
01149 } //end of the function ThreadUnlock
01150 //===========================================================================
01151 //
01152 // Parameter:               -
01153 // Returns:                 -
01154 // Changes Globals:     -
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 } //end of the function ThreadInitLock
01166 //===========================================================================
01167 //
01168 // Parameter:               -
01169 // Returns:                 -
01170 // Changes Globals:     -
01171 //===========================================================================
01172 void ThreadShutdownLock(void)
01173 {
01174     threaded = false;
01175 } //end of the function ThreadShutdownLock
01176 //===========================================================================
01177 //
01178 // Parameter:               -
01179 // Returns:                 -
01180 // Changes Globals:     -
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 //      pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
01207 //          , NULL, 0x80000);
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 } //end of the function RunThreadsOn
01226 //===========================================================================
01227 //
01228 // Parameter:               -
01229 // Returns:                 -
01230 // Changes Globals:     -
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     } //end if
01243     else
01244     {
01245         ThreadLock();
01246         if (currentnumthreads >= numthreads)
01247         {
01248             ThreadUnlock();
01249             return;
01250         } //end if
01251         //allocate new thread
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         //add the thread to the end of the list
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     } //end else
01279 } //end of the function AddThread
01280 //===========================================================================
01281 //
01282 // Parameter:               -
01283 // Returns:                 -
01284 // Changes Globals:     -
01285 //===========================================================================
01286 void RemoveThread(int threadid)
01287 {
01288     thread_t *thread, *last;
01289 
01290     //if a single thread
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         } //end if
01310         last = thread;
01311     } //end if
01312     if (!thread) Error("couldn't find thread with id %d", threadid);
01313     ThreadUnlock();
01314 } //end of the function RemoveThread
01315 //===========================================================================
01316 //
01317 // Parameter:               -
01318 // Returns:                 -
01319 // Changes Globals:     -
01320 //===========================================================================
01321 void WaitForAllThreadsFinished(void)
01322 {
01323     ThreadLock();
01324     while(firstthread)
01325     {
01326         ThreadUnlock();
01327 
01328         //wait (NULL);
01329 
01330         ThreadLock();
01331     } //end while
01332     ThreadUnlock();
01333 } //end of the function WaitForAllThreadsFinished
01334 //===========================================================================
01335 //
01336 // Parameter:               -
01337 // Returns:                 -
01338 // Changes Globals:     -
01339 //===========================================================================
01340 int GetNumThreads(void)
01341 {
01342     return currentnumthreads;
01343 } //end of the function GetNumThreads
01344 
01345 #endif //_MIPS_ISA
01346 
01347 
01348 //=======================================================================
01349 //
01350 // SINGLE THREAD
01351 //
01352 //=======================================================================
01353 
01354 #ifndef USED
01355 
01356 int numthreads = 1;
01357 int currentnumthreads = 0;
01358 
01359 //===========================================================================
01360 //
01361 // Parameter:               -
01362 // Returns:                 -
01363 // Changes Globals:     -
01364 //===========================================================================
01365 void ThreadSetDefault(void)
01366 {
01367     numthreads = 1;
01368 } //end of the function ThreadSetDefault
01369 //===========================================================================
01370 //
01371 // Parameter:               -
01372 // Returns:                 -
01373 // Changes Globals:     -
01374 //===========================================================================
01375 void ThreadLock(void)
01376 {
01377 } //end of the function ThreadLock
01378 //===========================================================================
01379 //
01380 // Parameter:               -
01381 // Returns:                 -
01382 // Changes Globals:     -
01383 //===========================================================================
01384 void ThreadUnlock(void)
01385 {
01386 } //end of the function ThreadUnlock
01387 //===========================================================================
01388 //
01389 // Parameter:               -
01390 // Returns:                 -
01391 // Changes Globals:     -
01392 //===========================================================================
01393 void ThreadSetupLock(void)
01394 {
01395     Log_Print("no multi-threading\n");
01396 } //end of the function ThreadInitLock
01397 //===========================================================================
01398 //
01399 // Parameter:               -
01400 // Returns:                 -
01401 // Changes Globals:     -
01402 //===========================================================================
01403 void ThreadShutdownLock(void)
01404 {
01405 } //end of the function ThreadShutdownLock
01406 //===========================================================================
01407 //
01408 // Parameter:               -
01409 // Returns:                 -
01410 // Changes Globals:     -
01411 //===========================================================================
01412 void ThreadSetupSemaphore(void)
01413 {
01414 } //end of the function ThreadSetupSemaphore
01415 //===========================================================================
01416 //
01417 // Parameter:           -
01418 // Returns:             -
01419 // Changes Globals:     -
01420 //===========================================================================
01421 void ThreadShutdownSemaphore(void)
01422 {
01423 } //end of the function ThreadShutdownSemaphore
01424 //===========================================================================
01425 //
01426 // Parameter:               -
01427 // Returns:                 -
01428 // Changes Globals:     -
01429 //===========================================================================
01430 void ThreadSemaphoreWait(void)
01431 {
01432 } //end of the function ThreadSemaphoreWait
01433 //===========================================================================
01434 //
01435 // Parameter:               -
01436 // Returns:                 -
01437 // Changes Globals:     -
01438 //===========================================================================
01439 void ThreadSemaphoreIncrease(int count)
01440 {
01441 } //end of the function ThreadSemaphoreIncrease
01442 //===========================================================================
01443 //
01444 // Parameter:               -
01445 // Returns:                 -
01446 // Changes Globals:     -
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 } //end of the function RunThreadsOn
01468 //===========================================================================
01469 //
01470 // Parameter:               -
01471 // Returns:                 -
01472 // Changes Globals:     -
01473 //===========================================================================
01474 void AddThread(void (*func)(int))
01475 {
01476     if (currentnumthreads >= numthreads) return;
01477     currentnumthreads++;
01478     func(-1);
01479     currentnumthreads--;
01480 } //end of the function AddThread
01481 //===========================================================================
01482 //
01483 // Parameter:               -
01484 // Returns:                 -
01485 // Changes Globals:     -
01486 //===========================================================================
01487 void RemoveThread(int threadid)
01488 {
01489 } //end of the function RemoveThread
01490 //===========================================================================
01491 //
01492 // Parameter:               -
01493 // Returns:                 -
01494 // Changes Globals:     -
01495 //===========================================================================
01496 void WaitForAllThreadsFinished(void)
01497 {
01498 } //end of the function WaitForAllThreadsFinished
01499 //===========================================================================
01500 //
01501 // Parameter:               -
01502 // Returns:                 -
01503 // Changes Globals:     -
01504 //===========================================================================
01505 int GetNumThreads(void)
01506 {
01507     return currentnumthreads;
01508 } //end of the function GetNumThreads
01509 
01510 #endif //USED

Generated on Thu Aug 25 12:37:17 2005 for Quake III Arena by  doxygen 1.3.9.1