blob: 877b8e1afd1fb32bde9f91ce1869475efc7dee08 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001#include "thread.h"
2
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +00003<<<<<<< thread.c
4#ifndef DEBUG
5#define DEBUG
6#endif
7
Guido van Rossumf9f2e821992-08-17 08:59:08 +00008#ifdef DEBUG
9#define dprintf(args) printf args
10#else
11#define dprintf(args)
12#endif
13
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +000014=======
15#ifdef DEBUG
16#define dprintf(args) printf args
17#else
18#define dprintf(args)
19#endif
20
21>>>>>>> 2.3
Guido van Rossum1984f1e1992-08-04 12:41:02 +000022#ifdef __sgi
23#include <stdlib.h>
24#include <stdio.h>
25#include <signal.h>
26#include <sys/types.h>
27#include <sys/prctl.h>
28#include <ulocks.h>
29
Guido van Rossumf9f2e821992-08-17 08:59:08 +000030#define MAXPROC 100 /* max # of threads that can be started */
31
Guido van Rossum1984f1e1992-08-04 12:41:02 +000032static usptr_t *shared_arena;
Guido van Rossumf9f2e821992-08-17 08:59:08 +000033static ulock_t count_lock; /* protection for some variables */
34static ulock_t wait_lock; /* lock used to wait for other threads */
35static int waiting_for_threads; /* protected by count_lock */
36static int nthreads; /* protected by count_lock */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000037static int exit_status;
38static int do_exit;
Guido van Rossumf9f2e821992-08-17 08:59:08 +000039static int exiting; /* we're already exiting (for maybe_exit) */
40static pid_t my_pid; /* PID of main thread */
41static pid_t pidlist[MAXPROC]; /* PIDs of other threads */
42static int maxpidindex; /* # of PIDs in pidlist */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000043#endif
44#ifdef sun
45#include <lwp/lwp.h>
46#include <lwp/stackdep.h>
47
Guido van Rossumf9f2e821992-08-17 08:59:08 +000048#define STACKSIZE 1000 /* stacksize for a thread */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000049#define NSTACKS 2 /* # stacks to be put in cache initialy */
50
51struct lock {
52 int lock_locked;
53 cv_t lock_condvar;
54 mon_t lock_monitor;
55};
56#endif
57#ifdef C_THREADS
58#include <cthreads.h>
59#endif
60
61#ifdef __STDC__
62#define _P(args) args
63#define _P0() (void)
64#define _P1(v,t) (t)
65#define _P2(v1,t1,v2,t2) (t1,t2)
66#else
67#define _P(args) ()
68#define _P0() ()
69#define _P1(v,t) (v) t;
70#define _P2(v1,t1,v2,t2) (v1,v2) t1; t2;
71#endif
72
73static int initialized;
74
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +000075<<<<<<< thread.c
76#ifdef __sgi
77/*
78 * This routine is called as a signal handler when another thread
79 * exits. When that happens, we must see whether we have to exit as
80 * well (because of an exit_prog()) or whether we should continue on.
81 */
82static void exit_sig _P0()
83{
84 dprintf(("exit_sig called\n"));
85 if (exiting && getpid() == my_pid) {
86 dprintf(("already exiting\n"));
87 return;
88 }
89 if (do_exit) {
90 dprintf(("exiting in exit_sig\n"));
91 exit_thread();
92 }
93}
94
95/*
96 * This routine is called when a process calls exit(). If that wasn't
97 * done from the library, we do as if an exit_prog() was intended.
98 */
99static void maybe_exit _P0()
100{
101 dprintf(("maybe_exit called\n"));
102 if (exiting) {
103 dprintf(("already exiting\n"));
104 return;
105 }
106 exit_prog(0);
107}
108#endif
109
110/*
111 * Initialization.
112 */
113void init_thread _P0()
114{
115#ifdef __sgi
116 struct sigaction s;
117#endif
118
119 dprintf(("init_thread called\n"));
120 if (initialized)
121 return;
122 initialized = 1;
123
124#ifdef __sgi
125 my_pid = getpid(); /* so that we know which is the main thread */
126 atexit(maybe_exit);
127 s.sa_handler = exit_sig;
128 sigemptyset(&s.sa_mask);
129 sigaddset(&s.sa_mask, SIGUSR1);
130 s.sa_flags = 0;
131 sigaction(SIGUSR1, &s, 0);
132 prctl(PR_SETEXITSIG, SIGUSR1);
133 usconfig(CONF_ARENATYPE, US_SHAREDONLY);
134 /*usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);*/
135 shared_arena = usinit(tmpnam(0));
136 count_lock = usnewlock(shared_arena);
137 (void) usinitlock(count_lock);
138 wait_lock = usnewlock(shared_arena);
139#endif
140#ifdef sun
141 lwp_setstkcache(STACKSIZE, NSTACKS);
142#endif
143#ifdef C_THREADS
144 cthread_init();
145#endif
146}
147
148/*
149 * Thread support.
150 */
151=======
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000152#ifdef __sgi
153/*
154 * This routine is called as a signal handler when another thread
155 * exits. When that happens, we must see whether we have to exit as
156 * well (because of an exit_prog()) or whether we should continue on.
157 */
158static void exit_sig _P0()
159{
160 dprintf(("exit_sig called\n"));
161 if (exiting && getpid() == my_pid) {
162 dprintf(("already exiting\n"));
163 return;
164 }
165 if (do_exit) {
166 dprintf(("exiting in exit_sig\n"));
167 exit_thread();
168 }
169}
170
171/*
172 * This routune is called when a process calls exit(). If that wasn't
173 * done from the library, we do as if an exit_prog() was intended.
174 */
175static void maybe_exit _P0()
176{
177 dprintf(("maybe_exit called\n"));
178 if (exiting) {
179 dprintf(("already exiting\n"));
180 return;
181 }
182 exit_prog(0);
183}
184#endif
185
186/*
187 * Initialization.
188 */
189void init_thread _P0()
190{
191#ifdef __sgi
192 struct sigaction s;
193#endif
194
195 dprintf(("init_thread called\n"));
196 if (initialized)
197 return;
198 initialized = 1;
199
200#ifdef __sgi
201 my_pid = getpid(); /* so that we know which is the main thread */
202 atexit(maybe_exit);
203 s.sa_handler = exit_sig;
204 sigemptyset(&s.sa_mask);
205 sigaddset(&s.sa_mask, SIGUSR1);
206 s.sa_flags = 0;
207 sigaction(SIGUSR1, &s, 0);
208 prctl(PR_SETEXITSIG, SIGUSR1);
209 usconfig(CONF_ARENATYPE, US_SHAREDONLY);
210 /*usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);*/
211 shared_arena = usinit(tmpnam(0));
212 count_lock = usnewlock(shared_arena);
213 (void) usinitlock(count_lock);
214 wait_lock = usnewlock(shared_arena);
215#endif
216#ifdef sun
217 lwp_setstkcache(STACKSIZE, NSTACKS);
218#endif
219#ifdef C_THREADS
220 cthread_init();
221#endif
222}
223
224/*
225 * Thread support.
226 */
Sjoerd Mullenderaee8bc11992-09-02 11:25:37 +0000227>>>>>>> 2.3
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000228int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
229{
230#ifdef sun
231 thread_t tid;
232#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000233 int success = 0; /* init not needed when SOLARIS and */
234 /* C_THREADS implemented properly */
235
236 dprintf(("start_new_thread called\n"));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000237 if (!initialized)
238 init_thread();
239#ifdef __sgi
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000240 if (ussetlock(count_lock) == 0)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000241 return 0;
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000242 if (maxpidindex >= MAXPROC)
243 success = -1;
244 else {
245 success = sproc(func, PR_SALL, arg);
246 if (success >= 0) {
247 nthreads++;
248 pidlist[maxpidindex++] = success;
249 }
250 }
251 (void) usunsetlock(count_lock);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000252#endif
253#ifdef SOLARIS
254 (void) thread_create(0, 0, func, arg, THREAD_NEW_LWP);
255#endif
256#ifdef sun
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000257 success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000258#endif
259#ifdef C_THREADS
260 (void) cthread_fork(func, arg);
261#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000262 return success < 0 ? 0 : 1;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000263}
264
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000265static void do_exit_thread _P1(no_cleanup, int no_cleanup)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000266{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000267 dprintf(("exit_thread called\n"));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000268 if (!initialized)
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000269 if (no_cleanup)
270 _exit(0);
271 else
272 exit(0);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000273#ifdef __sgi
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000274 (void) ussetlock(count_lock);
275 nthreads--;
276 if (getpid() == my_pid) {
277 /* main thread; wait for other threads to exit */
278 exiting = 1;
279 if (do_exit) {
280 int i;
281
282 /* notify other threads */
283 for (i = 0; i < maxpidindex; i++)
284 (void) kill(pidlist[i], SIGUSR1);
285 }
286 waiting_for_threads = 1;
287 ussetlock(wait_lock);
288 for (;;) {
289 if (nthreads < 0) {
290 dprintf(("really exit (%d)\n", exit_status));
291 if (no_cleanup)
292 _exit(exit_status);
293 else
294 exit(exit_status);
295 }
296 usunsetlock(count_lock);
297 dprintf(("waiting for other threads (%d)\n", nthreads));
298 ussetlock(wait_lock);
299 ussetlock(count_lock);
300 }
301 }
302 /* not the main thread */
303 if (waiting_for_threads) {
304 dprintf(("main thread is waiting\n"));
305 usunsetlock(wait_lock);
306 }
307 (void) usunsetlock(count_lock);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000308 _exit(0);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000309#endif
310#ifdef SOLARIS
311 thread_exit();
312#endif
313#ifdef sun
314 lwp_destroy(SELF);
315#endif
316#ifdef C_THREADS
317 cthread_exit(0);
318#endif
319}
320
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000321void exit_thread _P0()
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000322{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000323 do_exit_thread(0);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000324}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000325
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000326void _exit_thread _P0()
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000327{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000328 do_exit_thread(1);
329}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000330
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000331static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
332{
333 dprintf(("exit_prog(%d) called\n", status));
334 if (!initialized)
335 if (no_cleanup)
336 _exit(status);
337 else
338 exit(status);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000339#ifdef __sgi
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000340 do_exit = 1;
341 exit_status = status;
342 do_exit_thread(no_cleanup);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000343#endif
344#ifdef sun
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000345 pod_exit(status);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000346#endif
347}
348
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000349void exit_prog _P1(status, int status)
350{
351 do_exit_prog(status, 0);
352}
353
354void _exit_prog _P1(status, int status)
355{
356 do_exit_prog(status, 1);
357}
358
359/*
360 * Lock support.
361 */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000362type_lock allocate_lock _P0()
363{
364#ifdef __sgi
365 ulock_t lock;
366#endif
367#ifdef sun
368 struct lock *lock;
369 extern char *malloc();
370#endif
371
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000372 dprintf(("allocate_lock called\n"));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000373 if (!initialized)
374 init_thread();
375
376#ifdef __sgi
377 lock = usnewlock(shared_arena);
378 (void) usinitlock(lock);
379#endif
380#ifdef sun
381 lock = (struct lock *) malloc(sizeof(struct lock));
382 lock->lock_locked = 0;
383 (void) mon_create(&lock->lock_monitor);
384 (void) cv_create(&lock->lock_condvar, lock->lock_monitor);
385#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000386 dprintf(("allocate_lock() -> %lx\n", (long)lock));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000387 return (type_lock) lock;
388}
389
390void free_lock _P1(lock, type_lock lock)
391{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000392 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000393#ifdef __sgi
394 usfreelock((ulock_t) lock, shared_arena);
395#endif
396#ifdef sun
397 mon_destroy(((struct lock *) lock)->lock_monitor);
398 free((char *) lock);
399#endif
400}
401
402int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
403{
404 int success;
405
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000406 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000407#ifdef __sgi
408 if (waitflag)
409 success = ussetlock((ulock_t) lock);
410 else
411 success = uscsetlock((ulock_t) lock, 1); /* Try it once */
412#endif
413#ifdef sun
414 success = 0;
415
416 (void) mon_enter(((struct lock *) lock)->lock_monitor);
417 if (waitflag)
418 while (((struct lock *) lock)->lock_locked)
419 cv_wait(((struct lock *) lock)->lock_condvar);
420 if (!((struct lock *) lock)->lock_locked) {
421 success = 1;
422 ((struct lock *) lock)->lock_locked = 1;
423 }
424 cv_broadcast(((struct lock *) lock)->lock_condvar);
425 mon_exit(((struct lock *) lock)->lock_monitor);
426#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000427 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000428 return success;
429}
430
431void release_lock _P1(lock, type_lock lock)
432{
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000433 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000434#ifdef __sgi
435 (void) usunsetlock((ulock_t) lock);
436#endif
437#ifdef sun
438 (void) mon_enter(((struct lock *) lock)->lock_monitor);
439 ((struct lock *) lock)->lock_locked = 0;
440 cv_broadcast(((struct lock *) lock)->lock_condvar);
441 mon_exit(((struct lock *) lock)->lock_monitor);
442#endif
443}
444
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000445/*
446 * Semaphore support.
447 */
448type_sema allocate_sema _P1(value, int value)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000449{
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000450#ifdef __sgi
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000451 usema_t *sema;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000452#endif
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000453
454 dprintf(("allocate_sema called\n"));
455
456#ifdef __sgi
457 sema = usnewsema(shared_arena, value);
458 dprintf(("allocate_sema() -> %lx\n", (long) sema));
459 return (type_sema) sema;
460#endif
461}
462
463void free_sema _P1(sema, type_sema sema)
464{
465 dprintf(("free_sema(%lx) called\n", (long) sema));
466#ifdef __sgi
467 usfreesema((usema_t *) sema, shared_arena);
468#endif
469}
470
471void down_sema _P1(sema, type_sema sema)
472{
473 dprintf(("down_sema(%lx) called\n", (long) sema));
474#ifdef __sgi
475 (void) uspsema((usema_t *) sema);
476#endif
477 dprintf(("down_sema(%lx) return\n", (long) sema));
478}
479
480void up_sema _P1(sema, type_sema sema)
481{
482 dprintf(("up_sema(%lx)\n", (long) sema));
483#ifdef __sgi
484 (void) usvsema((usema_t *) sema);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000485#endif
486}