]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/common/threads.c
25a87c78e4dbc6b662ec0bb23c88b89e8a2a07dd
[xonotic/netradiant.git] / tools / quake2 / extra / common / threads.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools 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 2 Tools 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 Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22
23 #include "cmdlib.h"
24 #include "threads.h"
25
26 #define MAX_THREADS     64
27
28 int             dispatch;
29 int             workcount;
30 int             oldf;
31 qboolean                pacifier;
32
33 qboolean        threaded;
34
35 /*
36 =============
37 GetThreadWork
38
39 =============
40 */
41 int     GetThreadWork (void)
42 {
43         int     r;
44         int     f;
45
46         ThreadLock ();
47
48         if (dispatch == workcount)
49         {
50                 ThreadUnlock ();
51                 return -1;
52         }
53
54         f = 10*dispatch / workcount;
55         if (f != oldf)
56         {
57                 oldf = f;
58                 if (pacifier)
59                         printf ("%i...", f);
60         }
61
62         r = dispatch;
63         dispatch++;
64         ThreadUnlock ();
65
66         return r;
67 }
68
69
70 void (*workfunction) (int);
71
72 void ThreadWorkerFunction (int threadnum)
73 {
74         int             work;
75
76         while (1)
77         {
78                 work = GetThreadWork ();
79                 if (work == -1)
80                         break;
81 //printf ("thread %i, work %i\n", threadnum, work);
82                 workfunction(work);
83         }
84 }
85
86 void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
87 {
88         if (numthreads == -1)
89                 ThreadSetDefault ();
90         workfunction = func;
91         RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
92 }
93
94
95 /*
96 ===================================================================
97
98 WIN32
99
100 ===================================================================
101 */
102 #ifdef WIN32
103
104 #define USED
105
106 #include <windows.h>
107
108 int             numthreads = -1;
109 CRITICAL_SECTION                crit;
110 static int enter;
111
112 void ThreadSetDefault (void)
113 {
114         SYSTEM_INFO info;
115
116         if (numthreads == -1)   // not set manually
117         {
118                 GetSystemInfo (&info);
119                 numthreads = info.dwNumberOfProcessors;
120                 if (numthreads < 1 || numthreads > 32)
121                         numthreads = 1;
122         }
123
124         qprintf ("%i threads\n", numthreads);
125 }
126
127
128 void ThreadLock (void)
129 {
130         if (!threaded)
131                 return;
132         EnterCriticalSection (&crit);
133         if (enter)
134                 Error ("Recursive ThreadLock\n");
135         enter = 1;
136 }
137
138 void ThreadUnlock (void)
139 {
140         if (!threaded)
141                 return;
142         if (!enter)
143                 Error ("ThreadUnlock without lock\n");
144         enter = 0;
145         LeaveCriticalSection (&crit);
146 }
147
148 /*
149 =============
150 RunThreadsOn
151 =============
152 */
153 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
154 {
155         int             threadid[MAX_THREADS];
156         HANDLE  threadhandle[MAX_THREADS];
157         int             i;
158         int             start, end;
159
160         start = I_FloatTime ();
161         dispatch = 0;
162         workcount = workcnt;
163         oldf = -1;
164         pacifier = showpacifier;
165         threaded = true;
166
167         //
168         // run threads in parallel
169         //
170         InitializeCriticalSection (&crit);
171
172         if (numthreads == 1)
173         {       // use same thread
174                 func (0);
175         }
176         else
177         {
178                 for (i=0 ; i<numthreads ; i++)
179                 {
180                         threadhandle[i] = CreateThread(
181                            NULL,        // LPSECURITY_ATTRIBUTES lpsa,
182                            0,           // DWORD cbStack,
183                            (LPTHREAD_START_ROUTINE)func,        // LPTHREAD_START_ROUTINE lpStartAddr,
184                            (LPVOID)i,   // LPVOID lpvThreadParm,
185                            0,                   //   DWORD fdwCreate,
186                            &threadid[i]);
187                 }
188
189                 for (i=0 ; i<numthreads ; i++)
190                         WaitForSingleObject (threadhandle[i], INFINITE);
191         }
192         DeleteCriticalSection (&crit);
193
194         threaded = false;
195         end = I_FloatTime ();
196         if (pacifier)
197                 printf (" (%i)\n", end-start);
198 }
199
200
201 #endif
202
203 /*
204 ===================================================================
205
206 OSF1
207
208 ===================================================================
209 */
210
211 #ifdef __osf__
212 #define USED
213
214 int             numthreads = 4;
215
216 void ThreadSetDefault (void)
217 {
218         if (numthreads == -1)   // not set manually
219         {
220                 numthreads = 4;
221         }
222 }
223
224
225 #include <pthread.h>
226
227 pthread_mutex_t *my_mutex;
228
229 void ThreadLock (void)
230 {
231         if (my_mutex)
232                 pthread_mutex_lock (my_mutex);
233 }
234
235 void ThreadUnlock (void)
236 {
237         if (my_mutex)
238                 pthread_mutex_unlock (my_mutex);
239 }
240
241
242 /*
243 =============
244 RunThreadsOn
245 =============
246 */
247 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
248 {
249         int             i;
250         pthread_t       work_threads[MAX_THREADS];
251         pthread_addr_t  status;
252         pthread_attr_t  attrib;
253         pthread_mutexattr_t     mattrib;
254         int             start, end;
255
256         start = I_FloatTime ();
257         dispatch = 0;
258         workcount = workcnt;
259         oldf = -1;
260         pacifier = showpacifier;
261         threaded = true;
262
263         if (pacifier)
264                 setbuf (stdout, NULL);
265
266         if (!my_mutex)
267         {
268                 my_mutex = malloc (sizeof(*my_mutex));
269                 if (pthread_mutexattr_create (&mattrib) == -1)
270                         Error ("pthread_mutex_attr_create failed");
271                 if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
272                         Error ("pthread_mutexattr_setkind_np failed");
273                 if (pthread_mutex_init (my_mutex, mattrib) == -1)
274                         Error ("pthread_mutex_init failed");
275         }
276
277         if (pthread_attr_create (&attrib) == -1)
278                 Error ("pthread_attr_create failed");
279         if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
280                 Error ("pthread_attr_setstacksize failed");
281
282         for (i=0 ; i<numthreads ; i++)
283         {
284                 if (pthread_create(&work_threads[i], attrib
285                 , (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
286                         Error ("pthread_create failed");
287         }
288
289         for (i=0 ; i<numthreads ; i++)
290         {
291                 if (pthread_join (work_threads[i], &status) == -1)
292                         Error ("pthread_join failed");
293         }
294
295         threaded = false;
296
297         end = I_FloatTime ();
298         if (pacifier)
299                 printf (" (%i)\n", end-start);
300 }
301
302
303 #endif
304
305 /*
306 ===================================================================
307
308 IRIX
309
310 ===================================================================
311 */
312
313 #ifdef _MIPS_ISA
314 #define USED
315
316 #include <task.h>
317 #include <abi_mutex.h>
318 #include <sys/types.h>
319 #include <sys/prctl.h>
320
321
322 int             numthreads = -1;
323 abilock_t               lck;
324
325 void ThreadSetDefault (void)
326 {
327         if (numthreads == -1)
328                 numthreads = prctl(PR_MAXPPROCS);
329         printf ("%i threads\n", numthreads);
330 //@@
331         usconfig (CONF_INITUSERS, numthreads);
332 }
333
334
335 void ThreadLock (void)
336 {
337         spin_lock (&lck);
338 }
339
340 void ThreadUnlock (void)
341 {
342         release_lock (&lck);
343 }
344
345
346 /*
347 =============
348 RunThreadsOn
349 =============
350 */
351 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
352 {
353         int             i;
354         int             pid[MAX_THREADS];
355         int             start, end;
356
357         start = I_FloatTime ();
358         dispatch = 0;
359         workcount = workcnt;
360         oldf = -1;
361         pacifier = showpacifier;
362         threaded = true;
363
364         if (pacifier)
365                 setbuf (stdout, NULL);
366
367         init_lock (&lck);
368
369         for (i=0 ; i<numthreads-1 ; i++)
370         {
371                 pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
372                         , NULL, 0x100000);
373 //              pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
374 //                      , NULL, 0x80000);
375                 if (pid[i] == -1)
376                 {
377                         perror ("sproc");
378                         Error ("sproc failed");
379                 }
380         }
381
382         func(i);
383
384         for (i=0 ; i<numthreads-1 ; i++)
385                 wait (NULL);
386
387         threaded = false;
388
389         end = I_FloatTime ();
390         if (pacifier)
391                 printf (" (%i)\n", end-start);
392 }
393
394
395 #endif
396
397 /*
398 =======================================================================
399
400   SINGLE THREAD
401
402 =======================================================================
403 */
404
405 #ifndef USED
406
407 int             numthreads = 1;
408
409 void ThreadSetDefault (void)
410 {
411         numthreads = 1;
412 }
413
414 void ThreadLock (void)
415 {
416 }
417
418 void ThreadUnlock (void)
419 {
420 }
421
422 /*
423 =============
424 RunThreadsOn
425 =============
426 */
427 void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
428 {
429         int             i;
430         int             start, end;
431
432         dispatch = 0;
433         workcount = workcnt;
434         oldf = -1;
435         pacifier = showpacifier;
436         start = I_FloatTime ();
437 #ifdef NeXT
438         if (pacifier)
439                 setbuf (stdout, NULL);
440 #endif
441         func(0);
442
443         end = I_FloatTime ();
444         if (pacifier)
445                 printf (" (%i)\n", end-start);
446 }
447
448 #endif