blob: 44f2896877691d19f14f6ff22efc40eeae8cfd9d [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001#include "thread.h"
2
Guido van Rossumf9f2e821992-08-17 08:59:08 +00003#ifdef DEBUG
Sjoerd Mullenderd10d8291992-09-11 15:19:27 +00004static int thread_debug = 0;
5#define dprintf(args) (thread_debug && printf args)
Guido van Rossumf9f2e821992-08-17 08:59:08 +00006#else
7#define dprintf(args)
8#endif
9
Guido van Rossum1984f1e1992-08-04 12:41:02 +000010#ifdef __sgi
11#include <stdlib.h>
12#include <stdio.h>
13#include <signal.h>
14#include <sys/types.h>
15#include <sys/prctl.h>
16#include <ulocks.h>
Sjoerd Mullendere8934121993-01-13 12:08:48 +000017#include <errno.h>
Guido van Rossum1984f1e1992-08-04 12:41:02 +000018
Sjoerd Mullender76ab5fe1993-01-13 12:49:46 +000019#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
Guido van Rossumf9f2e821992-08-17 08:59:08 +000020#define MAXPROC 100 /* max # of threads that can be started */
21
Guido van Rossum1984f1e1992-08-04 12:41:02 +000022static usptr_t *shared_arena;
Guido van Rossumf9f2e821992-08-17 08:59:08 +000023static ulock_t count_lock; /* protection for some variables */
24static ulock_t wait_lock; /* lock used to wait for other threads */
25static int waiting_for_threads; /* protected by count_lock */
26static int nthreads; /* protected by count_lock */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000027static int exit_status;
Sjoerd Mullendered59d201993-01-06 13:36:38 +000028static int do_exit; /* indicates that the program is to exit */
Guido van Rossumf9f2e821992-08-17 08:59:08 +000029static int exiting; /* we're already exiting (for maybe_exit) */
30static pid_t my_pid; /* PID of main thread */
31static pid_t pidlist[MAXPROC]; /* PIDs of other threads */
32static int maxpidindex; /* # of PIDs in pidlist */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000033#endif
34#ifdef sun
35#include <lwp/lwp.h>
36#include <lwp/stackdep.h>
37
Guido van Rossumf9f2e821992-08-17 08:59:08 +000038#define STACKSIZE 1000 /* stacksize for a thread */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000039#define NSTACKS 2 /* # stacks to be put in cache initialy */
40
41struct lock {
42 int lock_locked;
43 cv_t lock_condvar;
44 mon_t lock_monitor;
45};
46#endif
47#ifdef C_THREADS
48#include <cthreads.h>
49#endif
50
51#ifdef __STDC__
52#define _P(args) args
53#define _P0() (void)
54#define _P1(v,t) (t)
55#define _P2(v1,t1,v2,t2) (t1,t2)
56#else
57#define _P(args) ()
58#define _P0() ()
59#define _P1(v,t) (v) t;
60#define _P2(v1,t1,v2,t2) (v1,v2) t1; t2;
61#endif
62
63static int initialized;
64
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +000065#ifdef __sgi
66/*
67 * This routine is called as a signal handler when another thread
68 * exits. When that happens, we must see whether we have to exit as
69 * well (because of an exit_prog()) or whether we should continue on.
70 */
71static void exit_sig _P0()
72{
73 dprintf(("exit_sig called\n"));
74 if (exiting && getpid() == my_pid) {
75 dprintf(("already exiting\n"));
76 return;
77 }
78 if (do_exit) {
79 dprintf(("exiting in exit_sig\n"));
80 exit_thread();
81 }
82}
83
84/*
85 * This routine is called when a process calls exit(). If that wasn't
86 * done from the library, we do as if an exit_prog() was intended.
87 */
88static void maybe_exit _P0()
89{
90 dprintf(("maybe_exit called\n"));
91 if (exiting) {
92 dprintf(("already exiting\n"));
93 return;
94 }
95 exit_prog(0);
96}
97#endif
98
99/*
100 * Initialization.
101 */
102void init_thread _P0()
103{
104#ifdef __sgi
105 struct sigaction s;
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000106#ifdef USE_DL
107 long addr, size;
108#endif
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000109#endif
110
Sjoerd Mullenderd10d8291992-09-11 15:19:27 +0000111#ifdef DEBUG
112 thread_debug = getenv("THREADDEBUG") != 0;
113#endif
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000114 if (initialized)
115 return;
116 initialized = 1;
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000117 dprintf(("init_thread called\n"));
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000118
119#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000120#ifdef USE_DL
121 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
122 perror("usconfig - CONF_INITSIZE (check)");
123 if (usconfig(CONF_INITSIZE, size) < 0)
124 perror("usconfig - CONF_INITSIZE (reset)");
Sjoerd Mullender76ab5fe1993-01-13 12:49:46 +0000125 addr = (long) dl_getrange(size + HDR_SIZE);
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000126 dprintf(("trying to use addr %lx-%lx for shared arena\n", addr, addr+size));
127 errno = 0;
128 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
129 perror("usconfig - CONF_ATTACHADDR (set)");
130#endif
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000131 if (usconfig(CONF_INITUSERS, 16) < 0)
132 perror("usconfig - CONF_INITUSERS");
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000133 my_pid = getpid(); /* so that we know which is the main thread */
134 atexit(maybe_exit);
135 s.sa_handler = exit_sig;
136 sigemptyset(&s.sa_mask);
Sjoerd Mullenderd10d8291992-09-11 15:19:27 +0000137 /*sigaddset(&s.sa_mask, SIGUSR1);*/
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000138 s.sa_flags = 0;
139 sigaction(SIGUSR1, &s, 0);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000140 if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
141 perror("prctl - PR_SETEXITSIG");
142 if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
143 perror("usconfig - CONF_ARENATYPE");
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000144 /*usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);*/
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000145 if ((shared_arena = usinit(tmpnam(0))) == 0)
146 perror("usinit");
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000147#ifdef USE_DL
148 if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
149 perror("usconfig - CONF_ATTACHADDR (reset)");
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000150#endif
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000151 if ((count_lock = usnewlock(shared_arena)) == NULL)
152 perror("usnewlock (count_lock)");
153 (void) usinitlock(count_lock);
154 if ((wait_lock = usnewlock(shared_arena)) == NULL)
155 perror("usnewlock (wait_lock)");
156 dprintf(("arena start: %lx, arena size: %ld\n", (long) shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000157#endif
158#ifdef sun
159 lwp_setstkcache(STACKSIZE, NSTACKS);
160#endif
161#ifdef C_THREADS
162 cthread_init();
163#endif
164}
165
166/*
167 * Thread support.
168 */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000169int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
170{
171#ifdef sun
172 thread_t tid;
173#endif
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000174#if defined(__sgi) && defined(USE_DL)
175 long addr, size;
176 static int local_initialized = 0;
177#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000178 int success = 0; /* init not needed when SOLARIS and */
179 /* C_THREADS implemented properly */
180
181 dprintf(("start_new_thread called\n"));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000182 if (!initialized)
183 init_thread();
184#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000185 switch (ussetlock(count_lock)) {
186 case 0: return 0;
187 case -1: perror("ussetlock (count_lock)");
188 }
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000189 if (maxpidindex >= MAXPROC)
190 success = -1;
191 else {
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000192#ifdef USE_DL
193 if (!local_initialized) {
194 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
195 perror("usconfig - CONF_INITSIZE (check)");
196 if (usconfig(CONF_INITSIZE, size) < 0)
197 perror("usconfig - CONF_INITSIZE (reset)");
Sjoerd Mullender76ab5fe1993-01-13 12:49:46 +0000198 addr = (long) dl_getrange(size + HDR_SIZE);
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000199 dprintf(("trying to use addr %lx-%lx for sproc\n", addr, addr+size));
200 errno = 0;
201 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
202 perror("usconfig - CONF_ATTACHADDR (set)");
203 }
204#endif
205 if ((success = sproc(func, PR_SALL, arg)) < 0)
206 perror("sproc");
207#ifdef USE_DL
208 if (!local_initialized) {
209 if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
210 perror("usconfig - CONF_ATTACHADDR (reset)");
211 local_initialized = 1;
212 }
213#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000214 if (success >= 0) {
215 nthreads++;
216 pidlist[maxpidindex++] = success;
217 }
218 }
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000219 if (usunsetlock(count_lock) < 0)
220 perror("usunsetlock (count_lock)");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000221#endif
222#ifdef SOLARIS
223 (void) thread_create(0, 0, func, arg, THREAD_NEW_LWP);
224#endif
225#ifdef sun
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000226 success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000227#endif
228#ifdef C_THREADS
229 (void) cthread_fork(func, arg);
230#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000231 return success < 0 ? 0 : 1;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000232}
233
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000234static void do_exit_thread _P1(no_cleanup, int no_cleanup)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000235{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000236 dprintf(("exit_thread called\n"));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000237 if (!initialized)
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000238 if (no_cleanup)
239 _exit(0);
240 else
241 exit(0);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000242#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000243 if (ussetlock(count_lock) < 0)
244 perror("ussetlock (count_lock)");
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000245 nthreads--;
246 if (getpid() == my_pid) {
247 /* main thread; wait for other threads to exit */
248 exiting = 1;
249 if (do_exit) {
250 int i;
251
252 /* notify other threads */
Sjoerd Mullenderd10d8291992-09-11 15:19:27 +0000253 if (nthreads >= 0) {
254 dprintf(("kill other threads\n"));
255 for (i = 0; i < maxpidindex; i++)
256 (void) kill(pidlist[i], SIGKILL);
257 _exit(exit_status);
258 }
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000259 }
260 waiting_for_threads = 1;
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000261 if (ussetlock(wait_lock) < 0)
262 perror("ussetlock (wait_lock)");
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000263 for (;;) {
264 if (nthreads < 0) {
265 dprintf(("really exit (%d)\n", exit_status));
266 if (no_cleanup)
267 _exit(exit_status);
268 else
269 exit(exit_status);
270 }
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000271 if (usunsetlock(count_lock) < 0)
272 perror("usunsetlock (count_lock)");
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000273 dprintf(("waiting for other threads (%d)\n", nthreads));
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000274 if (ussetlock(wait_lock) < 0)
275 perror("ussetlock (wait_lock)");
276 if (ussetlock(count_lock) < 0)
277 perror("ussetlock (count_lock)");
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000278 }
279 }
280 /* not the main thread */
281 if (waiting_for_threads) {
282 dprintf(("main thread is waiting\n"));
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000283 if (usunsetlock(wait_lock) < 0)
284 perror("usunsetlock (wait_lock)");
Sjoerd Mullenderd10d8291992-09-11 15:19:27 +0000285 } else if (do_exit)
286 (void) kill(my_pid, SIGUSR1);
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000287 if (usunsetlock(count_lock) < 0)
288 perror("usunsetlock (count_lock)");
Guido van Rossumff4949e1992-08-05 19:58:53 +0000289 _exit(0);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000290#endif
291#ifdef SOLARIS
292 thread_exit();
293#endif
294#ifdef sun
295 lwp_destroy(SELF);
296#endif
297#ifdef C_THREADS
298 cthread_exit(0);
299#endif
300}
301
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000302void exit_thread _P0()
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000303{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000304 do_exit_thread(0);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000305}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000306
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000307void _exit_thread _P0()
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000308{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000309 do_exit_thread(1);
310}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000311
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000312static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
313{
314 dprintf(("exit_prog(%d) called\n", status));
315 if (!initialized)
316 if (no_cleanup)
317 _exit(status);
318 else
319 exit(status);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000320#ifdef __sgi
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000321 do_exit = 1;
322 exit_status = status;
323 do_exit_thread(no_cleanup);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000324#endif
325#ifdef sun
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000326 pod_exit(status);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000327#endif
328}
329
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000330void exit_prog _P1(status, int status)
331{
332 do_exit_prog(status, 0);
333}
334
335void _exit_prog _P1(status, int status)
336{
337 do_exit_prog(status, 1);
338}
339
340/*
341 * Lock support.
342 */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000343type_lock allocate_lock _P0()
344{
345#ifdef __sgi
346 ulock_t lock;
347#endif
348#ifdef sun
349 struct lock *lock;
350 extern char *malloc();
351#endif
352
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000353 dprintf(("allocate_lock called\n"));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000354 if (!initialized)
355 init_thread();
356
357#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000358 if ((lock = usnewlock(shared_arena)) == NULL)
359 perror("usnewlock");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000360 (void) usinitlock(lock);
361#endif
362#ifdef sun
363 lock = (struct lock *) malloc(sizeof(struct lock));
364 lock->lock_locked = 0;
365 (void) mon_create(&lock->lock_monitor);
366 (void) cv_create(&lock->lock_condvar, lock->lock_monitor);
367#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000368 dprintf(("allocate_lock() -> %lx\n", (long)lock));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000369 return (type_lock) lock;
370}
371
372void free_lock _P1(lock, type_lock lock)
373{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000374 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000375#ifdef __sgi
376 usfreelock((ulock_t) lock, shared_arena);
377#endif
378#ifdef sun
379 mon_destroy(((struct lock *) lock)->lock_monitor);
380 free((char *) lock);
381#endif
382}
383
384int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
385{
386 int success;
387
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000388 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000389#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000390 errno = 0; /* clear it just in case */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000391 if (waitflag)
392 success = ussetlock((ulock_t) lock);
393 else
394 success = uscsetlock((ulock_t) lock, 1); /* Try it once */
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000395 if (success < 0)
396 perror(waitflag ? "ussetlock" : "uscsetlock");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000397#endif
398#ifdef sun
399 success = 0;
400
401 (void) mon_enter(((struct lock *) lock)->lock_monitor);
402 if (waitflag)
403 while (((struct lock *) lock)->lock_locked)
404 cv_wait(((struct lock *) lock)->lock_condvar);
405 if (!((struct lock *) lock)->lock_locked) {
406 success = 1;
407 ((struct lock *) lock)->lock_locked = 1;
408 }
409 cv_broadcast(((struct lock *) lock)->lock_condvar);
410 mon_exit(((struct lock *) lock)->lock_monitor);
411#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000412 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000413 return success;
414}
415
416void release_lock _P1(lock, type_lock lock)
417{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000418 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000419#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000420 if (usunsetlock((ulock_t) lock) < 0)
421 perror("usunsetlock");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000422#endif
423#ifdef sun
424 (void) mon_enter(((struct lock *) lock)->lock_monitor);
425 ((struct lock *) lock)->lock_locked = 0;
426 cv_broadcast(((struct lock *) lock)->lock_condvar);
427 mon_exit(((struct lock *) lock)->lock_monitor);
428#endif
429}
430
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000431/*
432 * Semaphore support.
433 */
434type_sema allocate_sema _P1(value, int value)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000435{
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000436#ifdef __sgi
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000437 usema_t *sema;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000438#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000439
440 dprintf(("allocate_sema called\n"));
Sjoerd Mullenderd10d8291992-09-11 15:19:27 +0000441 if (!initialized)
442 init_thread();
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000443
444#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000445 if ((sema = usnewsema(shared_arena, value)) == NULL)
446 perror("usnewsema");
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000447 dprintf(("allocate_sema() -> %lx\n", (long) sema));
448 return (type_sema) sema;
449#endif
450}
451
452void free_sema _P1(sema, type_sema sema)
453{
454 dprintf(("free_sema(%lx) called\n", (long) sema));
455#ifdef __sgi
456 usfreesema((usema_t *) sema, shared_arena);
457#endif
458}
459
460void down_sema _P1(sema, type_sema sema)
461{
462 dprintf(("down_sema(%lx) called\n", (long) sema));
463#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000464 if (uspsema((usema_t *) sema) < 0)
465 perror("uspsema");
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000466#endif
467 dprintf(("down_sema(%lx) return\n", (long) sema));
468}
469
470void up_sema _P1(sema, type_sema sema)
471{
472 dprintf(("up_sema(%lx)\n", (long) sema));
473#ifdef __sgi
Sjoerd Mullendere8934121993-01-13 12:08:48 +0000474 if (usvsema((usema_t *) sema) < 0)
475 perror("usvsema");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000476#endif
477}