Fix an amazing number of typos & malformed sentences reported by Detlef
[python/dscho.git] / Python / thread_sgi.h
bloba7b3114b36be29ef6b82e2485c934812cb14f277
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 or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 #ifdef WITH_SGI_DL
33 #define USE_DL
34 #endif
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <signal.h>
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <sys/prctl.h>
42 #include <ulocks.h>
43 #include <errno.h>
45 #define HDR_SIZE 2680 /* sizeof(ushdr_t) */
46 #define MAXPROC 100 /* max # of threads that can be started */
48 static usptr_t *shared_arena;
49 static ulock_t count_lock; /* protection for some variables */
50 static ulock_t wait_lock; /* lock used to wait for other threads */
51 static int waiting_for_threads; /* protected by count_lock */
52 static int nthreads; /* protected by count_lock */
53 static int exit_status;
54 #ifndef NO_EXIT_PROG
55 static int do_exit; /* indicates that the program is to exit */
56 #endif
57 static int exiting; /* we're already exiting (for maybe_exit) */
58 static pid_t my_pid; /* PID of main thread */
59 static struct pidlist {
60 pid_t parent;
61 pid_t child;
62 } pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
63 static int maxpidindex; /* # of PIDs in pidlist */
65 #ifndef NO_EXIT_PROG
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 PyThread_exit_prog()) or whether we should continue on.
71 static void exit_sig _P0()
73 d2printf(("exit_sig called\n"));
74 if (exiting && getpid() == my_pid) {
75 d2printf(("already exiting\n"));
76 return;
78 if (do_exit) {
79 d2printf(("exiting in exit_sig\n"));
80 #ifdef Py_DEBUG
81 if ((thread_debug & 8) == 0)
82 thread_debug &= ~1; /* don't produce debug messages */
83 #endif
84 PyThread_exit_thread();
89 * This routine is called when a process calls exit(). If that wasn't
90 * done from the library, we do as if an PyThread_exit_prog() was intended.
92 static void maybe_exit _P0()
94 dprintf(("maybe_exit called\n"));
95 if (exiting) {
96 dprintf(("already exiting\n"));
97 return;
99 PyThread_exit_prog(0);
101 #endif /* NO_EXIT_PROG */
104 * Initialization.
106 static void PyThread__init_thread _P0()
108 #ifndef NO_EXIT_PROG
109 struct sigaction s;
110 #endif /* NO_EXIT_PROG */
111 #ifdef USE_DL
112 long addr, size;
113 #endif /* USE_DL */
116 #ifdef USE_DL
117 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
118 perror("usconfig - CONF_INITSIZE (check)");
119 if (usconfig(CONF_INITSIZE, size) < 0)
120 perror("usconfig - CONF_INITSIZE (reset)");
121 addr = (long) dl_getrange(size + HDR_SIZE);
122 dprintf(("trying to use addr %lx-%lx for shared arena\n", addr, addr+size));
123 errno = 0;
124 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
125 perror("usconfig - CONF_ATTACHADDR (set)");
126 #endif /* USE_DL */
127 if (usconfig(CONF_INITUSERS, 16) < 0)
128 perror("usconfig - CONF_INITUSERS");
129 my_pid = getpid(); /* so that we know which is the main thread */
130 #ifndef NO_EXIT_PROG
131 atexit(maybe_exit);
132 s.sa_handler = exit_sig;
133 sigemptyset(&s.sa_mask);
134 /*sigaddset(&s.sa_mask, SIGUSR1);*/
135 s.sa_flags = 0;
136 sigaction(SIGUSR1, &s, 0);
137 if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
138 perror("prctl - PR_SETEXITSIG");
139 #endif /* NO_EXIT_PROG */
140 if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
141 perror("usconfig - CONF_ARENATYPE");
142 usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
143 #ifdef Py_DEBUG
144 if (thread_debug & 4)
145 usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
146 else if (thread_debug & 2)
147 usconfig(CONF_LOCKTYPE, US_DEBUG);
148 #endif /* Py_DEBUG */
149 if ((shared_arena = usinit(tmpnam(0))) == 0)
150 perror("usinit");
151 #ifdef USE_DL
152 if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
153 perror("usconfig - CONF_ATTACHADDR (reset)");
154 #endif /* USE_DL */
155 if ((count_lock = usnewlock(shared_arena)) == NULL)
156 perror("usnewlock (count_lock)");
157 (void) usinitlock(count_lock);
158 if ((wait_lock = usnewlock(shared_arena)) == NULL)
159 perror("usnewlock (wait_lock)");
160 dprintf(("arena start: %lx, arena size: %ld\n", (long) shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
164 * Thread support.
167 static void clean_threads _P0()
169 int i, j;
170 pid_t mypid, pid;
172 /* clean up any exited threads */
173 mypid = getpid();
174 i = 0;
175 while (i < maxpidindex) {
176 if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
177 pid = waitpid(pid, 0, WNOHANG);
178 if (pid > 0) {
179 /* a thread has exited */
180 pidlist[i] = pidlist[--maxpidindex];
181 /* remove references to children of dead proc */
182 for (j = 0; j < maxpidindex; j++)
183 if (pidlist[j].parent == pid)
184 pidlist[j].child = -1;
185 continue; /* don't increment i */
188 i++;
190 /* clean up the list */
191 i = 0;
192 while (i < maxpidindex) {
193 if (pidlist[i].child == -1) {
194 pidlist[i] = pidlist[--maxpidindex];
195 continue; /* don't increment i */
197 i++;
201 int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
203 #ifdef USE_DL
204 long addr, size;
205 static int local_initialized = 0;
206 #endif /* USE_DL */
207 int success = 0; /* init not needed when SOLARIS_THREADS and */
208 /* C_THREADS implemented properly */
210 dprintf(("PyThread_start_new_thread called\n"));
211 if (!initialized)
212 PyThread_init_thread();
213 switch (ussetlock(count_lock)) {
214 case 0: return 0;
215 case -1: perror("ussetlock (count_lock)");
217 if (maxpidindex >= MAXPROC)
218 success = -1;
219 else {
220 #ifdef USE_DL
221 if (!local_initialized) {
222 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
223 perror("usconfig - CONF_INITSIZE (check)");
224 if (usconfig(CONF_INITSIZE, size) < 0)
225 perror("usconfig - CONF_INITSIZE (reset)");
226 addr = (long) dl_getrange(size + HDR_SIZE);
227 dprintf(("trying to use addr %lx-%lx for sproc\n",
228 addr, addr+size));
229 errno = 0;
230 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
231 errno != 0)
232 perror("usconfig - CONF_ATTACHADDR (set)");
234 #endif /* USE_DL */
235 clean_threads();
236 if ((success = sproc(func, PR_SALL, arg)) < 0)
237 perror("sproc");
238 #ifdef USE_DL
239 if (!local_initialized) {
240 if (usconfig(CONF_ATTACHADDR, addr) < 0)
241 /* reset address */
242 perror("usconfig - CONF_ATTACHADDR (reset)");
243 local_initialized = 1;
245 #endif /* USE_DL */
246 if (success >= 0) {
247 nthreads++;
248 pidlist[maxpidindex].parent = getpid();
249 pidlist[maxpidindex++].child = success;
250 dprintf(("pidlist[%d] = %d\n",
251 maxpidindex-1, success));
254 if (usunsetlock(count_lock) < 0)
255 perror("usunsetlock (count_lock)");
256 return success < 0 ? 0 : 1;
259 long PyThread_get_thread_ident _P0()
261 return getpid();
264 static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup)
266 dprintf(("PyThread_exit_thread called\n"));
267 if (!initialized)
268 if (no_cleanup)
269 _exit(0);
270 else
271 exit(0);
272 if (ussetlock(count_lock) < 0)
273 perror("ussetlock (count_lock)");
274 nthreads--;
275 if (getpid() == my_pid) {
276 /* main thread; wait for other threads to exit */
277 exiting = 1;
278 #ifndef NO_EXIT_PROG
279 if (do_exit) {
280 int i;
282 /* notify other threads */
283 clean_threads();
284 if (nthreads >= 0) {
285 dprintf(("kill other threads\n"));
286 for (i = 0; i < maxpidindex; i++)
287 if (pidlist[i].child > 0)
288 (void) kill(pidlist[i].child,
289 SIGKILL);
290 _exit(exit_status);
293 #endif /* NO_EXIT_PROG */
294 waiting_for_threads = 1;
295 if (ussetlock(wait_lock) < 0)
296 perror("ussetlock (wait_lock)");
297 for (;;) {
298 if (nthreads < 0) {
299 dprintf(("really exit (%d)\n", exit_status));
300 if (no_cleanup)
301 _exit(exit_status);
302 else
303 exit(exit_status);
305 if (usunsetlock(count_lock) < 0)
306 perror("usunsetlock (count_lock)");
307 dprintf(("waiting for other threads (%d)\n", nthreads));
308 if (ussetlock(wait_lock) < 0)
309 perror("ussetlock (wait_lock)");
310 if (ussetlock(count_lock) < 0)
311 perror("ussetlock (count_lock)");
314 /* not the main thread */
315 if (waiting_for_threads) {
316 dprintf(("main thread is waiting\n"));
317 if (usunsetlock(wait_lock) < 0)
318 perror("usunsetlock (wait_lock)");
320 #ifndef NO_EXIT_PROG
321 else if (do_exit)
322 (void) kill(my_pid, SIGUSR1);
323 #endif /* NO_EXIT_PROG */
324 if (usunsetlock(count_lock) < 0)
325 perror("usunsetlock (count_lock)");
326 _exit(0);
329 void PyThread_exit_thread _P0()
331 do_PyThread_exit_thread(0);
334 void PyThread__exit_thread _P0()
336 do_PyThread_exit_thread(1);
339 #ifndef NO_EXIT_PROG
340 static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
342 dprintf(("PyThread_exit_prog(%d) called\n", status));
343 if (!initialized)
344 if (no_cleanup)
345 _exit(status);
346 else
347 exit(status);
348 do_exit = 1;
349 exit_status = status;
350 do_PyThread_exit_thread(no_cleanup);
353 void PyThread_exit_prog _P1(status, int status)
355 do_PyThread_exit_prog(status, 0);
358 void PyThread__exit_prog _P1(status, int status)
360 do_PyThread_exit_prog(status, 1);
362 #endif /* NO_EXIT_PROG */
365 * Lock support.
367 PyThread_type_lock PyThread_allocate_lock _P0()
369 ulock_t lock;
371 dprintf(("PyThread_allocate_lock called\n"));
372 if (!initialized)
373 PyThread_init_thread();
375 if ((lock = usnewlock(shared_arena)) == NULL)
376 perror("usnewlock");
377 (void) usinitlock(lock);
378 dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock));
379 return (PyThread_type_lock) lock;
382 void PyThread_free_lock _P1(lock, PyThread_type_lock lock)
384 dprintf(("PyThread_free_lock(%lx) called\n", (long)lock));
385 usfreelock((ulock_t) lock, shared_arena);
388 int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag)
390 int success;
392 dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
393 errno = 0; /* clear it just in case */
394 if (waitflag)
395 success = ussetlock((ulock_t) lock);
396 else
397 success = uscsetlock((ulock_t) lock, 1); /* Try it once */
398 if (success < 0)
399 perror(waitflag ? "ussetlock" : "uscsetlock");
400 dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
401 return success;
404 void PyThread_release_lock _P1(lock, PyThread_type_lock lock)
406 dprintf(("PyThread_release_lock(%lx) called\n", (long)lock));
407 if (usunsetlock((ulock_t) lock) < 0)
408 perror("usunsetlock");
412 * Semaphore support.
414 PyThread_type_sema PyThread_allocate_sema _P1(value, int value)
416 usema_t *sema;
417 dprintf(("PyThread_allocate_sema called\n"));
418 if (!initialized)
419 PyThread_init_thread();
421 if ((sema = usnewsema(shared_arena, value)) == NULL)
422 perror("usnewsema");
423 dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema));
424 return (PyThread_type_sema) sema;
427 void PyThread_free_sema _P1(sema, PyThread_type_sema sema)
429 dprintf(("PyThread_free_sema(%lx) called\n", (long) sema));
430 usfreesema((usema_t *) sema, shared_arena);
433 int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag)
435 int success;
437 dprintf(("PyThread_down_sema(%lx) called\n", (long) sema));
438 if (waitflag)
439 success = uspsema((usema_t *) sema);
440 else
441 success = uscpsema((usema_t *) sema);
442 if (success < 0)
443 perror(waitflag ? "uspsema" : "uscpsema");
444 dprintf(("PyThread_down_sema(%lx) return\n", (long) sema));
445 return success;
448 void PyThread_up_sema _P1(sema, PyThread_type_sema sema)
450 dprintf(("PyThread_up_sema(%lx)\n", (long) sema));
451 if (usvsema((usema_t *) sema) < 0)
452 perror("usvsema");
456 * Per-thread data ("key") support.
459 struct key {
460 struct key *next;
461 long id;
462 int key;
463 void *value;
466 static struct key *keyhead = NULL;
467 static int nkeys = 0;
468 static PyThread_type_lock keymutex = NULL;
470 static struct key *find_key _P2(key, int key, value, void *value)
472 struct key *p;
473 long id = PyThread_get_thread_ident();
474 for (p = keyhead; p != NULL; p = p->next) {
475 if (p->id == id && p->key == key)
476 return p;
478 if (value == NULL)
479 return NULL;
480 p = (struct key *)malloc(sizeof(struct key));
481 if (p != NULL) {
482 p->id = id;
483 p->key = key;
484 p->value = value;
485 PyThread_acquire_lock(keymutex, 1);
486 p->next = keyhead;
487 keyhead = p;
488 PyThread_release_lock(keymutex);
490 return p;
493 int PyThread_create_key _P0()
495 if (keymutex == NULL)
496 keymutex = PyThread_allocate_lock();
497 return ++nkeys;
500 void PyThread_delete_key _P1(key, int key)
502 struct key *p, **q;
503 PyThread_acquire_lock(keymutex, 1);
504 q = &keyhead;
505 while ((p = *q) != NULL) {
506 if (p->key == key) {
507 *q = p->next;
508 free((void *)p);
509 /* NB This does *not* free p->value! */
511 else
512 q = &p->next;
514 PyThread_release_lock(keymutex);
517 int PyThread_set_key_value _P2(key, int key, value, void *value)
519 struct key *p = find_key(key, value);
520 if (p == NULL)
521 return -1;
522 else
523 return 0;
526 void *PyThread_get_key_value _P1(key, int key)
528 struct key *p = find_key(key, NULL);
529 if (p == NULL)
530 return NULL;
531 else
532 return p->value;