blob: a7b3114b36be29ef6b82e2485c934812cb14f277 [file] [log] [blame]
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000029
30******************************************************************/
31
32#ifdef WITH_SGI_DL
33#define USE_DL
34#endif
35
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>
44
45#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
46#define MAXPROC 100 /* max # of threads that can be started */
47
48static usptr_t *shared_arena;
49static ulock_t count_lock; /* protection for some variables */
50static ulock_t wait_lock; /* lock used to wait for other threads */
51static int waiting_for_threads; /* protected by count_lock */
52static int nthreads; /* protected by count_lock */
53static int exit_status;
54#ifndef NO_EXIT_PROG
55static int do_exit; /* indicates that the program is to exit */
56#endif
57static int exiting; /* we're already exiting (for maybe_exit) */
58static pid_t my_pid; /* PID of main thread */
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +000059static struct pidlist {
60 pid_t parent;
61 pid_t child;
62} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000063static int maxpidindex; /* # of PIDs in pidlist */
64
65#ifndef NO_EXIT_PROG
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
Guido van Rossum65d5b571998-12-21 19:32:43 +000069 * well (because of an PyThread_exit_prog()) or whether we should continue on.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000070 */
71static void exit_sig _P0()
72{
73 d2printf(("exit_sig called\n"));
74 if (exiting && getpid() == my_pid) {
75 d2printf(("already exiting\n"));
76 return;
77 }
78 if (do_exit) {
79 d2printf(("exiting in exit_sig\n"));
Guido van Rossum408027e1996-12-30 16:17:54 +000080#ifdef Py_DEBUG
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000081 if ((thread_debug & 8) == 0)
82 thread_debug &= ~1; /* don't produce debug messages */
83#endif
Guido van Rossum65d5b571998-12-21 19:32:43 +000084 PyThread_exit_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000085 }
86}
87
88/*
89 * This routine is called when a process calls exit(). If that wasn't
Guido van Rossum65d5b571998-12-21 19:32:43 +000090 * done from the library, we do as if an PyThread_exit_prog() was intended.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000091 */
92static void maybe_exit _P0()
93{
94 dprintf(("maybe_exit called\n"));
95 if (exiting) {
96 dprintf(("already exiting\n"));
97 return;
98 }
Guido van Rossum65d5b571998-12-21 19:32:43 +000099 PyThread_exit_prog(0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000100}
101#endif /* NO_EXIT_PROG */
102
103/*
104 * Initialization.
105 */
Guido van Rossum65d5b571998-12-21 19:32:43 +0000106static void PyThread__init_thread _P0()
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000107{
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 */
114
115
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 */
Guido van Rossum408027e1996-12-30 16:17:54 +0000143#ifdef Py_DEBUG
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000144 if (thread_debug & 4)
145 usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
146 else if (thread_debug & 2)
147 usconfig(CONF_LOCKTYPE, US_DEBUG);
Guido van Rossum408027e1996-12-30 16:17:54 +0000148#endif /* Py_DEBUG */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000149 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)));
161}
162
163/*
164 * Thread support.
165 */
166
167static void clean_threads _P0()
168{
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000169 int i, j;
170 pid_t mypid, pid;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000171
172 /* clean up any exited threads */
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000173 mypid = getpid();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000174 i = 0;
175 while (i < maxpidindex) {
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000176 if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000177 pid = waitpid(pid, 0, WNOHANG);
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000178 if (pid > 0) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000179 /* a thread has exited */
180 pidlist[i] = pidlist[--maxpidindex];
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000181 /* 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;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000185 continue; /* don't increment i */
186 }
187 }
188 i++;
189 }
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000190 /* 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 */
196 }
197 i++;
198 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000199}
200
Guido van Rossum65d5b571998-12-21 19:32:43 +0000201int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000202{
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 */
209
Guido van Rossum65d5b571998-12-21 19:32:43 +0000210 dprintf(("PyThread_start_new_thread called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000211 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000212 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000213 switch (ussetlock(count_lock)) {
214 case 0: return 0;
215 case -1: perror("ussetlock (count_lock)");
216 }
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);
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000227 dprintf(("trying to use addr %lx-%lx for sproc\n",
228 addr, addr+size));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000229 errno = 0;
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000230 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
231 errno != 0)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000232 perror("usconfig - CONF_ATTACHADDR (set)");
233 }
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) {
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000240 if (usconfig(CONF_ATTACHADDR, addr) < 0)
241 /* reset address */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000242 perror("usconfig - CONF_ATTACHADDR (reset)");
243 local_initialized = 1;
244 }
245#endif /* USE_DL */
246 if (success >= 0) {
247 nthreads++;
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000248 pidlist[maxpidindex].parent = getpid();
249 pidlist[maxpidindex++].child = success;
250 dprintf(("pidlist[%d] = %d\n",
251 maxpidindex-1, success));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000252 }
253 }
254 if (usunsetlock(count_lock) < 0)
255 perror("usunsetlock (count_lock)");
256 return success < 0 ? 0 : 1;
257}
258
Guido van Rossum65d5b571998-12-21 19:32:43 +0000259long PyThread_get_thread_ident _P0()
Guido van Rossume944da81994-05-23 12:43:41 +0000260{
261 return getpid();
262}
263
Guido van Rossum65d5b571998-12-21 19:32:43 +0000264static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000265{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000266 dprintf(("PyThread_exit_thread called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000267 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;
281
282 /* notify other threads */
283 clean_threads();
284 if (nthreads >= 0) {
285 dprintf(("kill other threads\n"));
286 for (i = 0; i < maxpidindex; i++)
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000287 if (pidlist[i].child > 0)
288 (void) kill(pidlist[i].child,
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000289 SIGKILL);
290 _exit(exit_status);
291 }
292 }
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);
304 }
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)");
312 }
313 }
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)");
319 }
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);
327}
328
Guido van Rossum65d5b571998-12-21 19:32:43 +0000329void PyThread_exit_thread _P0()
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000330{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000331 do_PyThread_exit_thread(0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000332}
333
Guido van Rossum65d5b571998-12-21 19:32:43 +0000334void PyThread__exit_thread _P0()
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000335{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000336 do_PyThread_exit_thread(1);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000337}
338
339#ifndef NO_EXIT_PROG
Guido van Rossum65d5b571998-12-21 19:32:43 +0000340static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000341{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000342 dprintf(("PyThread_exit_prog(%d) called\n", status));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000343 if (!initialized)
344 if (no_cleanup)
345 _exit(status);
346 else
347 exit(status);
348 do_exit = 1;
349 exit_status = status;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000350 do_PyThread_exit_thread(no_cleanup);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000351}
352
Guido van Rossum65d5b571998-12-21 19:32:43 +0000353void PyThread_exit_prog _P1(status, int status)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000354{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000355 do_PyThread_exit_prog(status, 0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000356}
357
Guido van Rossum65d5b571998-12-21 19:32:43 +0000358void PyThread__exit_prog _P1(status, int status)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000359{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000360 do_PyThread_exit_prog(status, 1);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000361}
362#endif /* NO_EXIT_PROG */
363
364/*
365 * Lock support.
366 */
Guido van Rossum65d5b571998-12-21 19:32:43 +0000367PyThread_type_lock PyThread_allocate_lock _P0()
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000368{
369 ulock_t lock;
370
Guido van Rossum65d5b571998-12-21 19:32:43 +0000371 dprintf(("PyThread_allocate_lock called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000372 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000373 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000374
375 if ((lock = usnewlock(shared_arena)) == NULL)
376 perror("usnewlock");
377 (void) usinitlock(lock);
Guido van Rossum65d5b571998-12-21 19:32:43 +0000378 dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock));
379 return (PyThread_type_lock) lock;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000380}
381
Guido van Rossum65d5b571998-12-21 19:32:43 +0000382void PyThread_free_lock _P1(lock, PyThread_type_lock lock)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000383{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000384 dprintf(("PyThread_free_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000385 usfreelock((ulock_t) lock, shared_arena);
386}
387
Guido van Rossum65d5b571998-12-21 19:32:43 +0000388int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000389{
390 int success;
391
Guido van Rossum65d5b571998-12-21 19:32:43 +0000392 dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000393 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");
Guido van Rossum65d5b571998-12-21 19:32:43 +0000400 dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000401 return success;
402}
403
Guido van Rossum65d5b571998-12-21 19:32:43 +0000404void PyThread_release_lock _P1(lock, PyThread_type_lock lock)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000405{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000406 dprintf(("PyThread_release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000407 if (usunsetlock((ulock_t) lock) < 0)
408 perror("usunsetlock");
409}
410
411/*
412 * Semaphore support.
413 */
Guido van Rossum65d5b571998-12-21 19:32:43 +0000414PyThread_type_sema PyThread_allocate_sema _P1(value, int value)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000415{
416 usema_t *sema;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000417 dprintf(("PyThread_allocate_sema called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000418 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000419 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000420
421 if ((sema = usnewsema(shared_arena, value)) == NULL)
422 perror("usnewsema");
Guido van Rossum65d5b571998-12-21 19:32:43 +0000423 dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema));
424 return (PyThread_type_sema) sema;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000425}
426
Guido van Rossum65d5b571998-12-21 19:32:43 +0000427void PyThread_free_sema _P1(sema, PyThread_type_sema sema)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000428{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000429 dprintf(("PyThread_free_sema(%lx) called\n", (long) sema));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000430 usfreesema((usema_t *) sema, shared_arena);
431}
432
Guido van Rossum65d5b571998-12-21 19:32:43 +0000433int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000434{
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000435 int success;
436
Guido van Rossum65d5b571998-12-21 19:32:43 +0000437 dprintf(("PyThread_down_sema(%lx) called\n", (long) sema));
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000438 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");
Guido van Rossum65d5b571998-12-21 19:32:43 +0000444 dprintf(("PyThread_down_sema(%lx) return\n", (long) sema));
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000445 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000446}
447
Guido van Rossum65d5b571998-12-21 19:32:43 +0000448void PyThread_up_sema _P1(sema, PyThread_type_sema sema)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000449{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000450 dprintf(("PyThread_up_sema(%lx)\n", (long) sema));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000451 if (usvsema((usema_t *) sema) < 0)
452 perror("usvsema");
453}
Guido van Rossuma027efa1997-05-05 20:56:21 +0000454
455/*
456 * Per-thread data ("key") support.
457 */
458
459struct key {
460 struct key *next;
461 long id;
462 int key;
463 void *value;
464};
465
466static struct key *keyhead = NULL;
467static int nkeys = 0;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000468static PyThread_type_lock keymutex = NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000469
470static struct key *find_key _P2(key, int key, value, void *value)
471{
472 struct key *p;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000473 long id = PyThread_get_thread_ident();
Guido van Rossuma027efa1997-05-05 20:56:21 +0000474 for (p = keyhead; p != NULL; p = p->next) {
475 if (p->id == id && p->key == key)
476 return p;
477 }
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;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000485 PyThread_acquire_lock(keymutex, 1);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000486 p->next = keyhead;
487 keyhead = p;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000488 PyThread_release_lock(keymutex);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000489 }
490 return p;
491}
492
Guido van Rossum65d5b571998-12-21 19:32:43 +0000493int PyThread_create_key _P0()
Guido van Rossuma027efa1997-05-05 20:56:21 +0000494{
495 if (keymutex == NULL)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000496 keymutex = PyThread_allocate_lock();
Guido van Rossuma027efa1997-05-05 20:56:21 +0000497 return ++nkeys;
498}
499
Guido van Rossum65d5b571998-12-21 19:32:43 +0000500void PyThread_delete_key _P1(key, int key)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000501{
502 struct key *p, **q;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000503 PyThread_acquire_lock(keymutex, 1);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000504 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! */
510 }
511 else
512 q = &p->next;
513 }
Guido van Rossum65d5b571998-12-21 19:32:43 +0000514 PyThread_release_lock(keymutex);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000515}
516
Guido van Rossum65d5b571998-12-21 19:32:43 +0000517int PyThread_set_key_value _P2(key, int key, value, void *value)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000518{
519 struct key *p = find_key(key, value);
520 if (p == NULL)
521 return -1;
522 else
523 return 0;
524}
525
Guido van Rossum65d5b571998-12-21 19:32:43 +0000526void *PyThread_get_key_value _P1(key, int key)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000527{
528 struct key *p = find_key(key, NULL);
529 if (p == NULL)
530 return NULL;
531 else
532 return p->value;
533}