Use py_resource module
[python/dscho.git] / Python / thread_sgi.h
blob654d4aec3a6c676f949163c5b06ce6670c96c30e
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 #ifdef WITH_SGI_DL
26 #define USE_DL
27 #endif
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/prctl.h>
35 #include <ulocks.h>
36 #include <errno.h>
38 #define HDR_SIZE 2680 /* sizeof(ushdr_t) */
39 #define MAXPROC 100 /* max # of threads that can be started */
41 static usptr_t *shared_arena;
42 static ulock_t count_lock; /* protection for some variables */
43 static ulock_t wait_lock; /* lock used to wait for other threads */
44 static int waiting_for_threads; /* protected by count_lock */
45 static int nthreads; /* protected by count_lock */
46 static int exit_status;
47 #ifndef NO_EXIT_PROG
48 static int do_exit; /* indicates that the program is to exit */
49 #endif
50 static int exiting; /* we're already exiting (for maybe_exit) */
51 static pid_t my_pid; /* PID of main thread */
52 static struct pidlist {
53 pid_t parent;
54 pid_t child;
55 } pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
56 static int maxpidindex; /* # of PIDs in pidlist */
58 #ifndef NO_EXIT_PROG
60 * This routine is called as a signal handler when another thread
61 * exits. When that happens, we must see whether we have to exit as
62 * well (because of an exit_prog()) or whether we should continue on.
64 static void exit_sig _P0()
66 d2printf(("exit_sig called\n"));
67 if (exiting && getpid() == my_pid) {
68 d2printf(("already exiting\n"));
69 return;
71 if (do_exit) {
72 d2printf(("exiting in exit_sig\n"));
73 #ifdef DEBUG
74 if ((thread_debug & 8) == 0)
75 thread_debug &= ~1; /* don't produce debug messages */
76 #endif
77 exit_thread();
82 * This routine is called when a process calls exit(). If that wasn't
83 * done from the library, we do as if an exit_prog() was intended.
85 static void maybe_exit _P0()
87 dprintf(("maybe_exit called\n"));
88 if (exiting) {
89 dprintf(("already exiting\n"));
90 return;
92 exit_prog(0);
94 #endif /* NO_EXIT_PROG */
97 * Initialization.
99 static void _init_thread _P0()
101 #ifndef NO_EXIT_PROG
102 struct sigaction s;
103 #endif /* NO_EXIT_PROG */
104 #ifdef USE_DL
105 long addr, size;
106 #endif /* USE_DL */
109 #ifdef USE_DL
110 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
111 perror("usconfig - CONF_INITSIZE (check)");
112 if (usconfig(CONF_INITSIZE, size) < 0)
113 perror("usconfig - CONF_INITSIZE (reset)");
114 addr = (long) dl_getrange(size + HDR_SIZE);
115 dprintf(("trying to use addr %lx-%lx for shared arena\n", addr, addr+size));
116 errno = 0;
117 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
118 perror("usconfig - CONF_ATTACHADDR (set)");
119 #endif /* USE_DL */
120 if (usconfig(CONF_INITUSERS, 16) < 0)
121 perror("usconfig - CONF_INITUSERS");
122 my_pid = getpid(); /* so that we know which is the main thread */
123 #ifndef NO_EXIT_PROG
124 atexit(maybe_exit);
125 s.sa_handler = exit_sig;
126 sigemptyset(&s.sa_mask);
127 /*sigaddset(&s.sa_mask, SIGUSR1);*/
128 s.sa_flags = 0;
129 sigaction(SIGUSR1, &s, 0);
130 if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
131 perror("prctl - PR_SETEXITSIG");
132 #endif /* NO_EXIT_PROG */
133 if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
134 perror("usconfig - CONF_ARENATYPE");
135 usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
136 #ifdef DEBUG
137 if (thread_debug & 4)
138 usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
139 else if (thread_debug & 2)
140 usconfig(CONF_LOCKTYPE, US_DEBUG);
141 #endif /* DEBUG */
142 if ((shared_arena = usinit(tmpnam(0))) == 0)
143 perror("usinit");
144 #ifdef USE_DL
145 if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
146 perror("usconfig - CONF_ATTACHADDR (reset)");
147 #endif /* USE_DL */
148 if ((count_lock = usnewlock(shared_arena)) == NULL)
149 perror("usnewlock (count_lock)");
150 (void) usinitlock(count_lock);
151 if ((wait_lock = usnewlock(shared_arena)) == NULL)
152 perror("usnewlock (wait_lock)");
153 dprintf(("arena start: %lx, arena size: %ld\n", (long) shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
157 * Thread support.
160 static void clean_threads _P0()
162 int i, j;
163 pid_t mypid, pid;
165 /* clean up any exited threads */
166 mypid = getpid();
167 i = 0;
168 while (i < maxpidindex) {
169 if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
170 pid = waitpid(pid, 0, WNOHANG);
171 if (pid > 0) {
172 /* a thread has exited */
173 pidlist[i] = pidlist[--maxpidindex];
174 /* remove references to children of dead proc */
175 for (j = 0; j < maxpidindex; j++)
176 if (pidlist[j].parent == pid)
177 pidlist[j].child = -1;
178 continue; /* don't increment i */
181 i++;
183 /* clean up the list */
184 i = 0;
185 while (i < maxpidindex) {
186 if (pidlist[i].child == -1) {
187 pidlist[i] = pidlist[--maxpidindex];
188 continue; /* don't increment i */
190 i++;
194 int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
196 #ifdef USE_DL
197 long addr, size;
198 static int local_initialized = 0;
199 #endif /* USE_DL */
200 int success = 0; /* init not needed when SOLARIS_THREADS and */
201 /* C_THREADS implemented properly */
203 dprintf(("start_new_thread called\n"));
204 if (!initialized)
205 init_thread();
206 switch (ussetlock(count_lock)) {
207 case 0: return 0;
208 case -1: perror("ussetlock (count_lock)");
210 if (maxpidindex >= MAXPROC)
211 success = -1;
212 else {
213 #ifdef USE_DL
214 if (!local_initialized) {
215 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
216 perror("usconfig - CONF_INITSIZE (check)");
217 if (usconfig(CONF_INITSIZE, size) < 0)
218 perror("usconfig - CONF_INITSIZE (reset)");
219 addr = (long) dl_getrange(size + HDR_SIZE);
220 dprintf(("trying to use addr %lx-%lx for sproc\n",
221 addr, addr+size));
222 errno = 0;
223 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
224 errno != 0)
225 perror("usconfig - CONF_ATTACHADDR (set)");
227 #endif /* USE_DL */
228 clean_threads();
229 if ((success = sproc(func, PR_SALL, arg)) < 0)
230 perror("sproc");
231 #ifdef USE_DL
232 if (!local_initialized) {
233 if (usconfig(CONF_ATTACHADDR, addr) < 0)
234 /* reset address */
235 perror("usconfig - CONF_ATTACHADDR (reset)");
236 local_initialized = 1;
238 #endif /* USE_DL */
239 if (success >= 0) {
240 nthreads++;
241 pidlist[maxpidindex].parent = getpid();
242 pidlist[maxpidindex++].child = success;
243 dprintf(("pidlist[%d] = %d\n",
244 maxpidindex-1, success));
247 if (usunsetlock(count_lock) < 0)
248 perror("usunsetlock (count_lock)");
249 return success < 0 ? 0 : 1;
252 long get_thread_ident _P0()
254 return getpid();
257 static void do_exit_thread _P1(no_cleanup, int no_cleanup)
259 dprintf(("exit_thread called\n"));
260 if (!initialized)
261 if (no_cleanup)
262 _exit(0);
263 else
264 exit(0);
265 if (ussetlock(count_lock) < 0)
266 perror("ussetlock (count_lock)");
267 nthreads--;
268 if (getpid() == my_pid) {
269 /* main thread; wait for other threads to exit */
270 exiting = 1;
271 #ifndef NO_EXIT_PROG
272 if (do_exit) {
273 int i;
275 /* notify other threads */
276 clean_threads();
277 if (nthreads >= 0) {
278 dprintf(("kill other threads\n"));
279 for (i = 0; i < maxpidindex; i++)
280 if (pidlist[i].child > 0)
281 (void) kill(pidlist[i].child,
282 SIGKILL);
283 _exit(exit_status);
286 #endif /* NO_EXIT_PROG */
287 waiting_for_threads = 1;
288 if (ussetlock(wait_lock) < 0)
289 perror("ussetlock (wait_lock)");
290 for (;;) {
291 if (nthreads < 0) {
292 dprintf(("really exit (%d)\n", exit_status));
293 if (no_cleanup)
294 _exit(exit_status);
295 else
296 exit(exit_status);
298 if (usunsetlock(count_lock) < 0)
299 perror("usunsetlock (count_lock)");
300 dprintf(("waiting for other threads (%d)\n", nthreads));
301 if (ussetlock(wait_lock) < 0)
302 perror("ussetlock (wait_lock)");
303 if (ussetlock(count_lock) < 0)
304 perror("ussetlock (count_lock)");
307 /* not the main thread */
308 if (waiting_for_threads) {
309 dprintf(("main thread is waiting\n"));
310 if (usunsetlock(wait_lock) < 0)
311 perror("usunsetlock (wait_lock)");
313 #ifndef NO_EXIT_PROG
314 else if (do_exit)
315 (void) kill(my_pid, SIGUSR1);
316 #endif /* NO_EXIT_PROG */
317 if (usunsetlock(count_lock) < 0)
318 perror("usunsetlock (count_lock)");
319 _exit(0);
322 void exit_thread _P0()
324 do_exit_thread(0);
327 void _exit_thread _P0()
329 do_exit_thread(1);
332 #ifndef NO_EXIT_PROG
333 static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
335 dprintf(("exit_prog(%d) called\n", status));
336 if (!initialized)
337 if (no_cleanup)
338 _exit(status);
339 else
340 exit(status);
341 do_exit = 1;
342 exit_status = status;
343 do_exit_thread(no_cleanup);
346 void exit_prog _P1(status, int status)
348 do_exit_prog(status, 0);
351 void _exit_prog _P1(status, int status)
353 do_exit_prog(status, 1);
355 #endif /* NO_EXIT_PROG */
358 * Lock support.
360 type_lock allocate_lock _P0()
362 ulock_t lock;
364 dprintf(("allocate_lock called\n"));
365 if (!initialized)
366 init_thread();
368 if ((lock = usnewlock(shared_arena)) == NULL)
369 perror("usnewlock");
370 (void) usinitlock(lock);
371 dprintf(("allocate_lock() -> %lx\n", (long)lock));
372 return (type_lock) lock;
375 void free_lock _P1(lock, type_lock lock)
377 dprintf(("free_lock(%lx) called\n", (long)lock));
378 usfreelock((ulock_t) lock, shared_arena);
381 int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
383 int success;
385 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
386 errno = 0; /* clear it just in case */
387 if (waitflag)
388 success = ussetlock((ulock_t) lock);
389 else
390 success = uscsetlock((ulock_t) lock, 1); /* Try it once */
391 if (success < 0)
392 perror(waitflag ? "ussetlock" : "uscsetlock");
393 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
394 return success;
397 void release_lock _P1(lock, type_lock lock)
399 dprintf(("release_lock(%lx) called\n", (long)lock));
400 if (usunsetlock((ulock_t) lock) < 0)
401 perror("usunsetlock");
405 * Semaphore support.
407 type_sema allocate_sema _P1(value, int value)
409 usema_t *sema;
410 dprintf(("allocate_sema called\n"));
411 if (!initialized)
412 init_thread();
414 if ((sema = usnewsema(shared_arena, value)) == NULL)
415 perror("usnewsema");
416 dprintf(("allocate_sema() -> %lx\n", (long) sema));
417 return (type_sema) sema;
420 void free_sema _P1(sema, type_sema sema)
422 dprintf(("free_sema(%lx) called\n", (long) sema));
423 usfreesema((usema_t *) sema, shared_arena);
426 void down_sema _P1(sema, type_sema sema)
428 dprintf(("down_sema(%lx) called\n", (long) sema));
429 if (uspsema((usema_t *) sema) < 0)
430 perror("uspsema");
431 dprintf(("down_sema(%lx) return\n", (long) sema));
434 void up_sema _P1(sema, type_sema sema)
436 dprintf(("up_sema(%lx)\n", (long) sema));
437 if (usvsema((usema_t *) sema) < 0)
438 perror("usvsema");