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