blob: a1ebe6d4388bb878250887a398e71a9a768c1997 [file] [log] [blame]
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00009******************************************************************/
10
11#ifdef WITH_SGI_DL
12#define USE_DL
13#endif
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <signal.h>
18#include <sys/types.h>
19#include <sys/wait.h>
20#include <sys/prctl.h>
21#include <ulocks.h>
22#include <errno.h>
23
24#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
25#define MAXPROC 100 /* max # of threads that can be started */
26
27static usptr_t *shared_arena;
28static ulock_t count_lock; /* protection for some variables */
29static ulock_t wait_lock; /* lock used to wait for other threads */
30static int waiting_for_threads; /* protected by count_lock */
31static int nthreads; /* protected by count_lock */
32static int exit_status;
33#ifndef NO_EXIT_PROG
34static int do_exit; /* indicates that the program is to exit */
35#endif
36static int exiting; /* we're already exiting (for maybe_exit) */
37static pid_t my_pid; /* PID of main thread */
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +000038static struct pidlist {
39 pid_t parent;
40 pid_t child;
41} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000042static int maxpidindex; /* # of PIDs in pidlist */
43
44#ifndef NO_EXIT_PROG
45/*
46 * This routine is called as a signal handler when another thread
47 * exits. When that happens, we must see whether we have to exit as
Guido van Rossum65d5b571998-12-21 19:32:43 +000048 * well (because of an PyThread_exit_prog()) or whether we should continue on.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000049 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000050static void exit_sig(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000051{
52 d2printf(("exit_sig called\n"));
53 if (exiting && getpid() == my_pid) {
54 d2printf(("already exiting\n"));
55 return;
56 }
57 if (do_exit) {
58 d2printf(("exiting in exit_sig\n"));
Guido van Rossum408027e1996-12-30 16:17:54 +000059#ifdef Py_DEBUG
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000060 if ((thread_debug & 8) == 0)
61 thread_debug &= ~1; /* don't produce debug messages */
62#endif
Guido van Rossum65d5b571998-12-21 19:32:43 +000063 PyThread_exit_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000064 }
65}
66
67/*
68 * This routine is called when a process calls exit(). If that wasn't
Guido van Rossum65d5b571998-12-21 19:32:43 +000069 * done from the library, we do as if an PyThread_exit_prog() was intended.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000070 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000071static void maybe_exit(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000072{
73 dprintf(("maybe_exit called\n"));
74 if (exiting) {
75 dprintf(("already exiting\n"));
76 return;
77 }
Guido van Rossum65d5b571998-12-21 19:32:43 +000078 PyThread_exit_prog(0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000079}
80#endif /* NO_EXIT_PROG */
81
82/*
83 * Initialization.
84 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000085static void PyThread__init_thread(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000086{
87#ifndef NO_EXIT_PROG
88 struct sigaction s;
89#endif /* NO_EXIT_PROG */
90#ifdef USE_DL
91 long addr, size;
92#endif /* USE_DL */
93
94
95#ifdef USE_DL
96 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
97 perror("usconfig - CONF_INITSIZE (check)");
98 if (usconfig(CONF_INITSIZE, size) < 0)
99 perror("usconfig - CONF_INITSIZE (reset)");
100 addr = (long) dl_getrange(size + HDR_SIZE);
Fred Drakea44d3532000-06-30 15:01:00 +0000101 dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000102 errno = 0;
103 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
104 perror("usconfig - CONF_ATTACHADDR (set)");
105#endif /* USE_DL */
106 if (usconfig(CONF_INITUSERS, 16) < 0)
107 perror("usconfig - CONF_INITUSERS");
108 my_pid = getpid(); /* so that we know which is the main thread */
109#ifndef NO_EXIT_PROG
110 atexit(maybe_exit);
111 s.sa_handler = exit_sig;
112 sigemptyset(&s.sa_mask);
113 /*sigaddset(&s.sa_mask, SIGUSR1);*/
114 s.sa_flags = 0;
115 sigaction(SIGUSR1, &s, 0);
116 if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
117 perror("prctl - PR_SETEXITSIG");
118#endif /* NO_EXIT_PROG */
119 if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
120 perror("usconfig - CONF_ARENATYPE");
121 usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
Guido van Rossum408027e1996-12-30 16:17:54 +0000122#ifdef Py_DEBUG
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000123 if (thread_debug & 4)
124 usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
125 else if (thread_debug & 2)
126 usconfig(CONF_LOCKTYPE, US_DEBUG);
Guido van Rossum408027e1996-12-30 16:17:54 +0000127#endif /* Py_DEBUG */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000128 if ((shared_arena = usinit(tmpnam(0))) == 0)
129 perror("usinit");
130#ifdef USE_DL
131 if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
132 perror("usconfig - CONF_ATTACHADDR (reset)");
133#endif /* USE_DL */
134 if ((count_lock = usnewlock(shared_arena)) == NULL)
135 perror("usnewlock (count_lock)");
136 (void) usinitlock(count_lock);
137 if ((wait_lock = usnewlock(shared_arena)) == NULL)
138 perror("usnewlock (wait_lock)");
Fred Drakea44d3532000-06-30 15:01:00 +0000139 dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000140}
141
142/*
143 * Thread support.
144 */
145
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000146static void clean_threads(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000147{
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000148 int i, j;
149 pid_t mypid, pid;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000150
151 /* clean up any exited threads */
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000152 mypid = getpid();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000153 i = 0;
154 while (i < maxpidindex) {
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000155 if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000156 pid = waitpid(pid, 0, WNOHANG);
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000157 if (pid > 0) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000158 /* a thread has exited */
159 pidlist[i] = pidlist[--maxpidindex];
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000160 /* remove references to children of dead proc */
161 for (j = 0; j < maxpidindex; j++)
162 if (pidlist[j].parent == pid)
163 pidlist[j].child = -1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000164 continue; /* don't increment i */
165 }
166 }
167 i++;
168 }
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000169 /* clean up the list */
170 i = 0;
171 while (i < maxpidindex) {
172 if (pidlist[i].child == -1) {
173 pidlist[i] = pidlist[--maxpidindex];
174 continue; /* don't increment i */
175 }
176 i++;
177 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000178}
179
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000180int PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000181{
182#ifdef USE_DL
183 long addr, size;
184 static int local_initialized = 0;
185#endif /* USE_DL */
186 int success = 0; /* init not needed when SOLARIS_THREADS and */
187 /* C_THREADS implemented properly */
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189 dprintf(("PyThread_start_new_thread called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000190 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000191 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000192 switch (ussetlock(count_lock)) {
193 case 0: return 0;
194 case -1: perror("ussetlock (count_lock)");
195 }
196 if (maxpidindex >= MAXPROC)
197 success = -1;
198 else {
199#ifdef USE_DL
200 if (!local_initialized) {
201 if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
202 perror("usconfig - CONF_INITSIZE (check)");
203 if (usconfig(CONF_INITSIZE, size) < 0)
204 perror("usconfig - CONF_INITSIZE (reset)");
205 addr = (long) dl_getrange(size + HDR_SIZE);
Fred Drakea44d3532000-06-30 15:01:00 +0000206 dprintf(("trying to use addr %p-%p for sproc\n",
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000207 addr, addr+size));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000208 errno = 0;
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000209 if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
210 errno != 0)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000211 perror("usconfig - CONF_ATTACHADDR (set)");
212 }
213#endif /* USE_DL */
214 clean_threads();
215 if ((success = sproc(func, PR_SALL, arg)) < 0)
216 perror("sproc");
217#ifdef USE_DL
218 if (!local_initialized) {
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000219 if (usconfig(CONF_ATTACHADDR, addr) < 0)
220 /* reset address */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000221 perror("usconfig - CONF_ATTACHADDR (reset)");
222 local_initialized = 1;
223 }
224#endif /* USE_DL */
225 if (success >= 0) {
226 nthreads++;
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000227 pidlist[maxpidindex].parent = getpid();
228 pidlist[maxpidindex++].child = success;
229 dprintf(("pidlist[%d] = %d\n",
230 maxpidindex-1, success));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000231 }
232 }
233 if (usunsetlock(count_lock) < 0)
234 perror("usunsetlock (count_lock)");
235 return success < 0 ? 0 : 1;
236}
237
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000238long PyThread_get_thread_ident(void)
Guido van Rossume944da81994-05-23 12:43:41 +0000239{
240 return getpid();
241}
242
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000243static void do_PyThread_exit_thread(int no_cleanup)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000244{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000245 dprintf(("PyThread_exit_thread called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000246 if (!initialized)
247 if (no_cleanup)
248 _exit(0);
249 else
250 exit(0);
251 if (ussetlock(count_lock) < 0)
252 perror("ussetlock (count_lock)");
253 nthreads--;
254 if (getpid() == my_pid) {
255 /* main thread; wait for other threads to exit */
256 exiting = 1;
257#ifndef NO_EXIT_PROG
258 if (do_exit) {
259 int i;
260
261 /* notify other threads */
262 clean_threads();
263 if (nthreads >= 0) {
264 dprintf(("kill other threads\n"));
265 for (i = 0; i < maxpidindex; i++)
Guido van Rossum6f5f8dd1994-05-30 13:39:05 +0000266 if (pidlist[i].child > 0)
267 (void) kill(pidlist[i].child,
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000268 SIGKILL);
269 _exit(exit_status);
270 }
271 }
272#endif /* NO_EXIT_PROG */
273 waiting_for_threads = 1;
274 if (ussetlock(wait_lock) < 0)
275 perror("ussetlock (wait_lock)");
276 for (;;) {
277 if (nthreads < 0) {
278 dprintf(("really exit (%d)\n", exit_status));
279 if (no_cleanup)
280 _exit(exit_status);
281 else
282 exit(exit_status);
283 }
284 if (usunsetlock(count_lock) < 0)
285 perror("usunsetlock (count_lock)");
286 dprintf(("waiting for other threads (%d)\n", nthreads));
287 if (ussetlock(wait_lock) < 0)
288 perror("ussetlock (wait_lock)");
289 if (ussetlock(count_lock) < 0)
290 perror("ussetlock (count_lock)");
291 }
292 }
293 /* not the main thread */
294 if (waiting_for_threads) {
295 dprintf(("main thread is waiting\n"));
296 if (usunsetlock(wait_lock) < 0)
297 perror("usunsetlock (wait_lock)");
298 }
299#ifndef NO_EXIT_PROG
300 else if (do_exit)
301 (void) kill(my_pid, SIGUSR1);
302#endif /* NO_EXIT_PROG */
303 if (usunsetlock(count_lock) < 0)
304 perror("usunsetlock (count_lock)");
305 _exit(0);
306}
307
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000308void PyThread_exit_thread(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000309{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000310 do_PyThread_exit_thread(0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000311}
312
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000313void PyThread__exit_thread(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000314{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000315 do_PyThread_exit_thread(1);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000316}
317
318#ifndef NO_EXIT_PROG
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000319static void do_PyThread_exit_prog(int status, int no_cleanup)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000320{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000321 dprintf(("PyThread_exit_prog(%d) called\n", status));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000322 if (!initialized)
323 if (no_cleanup)
324 _exit(status);
325 else
326 exit(status);
327 do_exit = 1;
328 exit_status = status;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000329 do_PyThread_exit_thread(no_cleanup);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000330}
331
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000332void PyThread_exit_prog(int status)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000333{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000334 do_PyThread_exit_prog(status, 0);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000335}
336
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000337void PyThread__exit_prog(int status)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000338{
Guido van Rossum65d5b571998-12-21 19:32:43 +0000339 do_PyThread_exit_prog(status, 1);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000340}
341#endif /* NO_EXIT_PROG */
342
343/*
344 * Lock support.
345 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000346PyThread_type_lock PyThread_allocate_lock(void)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000347{
348 ulock_t lock;
349
Guido van Rossum65d5b571998-12-21 19:32:43 +0000350 dprintf(("PyThread_allocate_lock called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000351 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000352 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000353
354 if ((lock = usnewlock(shared_arena)) == NULL)
355 perror("usnewlock");
356 (void) usinitlock(lock);
Fred Drakea44d3532000-06-30 15:01:00 +0000357 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
Guido van Rossum65d5b571998-12-21 19:32:43 +0000358 return (PyThread_type_lock) lock;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000359}
360
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000361void PyThread_free_lock(PyThread_type_lock lock)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000362{
Fred Drakea44d3532000-06-30 15:01:00 +0000363 dprintf(("PyThread_free_lock(%p) called\n", lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000364 usfreelock((ulock_t) lock, shared_arena);
365}
366
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000367int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000368{
369 int success;
370
Fred Drakea44d3532000-06-30 15:01:00 +0000371 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000372 errno = 0; /* clear it just in case */
373 if (waitflag)
374 success = ussetlock((ulock_t) lock);
375 else
376 success = uscsetlock((ulock_t) lock, 1); /* Try it once */
377 if (success < 0)
378 perror(waitflag ? "ussetlock" : "uscsetlock");
Fred Drakea44d3532000-06-30 15:01:00 +0000379 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000380 return success;
381}
382
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000383void PyThread_release_lock(PyThread_type_lock lock)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000384{
Fred Drakea44d3532000-06-30 15:01:00 +0000385 dprintf(("PyThread_release_lock(%p) called\n", lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000386 if (usunsetlock((ulock_t) lock) < 0)
387 perror("usunsetlock");
388}
389
390/*
391 * Semaphore support.
392 */
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000393PyThread_type_sema PyThread_allocate_sema(int value)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000394{
395 usema_t *sema;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000396 dprintf(("PyThread_allocate_sema called\n"));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000397 if (!initialized)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000398 PyThread_init_thread();
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000399
400 if ((sema = usnewsema(shared_arena, value)) == NULL)
401 perror("usnewsema");
Fred Drakea44d3532000-06-30 15:01:00 +0000402 dprintf(("PyThread_allocate_sema() -> %p\n", sema));
Guido van Rossum65d5b571998-12-21 19:32:43 +0000403 return (PyThread_type_sema) sema;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000404}
405
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000406void PyThread_free_sema(PyThread_type_sema sema)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000407{
Fred Drakea44d3532000-06-30 15:01:00 +0000408 dprintf(("PyThread_free_sema(%p) called\n", sema));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000409 usfreesema((usema_t *) sema, shared_arena);
410}
411
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000412int PyThread_down_sema(PyThread_type_sema sema, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000413{
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000414 int success;
415
Fred Drakea44d3532000-06-30 15:01:00 +0000416 dprintf(("PyThread_down_sema(%p) called\n", sema));
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000417 if (waitflag)
418 success = uspsema((usema_t *) sema);
419 else
420 success = uscpsema((usema_t *) sema);
421 if (success < 0)
422 perror(waitflag ? "uspsema" : "uscpsema");
Fred Drakea44d3532000-06-30 15:01:00 +0000423 dprintf(("PyThread_down_sema(%p) return\n", sema));
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000424 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000425}
426
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000427void PyThread_up_sema(PyThread_type_sema sema)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000428{
Fred Drakea44d3532000-06-30 15:01:00 +0000429 dprintf(("PyThread_up_sema(%p)\n", sema));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000430 if (usvsema((usema_t *) sema) < 0)
431 perror("usvsema");
432}
Guido van Rossuma027efa1997-05-05 20:56:21 +0000433
434/*
435 * Per-thread data ("key") support.
436 */
437
438struct key {
439 struct key *next;
440 long id;
441 int key;
442 void *value;
443};
444
445static struct key *keyhead = NULL;
446static int nkeys = 0;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000447static PyThread_type_lock keymutex = NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000448
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000449static struct key *find_key(int key, void *value)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000450{
451 struct key *p;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000452 long id = PyThread_get_thread_ident();
Guido van Rossuma027efa1997-05-05 20:56:21 +0000453 for (p = keyhead; p != NULL; p = p->next) {
454 if (p->id == id && p->key == key)
455 return p;
456 }
457 if (value == NULL)
458 return NULL;
459 p = (struct key *)malloc(sizeof(struct key));
460 if (p != NULL) {
461 p->id = id;
462 p->key = key;
463 p->value = value;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000464 PyThread_acquire_lock(keymutex, 1);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000465 p->next = keyhead;
466 keyhead = p;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000467 PyThread_release_lock(keymutex);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000468 }
469 return p;
470}
471
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000472int PyThread_create_key(void)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000473{
474 if (keymutex == NULL)
Guido van Rossum65d5b571998-12-21 19:32:43 +0000475 keymutex = PyThread_allocate_lock();
Guido van Rossuma027efa1997-05-05 20:56:21 +0000476 return ++nkeys;
477}
478
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000479void PyThread_delete_key(int key)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000480{
481 struct key *p, **q;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000482 PyThread_acquire_lock(keymutex, 1);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000483 q = &keyhead;
484 while ((p = *q) != NULL) {
485 if (p->key == key) {
486 *q = p->next;
487 free((void *)p);
488 /* NB This does *not* free p->value! */
489 }
490 else
491 q = &p->next;
492 }
Guido van Rossum65d5b571998-12-21 19:32:43 +0000493 PyThread_release_lock(keymutex);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000494}
495
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000496int PyThread_set_key_value(int key, void *value)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000497{
498 struct key *p = find_key(key, value);
499 if (p == NULL)
500 return -1;
501 else
502 return 0;
503}
504
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000505void *PyThread_get_key_value(int key)
Guido van Rossuma027efa1997-05-05 20:56:21 +0000506{
507 struct key *p = find_key(key, NULL);
508 if (p == NULL)
509 return NULL;
510 else
511 return p->value;
512}