threads.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "cmdlib.h"
  19. #include "threads.h"
  20. #define MAX_THREADS 64
  21. int dispatch;
  22. int workcount;
  23. int oldf;
  24. qboolean pacifier;
  25. qboolean threaded;
  26. /*
  27. =============
  28. GetThreadWork
  29. =============
  30. */
  31. int GetThreadWork (void)
  32. {
  33. int r;
  34. int f;
  35. ThreadLock ();
  36. if (dispatch == workcount)
  37. {
  38. ThreadUnlock ();
  39. return -1;
  40. }
  41. f = 10*dispatch / workcount;
  42. if (f != oldf)
  43. {
  44. oldf = f;
  45. if (pacifier)
  46. printf ("%i...", f);
  47. }
  48. r = dispatch;
  49. dispatch++;
  50. ThreadUnlock ();
  51. return r;
  52. }
  53. void (*workfunction) (int);
  54. void ThreadWorkerFunction (int threadnum)
  55. {
  56. int work;
  57. while (1)
  58. {
  59. work = GetThreadWork ();
  60. if (work == -1)
  61. break;
  62. //printf ("thread %i, work %i\n", threadnum, work);
  63. workfunction(work);
  64. }
  65. }
  66. void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
  67. {
  68. if (numthreads == -1)
  69. ThreadSetDefault ();
  70. workfunction = func;
  71. RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
  72. }
  73. /*
  74. ===================================================================
  75. WIN32
  76. ===================================================================
  77. */
  78. #ifdef WIN32
  79. #define USED
  80. #include <windows.h>
  81. int numthreads = -1;
  82. CRITICAL_SECTION crit;
  83. static int enter;
  84. void ThreadSetDefault (void)
  85. {
  86. SYSTEM_INFO info;
  87. if (numthreads == -1) // not set manually
  88. {
  89. GetSystemInfo (&info);
  90. numthreads = info.dwNumberOfProcessors;
  91. if (numthreads < 1 || numthreads > 32)
  92. numthreads = 1;
  93. }
  94. qprintf ("%i threads\n", numthreads);
  95. }
  96. void ThreadLock (void)
  97. {
  98. if (!threaded)
  99. return;
  100. EnterCriticalSection (&crit);
  101. if (enter)
  102. Error ("Recursive ThreadLock\n");
  103. enter = 1;
  104. }
  105. void ThreadUnlock (void)
  106. {
  107. if (!threaded)
  108. return;
  109. if (!enter)
  110. Error ("ThreadUnlock without lock\n");
  111. enter = 0;
  112. LeaveCriticalSection (&crit);
  113. }
  114. /*
  115. =============
  116. RunThreadsOn
  117. =============
  118. */
  119. void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
  120. {
  121. int threadid[MAX_THREADS];
  122. HANDLE threadhandle[MAX_THREADS];
  123. int i;
  124. int start, end;
  125. start = I_FloatTime ();
  126. dispatch = 0;
  127. workcount = workcnt;
  128. oldf = -1;
  129. pacifier = showpacifier;
  130. threaded = true;
  131. //
  132. // run threads in parallel
  133. //
  134. InitializeCriticalSection (&crit);
  135. if (numthreads == 1)
  136. { // use same thread
  137. func (0);
  138. }
  139. else
  140. {
  141. for (i=0 ; i<numthreads ; i++)
  142. {
  143. threadhandle[i] = CreateThread(
  144. NULL, // LPSECURITY_ATTRIBUTES lpsa,
  145. 0, // DWORD cbStack,
  146. (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
  147. (LPVOID)i, // LPVOID lpvThreadParm,
  148. 0, // DWORD fdwCreate,
  149. &threadid[i]);
  150. }
  151. for (i=0 ; i<numthreads ; i++)
  152. WaitForSingleObject (threadhandle[i], INFINITE);
  153. }
  154. DeleteCriticalSection (&crit);
  155. threaded = false;
  156. end = I_FloatTime ();
  157. if (pacifier)
  158. printf (" (%i)\n", end-start);
  159. }
  160. #endif
  161. /*
  162. ===================================================================
  163. OSF1
  164. ===================================================================
  165. */
  166. #ifdef __osf__
  167. #define USED
  168. int numthreads = 4;
  169. void ThreadSetDefault (void)
  170. {
  171. if (numthreads == -1) // not set manually
  172. {
  173. numthreads = 4;
  174. }
  175. }
  176. #include <pthread.h>
  177. pthread_mutex_t *my_mutex;
  178. void ThreadLock (void)
  179. {
  180. if (my_mutex)
  181. pthread_mutex_lock (my_mutex);
  182. }
  183. void ThreadUnlock (void)
  184. {
  185. if (my_mutex)
  186. pthread_mutex_unlock (my_mutex);
  187. }
  188. /*
  189. =============
  190. RunThreadsOn
  191. =============
  192. */
  193. void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
  194. {
  195. int i;
  196. pthread_t work_threads[MAX_THREADS];
  197. pthread_addr_t status;
  198. pthread_attr_t attrib;
  199. pthread_mutexattr_t mattrib;
  200. int start, end;
  201. start = I_FloatTime ();
  202. dispatch = 0;
  203. workcount = workcnt;
  204. oldf = -1;
  205. pacifier = showpacifier;
  206. threaded = true;
  207. if (pacifier)
  208. setbuf (stdout, NULL);
  209. if (!my_mutex)
  210. {
  211. my_mutex = malloc (sizeof(*my_mutex));
  212. if (pthread_mutexattr_create (&mattrib) == -1)
  213. Error ("pthread_mutex_attr_create failed");
  214. if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
  215. Error ("pthread_mutexattr_setkind_np failed");
  216. if (pthread_mutex_init (my_mutex, mattrib) == -1)
  217. Error ("pthread_mutex_init failed");
  218. }
  219. if (pthread_attr_create (&attrib) == -1)
  220. Error ("pthread_attr_create failed");
  221. if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
  222. Error ("pthread_attr_setstacksize failed");
  223. for (i=0 ; i<numthreads ; i++)
  224. {
  225. if (pthread_create(&work_threads[i], attrib
  226. , (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
  227. Error ("pthread_create failed");
  228. }
  229. for (i=0 ; i<numthreads ; i++)
  230. {
  231. if (pthread_join (work_threads[i], &status) == -1)
  232. Error ("pthread_join failed");
  233. }
  234. threaded = false;
  235. end = I_FloatTime ();
  236. if (pacifier)
  237. printf (" (%i)\n", end-start);
  238. }
  239. #endif
  240. /*
  241. ===================================================================
  242. IRIX
  243. ===================================================================
  244. */
  245. #ifdef _MIPS_ISA
  246. #define USED
  247. #include <task.h>
  248. #include <abi_mutex.h>
  249. #include <sys/types.h>
  250. #include <sys/prctl.h>
  251. int numthreads = -1;
  252. abilock_t lck;
  253. void ThreadSetDefault (void)
  254. {
  255. if (numthreads == -1)
  256. numthreads = prctl(PR_MAXPPROCS);
  257. printf ("%i threads\n", numthreads);
  258. //@@
  259. usconfig (CONF_INITUSERS, numthreads);
  260. }
  261. void ThreadLock (void)
  262. {
  263. spin_lock (&lck);
  264. }
  265. void ThreadUnlock (void)
  266. {
  267. release_lock (&lck);
  268. }
  269. /*
  270. =============
  271. RunThreadsOn
  272. =============
  273. */
  274. void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
  275. {
  276. int i;
  277. int pid[MAX_THREADS];
  278. int start, end;
  279. start = I_FloatTime ();
  280. dispatch = 0;
  281. workcount = workcnt;
  282. oldf = -1;
  283. pacifier = showpacifier;
  284. threaded = true;
  285. if (pacifier)
  286. setbuf (stdout, NULL);
  287. init_lock (&lck);
  288. for (i=0 ; i<numthreads-1 ; i++)
  289. {
  290. pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
  291. , NULL, 0x100000);
  292. // pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
  293. // , NULL, 0x80000);
  294. if (pid[i] == -1)
  295. {
  296. perror ("sproc");
  297. Error ("sproc failed");
  298. }
  299. }
  300. func(i);
  301. for (i=0 ; i<numthreads-1 ; i++)
  302. wait (NULL);
  303. threaded = false;
  304. end = I_FloatTime ();
  305. if (pacifier)
  306. printf (" (%i)\n", end-start);
  307. }
  308. #endif
  309. /*
  310. =======================================================================
  311. SINGLE THREAD
  312. =======================================================================
  313. */
  314. #ifndef USED
  315. int numthreads = 1;
  316. void ThreadSetDefault (void)
  317. {
  318. numthreads = 1;
  319. }
  320. void ThreadLock (void)
  321. {
  322. }
  323. void ThreadUnlock (void)
  324. {
  325. }
  326. /*
  327. =============
  328. RunThreadsOn
  329. =============
  330. */
  331. void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
  332. {
  333. int i;
  334. int start, end;
  335. dispatch = 0;
  336. workcount = workcnt;
  337. oldf = -1;
  338. pacifier = showpacifier;
  339. start = I_FloatTime ();
  340. #ifdef NeXT
  341. if (pacifier)
  342. setbuf (stdout, NULL);
  343. #endif
  344. func(0);
  345. end = I_FloatTime ();
  346. if (pacifier)
  347. printf (" (%i)\n", end-start);
  348. }
  349. #endif