11 #include <sys/prctl.h>
15 #define HDR_SIZE 2680 /* sizeof(ushdr_t) */
16 #define MAXPROC 100 /* max # of threads that can be started */
18 static usptr_t
*shared_arena
;
19 static ulock_t count_lock
; /* protection for some variables */
20 static ulock_t wait_lock
; /* lock used to wait for other threads */
21 static int waiting_for_threads
; /* protected by count_lock */
22 static int nthreads
; /* protected by count_lock */
23 static int exit_status
;
25 static int do_exit
; /* indicates that the program is to exit */
27 static int exiting
; /* we're already exiting (for maybe_exit) */
28 static pid_t my_pid
; /* PID of main thread */
29 static struct pidlist
{
32 } pidlist
[MAXPROC
]; /* PIDs of other threads; protected by count_lock */
33 static int maxpidindex
; /* # of PIDs in pidlist */
37 * This routine is called as a signal handler when another thread
38 * exits. When that happens, we must see whether we have to exit as
39 * well (because of an PyThread_exit_prog()) or whether we should continue on.
41 static void exit_sig(void)
43 d2printf(("exit_sig called\n"));
44 if (exiting
&& getpid() == my_pid
) {
45 d2printf(("already exiting\n"));
49 d2printf(("exiting in exit_sig\n"));
51 if ((thread_debug
& 8) == 0)
52 thread_debug
&= ~1; /* don't produce debug messages */
54 PyThread_exit_thread();
59 * This routine is called when a process calls exit(). If that wasn't
60 * done from the library, we do as if an PyThread_exit_prog() was intended.
62 static void maybe_exit(void)
64 dprintf(("maybe_exit called\n"));
66 dprintf(("already exiting\n"));
69 PyThread_exit_prog(0);
71 #endif /* NO_EXIT_PROG */
76 static void PyThread__init_thread(void)
80 #endif /* NO_EXIT_PROG */
87 if ((size
= usconfig(CONF_INITSIZE
, 64*1024)) < 0)
88 perror("usconfig - CONF_INITSIZE (check)");
89 if (usconfig(CONF_INITSIZE
, size
) < 0)
90 perror("usconfig - CONF_INITSIZE (reset)");
91 addr
= (long) dl_getrange(size
+ HDR_SIZE
);
92 dprintf(("trying to use addr %p-%p for shared arena\n", addr
, addr
+size
));
94 if ((addr
= usconfig(CONF_ATTACHADDR
, addr
)) < 0 && errno
!= 0)
95 perror("usconfig - CONF_ATTACHADDR (set)");
97 if (usconfig(CONF_INITUSERS
, 16) < 0)
98 perror("usconfig - CONF_INITUSERS");
99 my_pid
= getpid(); /* so that we know which is the main thread */
102 s
.sa_handler
= exit_sig
;
103 sigemptyset(&s
.sa_mask
);
104 /*sigaddset(&s.sa_mask, SIGUSR1);*/
106 sigaction(SIGUSR1
, &s
, 0);
107 if (prctl(PR_SETEXITSIG
, SIGUSR1
) < 0)
108 perror("prctl - PR_SETEXITSIG");
109 #endif /* NO_EXIT_PROG */
110 if (usconfig(CONF_ARENATYPE
, US_SHAREDONLY
) < 0)
111 perror("usconfig - CONF_ARENATYPE");
112 usconfig(CONF_LOCKTYPE
, US_DEBUG
); /* XXX */
114 if (thread_debug
& 4)
115 usconfig(CONF_LOCKTYPE
, US_DEBUGPLUS
);
116 else if (thread_debug
& 2)
117 usconfig(CONF_LOCKTYPE
, US_DEBUG
);
118 #endif /* Py_DEBUG */
119 if ((shared_arena
= usinit(tmpnam(0))) == 0)
122 if (usconfig(CONF_ATTACHADDR
, addr
) < 0) /* reset address */
123 perror("usconfig - CONF_ATTACHADDR (reset)");
125 if ((count_lock
= usnewlock(shared_arena
)) == NULL
)
126 perror("usnewlock (count_lock)");
127 (void) usinitlock(count_lock
);
128 if ((wait_lock
= usnewlock(shared_arena
)) == NULL
)
129 perror("usnewlock (wait_lock)");
130 dprintf(("arena start: %p, arena size: %ld\n", shared_arena
, (long) usconfig(CONF_GETSIZE
, shared_arena
)));
137 static void clean_threads(void)
142 /* clean up any exited threads */
145 while (i
< maxpidindex
) {
146 if (pidlist
[i
].parent
== mypid
&& (pid
= pidlist
[i
].child
) > 0) {
147 pid
= waitpid(pid
, 0, WNOHANG
);
149 /* a thread has exited */
150 pidlist
[i
] = pidlist
[--maxpidindex
];
151 /* remove references to children of dead proc */
152 for (j
= 0; j
< maxpidindex
; j
++)
153 if (pidlist
[j
].parent
== pid
)
154 pidlist
[j
].child
= -1;
155 continue; /* don't increment i */
160 /* clean up the list */
162 while (i
< maxpidindex
) {
163 if (pidlist
[i
].child
== -1) {
164 pidlist
[i
] = pidlist
[--maxpidindex
];
165 continue; /* don't increment i */
171 long PyThread_start_new_thread(void (*func
)(void *), void *arg
)
175 static int local_initialized
= 0;
177 int success
= 0; /* init not needed when SOLARIS_THREADS and */
178 /* C_THREADS implemented properly */
180 dprintf(("PyThread_start_new_thread called\n"));
182 PyThread_init_thread();
183 switch (ussetlock(count_lock
)) {
185 case -1: perror("ussetlock (count_lock)");
187 if (maxpidindex
>= MAXPROC
)
191 if (!local_initialized
) {
192 if ((size
= usconfig(CONF_INITSIZE
, 64*1024)) < 0)
193 perror("usconfig - CONF_INITSIZE (check)");
194 if (usconfig(CONF_INITSIZE
, size
) < 0)
195 perror("usconfig - CONF_INITSIZE (reset)");
196 addr
= (long) dl_getrange(size
+ HDR_SIZE
);
197 dprintf(("trying to use addr %p-%p for sproc\n",
200 if ((addr
= usconfig(CONF_ATTACHADDR
, addr
)) < 0 &&
202 perror("usconfig - CONF_ATTACHADDR (set)");
206 if ((success
= sproc(func
, PR_SALL
, arg
)) < 0)
209 if (!local_initialized
) {
210 if (usconfig(CONF_ATTACHADDR
, addr
) < 0)
212 perror("usconfig - CONF_ATTACHADDR (reset)");
213 local_initialized
= 1;
218 pidlist
[maxpidindex
].parent
= getpid();
219 pidlist
[maxpidindex
++].child
= success
;
220 dprintf(("pidlist[%d] = %d\n",
221 maxpidindex
-1, success
));
224 if (usunsetlock(count_lock
) < 0)
225 perror("usunsetlock (count_lock)");
229 long PyThread_get_thread_ident(void)
234 static void do_PyThread_exit_thread(int no_cleanup
)
236 dprintf(("PyThread_exit_thread called\n"));
242 if (ussetlock(count_lock
) < 0)
243 perror("ussetlock (count_lock)");
245 if (getpid() == my_pid
) {
246 /* main thread; wait for other threads to exit */
252 /* notify other threads */
255 dprintf(("kill other threads\n"));
256 for (i
= 0; i
< maxpidindex
; i
++)
257 if (pidlist
[i
].child
> 0)
258 (void) kill(pidlist
[i
].child
,
263 #endif /* NO_EXIT_PROG */
264 waiting_for_threads
= 1;
265 if (ussetlock(wait_lock
) < 0)
266 perror("ussetlock (wait_lock)");
269 dprintf(("really exit (%d)\n", exit_status
));
275 if (usunsetlock(count_lock
) < 0)
276 perror("usunsetlock (count_lock)");
277 dprintf(("waiting for other threads (%d)\n", nthreads
));
278 if (ussetlock(wait_lock
) < 0)
279 perror("ussetlock (wait_lock)");
280 if (ussetlock(count_lock
) < 0)
281 perror("ussetlock (count_lock)");
284 /* not the main thread */
285 if (waiting_for_threads
) {
286 dprintf(("main thread is waiting\n"));
287 if (usunsetlock(wait_lock
) < 0)
288 perror("usunsetlock (wait_lock)");
292 (void) kill(my_pid
, SIGUSR1
);
293 #endif /* NO_EXIT_PROG */
294 if (usunsetlock(count_lock
) < 0)
295 perror("usunsetlock (count_lock)");
299 void PyThread_exit_thread(void)
301 do_PyThread_exit_thread(0);
304 void PyThread__exit_thread(void)
306 do_PyThread_exit_thread(1);
310 static void do_PyThread_exit_prog(int status
, int no_cleanup
)
312 dprintf(("PyThread_exit_prog(%d) called\n", status
));
319 exit_status
= status
;
320 do_PyThread_exit_thread(no_cleanup
);
323 void PyThread_exit_prog(int status
)
325 do_PyThread_exit_prog(status
, 0);
328 void PyThread__exit_prog(int status
)
330 do_PyThread_exit_prog(status
, 1);
332 #endif /* NO_EXIT_PROG */
337 PyThread_type_lock
PyThread_allocate_lock(void)
341 dprintf(("PyThread_allocate_lock called\n"));
343 PyThread_init_thread();
345 if ((lock
= usnewlock(shared_arena
)) == NULL
)
347 (void) usinitlock(lock
);
348 dprintf(("PyThread_allocate_lock() -> %p\n", lock
));
349 return (PyThread_type_lock
) lock
;
352 void PyThread_free_lock(PyThread_type_lock lock
)
354 dprintf(("PyThread_free_lock(%p) called\n", lock
));
355 usfreelock((ulock_t
) lock
, shared_arena
);
358 int PyThread_acquire_lock(PyThread_type_lock lock
, int waitflag
)
362 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock
, waitflag
));
363 errno
= 0; /* clear it just in case */
365 success
= ussetlock((ulock_t
) lock
);
367 success
= uscsetlock((ulock_t
) lock
, 1); /* Try it once */
369 perror(waitflag
? "ussetlock" : "uscsetlock");
370 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock
, waitflag
, success
));
374 void PyThread_release_lock(PyThread_type_lock lock
)
376 dprintf(("PyThread_release_lock(%p) called\n", lock
));
377 if (usunsetlock((ulock_t
) lock
) < 0)
378 perror("usunsetlock");
382 * Per-thread data ("key") support.
392 static struct key
*keyhead
= NULL
;
393 static int nkeys
= 0;
394 static PyThread_type_lock keymutex
= NULL
;
396 static struct key
*find_key(int key
, void *value
)
399 long id
= PyThread_get_thread_ident();
400 for (p
= keyhead
; p
!= NULL
; p
= p
->next
) {
401 if (p
->id
== id
&& p
->key
== key
)
406 p
= (struct key
*)malloc(sizeof(struct key
));
411 PyThread_acquire_lock(keymutex
, 1);
414 PyThread_release_lock(keymutex
);
419 int PyThread_create_key(void)
421 if (keymutex
== NULL
)
422 keymutex
= PyThread_allocate_lock();
426 void PyThread_delete_key(int key
)
429 PyThread_acquire_lock(keymutex
, 1);
431 while ((p
= *q
) != NULL
) {
435 /* NB This does *not* free p->value! */
440 PyThread_release_lock(keymutex
);
443 int PyThread_set_key_value(int key
, void *value
)
445 struct key
*p
= find_key(key
, value
);
452 void *PyThread_get_key_value(int key
)
454 struct key
*p
= find_key(key
, NULL
);