History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Python/thread_sgi.h (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Python/thread_sgi.h+375−0
@@ -0,0 +1,375 @@
1+
2+#include <stdlib.h>
3+#include <stdio.h>
4+#include <signal.h>
5+#include <sys/types.h>
6+#include <sys/wait.h>
7+#include <sys/prctl.h>
8+#include <ulocks.h>
9+#include <errno.h>
10+
11+#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
12+#define MAXPROC 100 /* max # of threads that can be started */
13+
14+static usptr_t *shared_arena;
15+static ulock_t count_lock; /* protection for some variables */
16+static ulock_t wait_lock; /* lock used to wait for other threads */
17+static int waiting_for_threads; /* protected by count_lock */
18+static int nthreads; /* protected by count_lock */
19+static int exit_status;
20+#ifndef NO_EXIT_PROG
21+static int do_exit; /* indicates that the program is to exit */
22+#endif
23+static int exiting; /* we're already exiting (for maybe_exit) */
24+static pid_t my_pid; /* PID of main thread */
25+static struct pidlist {
26+ pid_t parent;
27+ pid_t child;
28+} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
29+static int maxpidindex; /* # of PIDs in pidlist */
30+
31+#ifndef NO_EXIT_PROG
32+/*
33+ * This routine is called as a signal handler when another thread
34+ * exits. When that happens, we must see whether we have to exit as
35+ * well (because of an PyThread_exit_prog()) or whether we should continue on.
36+ */
37+static void exit_sig(void)
38+{
39+ d2printf(("exit_sig called\n"));
40+ if (exiting && getpid() == my_pid) {
41+ d2printf(("already exiting\n"));
42+ return;
43+ }
44+ if (do_exit) {
45+ d2printf(("exiting in exit_sig\n"));
46+#ifdef Py_DEBUG
47+ if ((thread_debug & 8) == 0)
48+ thread_debug &= ~1; /* don't produce debug messages */
49+#endif
50+ PyThread_exit_thread();
51+ }
52+}
53+
54+/*
55+ * This routine is called when a process calls exit(). If that wasn't
56+ * done from the library, we do as if an PyThread_exit_prog() was intended.
57+ */
58+static void maybe_exit(void)
59+{
60+ dprintf(("maybe_exit called\n"));
61+ if (exiting) {
62+ dprintf(("already exiting\n"));
63+ return;
64+ }
65+ PyThread_exit_prog(0);
66+}
67+#endif /* NO_EXIT_PROG */
68+
69+/*
70+ * Initialization.
71+ */
72+static void PyThread__init_thread(void)
73+{
74+#ifndef NO_EXIT_PROG
75+ struct sigaction s;
76+#endif /* NO_EXIT_PROG */
77+#ifdef USE_DL
78+ long addr, size;
79+#endif /* USE_DL */
80+
81+
82+#ifdef USE_DL
83+ if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
84+ perror("usconfig - CONF_INITSIZE (check)");
85+ if (usconfig(CONF_INITSIZE, size) < 0)
86+ perror("usconfig - CONF_INITSIZE (reset)");
87+ addr = (long) dl_getrange(size + HDR_SIZE);
88+ dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
89+ errno = 0;
90+ if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
91+ perror("usconfig - CONF_ATTACHADDR (set)");
92+#endif /* USE_DL */
93+ if (usconfig(CONF_INITUSERS, 16) < 0)
94+ perror("usconfig - CONF_INITUSERS");
95+ my_pid = getpid(); /* so that we know which is the main thread */
96+#ifndef NO_EXIT_PROG
97+ atexit(maybe_exit);
98+ s.sa_handler = exit_sig;
99+ sigemptyset(&s.sa_mask);
100+ /*sigaddset(&s.sa_mask, SIGUSR1);*/
101+ s.sa_flags = 0;
102+ sigaction(SIGUSR1, &s, 0);
103+ if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
104+ perror("prctl - PR_SETEXITSIG");
105+#endif /* NO_EXIT_PROG */
106+ if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
107+ perror("usconfig - CONF_ARENATYPE");
108+ usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
109+#ifdef Py_DEBUG
110+ if (thread_debug & 4)
111+ usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
112+ else if (thread_debug & 2)
113+ usconfig(CONF_LOCKTYPE, US_DEBUG);
114+#endif /* Py_DEBUG */
115+ if ((shared_arena = usinit(tmpnam(0))) == 0)
116+ perror("usinit");
117+#ifdef USE_DL
118+ if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
119+ perror("usconfig - CONF_ATTACHADDR (reset)");
120+#endif /* USE_DL */
121+ if ((count_lock = usnewlock(shared_arena)) == NULL)
122+ perror("usnewlock (count_lock)");
123+ (void) usinitlock(count_lock);
124+ if ((wait_lock = usnewlock(shared_arena)) == NULL)
125+ perror("usnewlock (wait_lock)");
126+ dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
127+}
128+
129+/*
130+ * Thread support.
131+ */
132+
133+static void clean_threads(void)
134+{
135+ int i, j;
136+ pid_t mypid, pid;
137+
138+ /* clean up any exited threads */
139+ mypid = getpid();
140+ i = 0;
141+ while (i < maxpidindex) {
142+ if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
143+ pid = waitpid(pid, 0, WNOHANG);
144+ if (pid > 0) {
145+ /* a thread has exited */
146+ pidlist[i] = pidlist[--maxpidindex];
147+ /* remove references to children of dead proc */
148+ for (j = 0; j < maxpidindex; j++)
149+ if (pidlist[j].parent == pid)
150+ pidlist[j].child = -1;
151+ continue; /* don't increment i */
152+ }
153+ }
154+ i++;
155+ }
156+ /* clean up the list */
157+ i = 0;
158+ while (i < maxpidindex) {
159+ if (pidlist[i].child == -1) {
160+ pidlist[i] = pidlist[--maxpidindex];
161+ continue; /* don't increment i */
162+ }
163+ i++;
164+ }
165+}
166+
167+long PyThread_start_new_thread(void (*func)(void *), void *arg)
168+{
169+#ifdef USE_DL
170+ long addr, size;
171+ static int local_initialized = 0;
172+#endif /* USE_DL */
173+ int success = 0; /* init not needed when SOLARIS_THREADS and */
174+ /* C_THREADS implemented properly */
175+
176+ dprintf(("PyThread_start_new_thread called\n"));
177+ if (!initialized)
178+ PyThread_init_thread();
179+ switch (ussetlock(count_lock)) {
180+ case 0: return 0;
181+ case -1: perror("ussetlock (count_lock)");
182+ }
183+ if (maxpidindex >= MAXPROC)
184+ success = -1;
185+ else {
186+#ifdef USE_DL
187+ if (!local_initialized) {
188+ if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
189+ perror("usconfig - CONF_INITSIZE (check)");
190+ if (usconfig(CONF_INITSIZE, size) < 0)
191+ perror("usconfig - CONF_INITSIZE (reset)");
192+ addr = (long) dl_getrange(size + HDR_SIZE);
193+ dprintf(("trying to use addr %p-%p for sproc\n",
194+ addr, addr+size));
195+ errno = 0;
196+ if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
197+ errno != 0)
198+ perror("usconfig - CONF_ATTACHADDR (set)");
199+ }
200+#endif /* USE_DL */
201+ clean_threads();
202+ if ((success = sproc(func, PR_SALL, arg)) < 0)
203+ perror("sproc");
204+#ifdef USE_DL
205+ if (!local_initialized) {
206+ if (usconfig(CONF_ATTACHADDR, addr) < 0)
207+ /* reset address */
208+ perror("usconfig - CONF_ATTACHADDR (reset)");
209+ local_initialized = 1;
210+ }
211+#endif /* USE_DL */
212+ if (success >= 0) {
213+ nthreads++;
214+ pidlist[maxpidindex].parent = getpid();
215+ pidlist[maxpidindex++].child = success;
216+ dprintf(("pidlist[%d] = %d\n",
217+ maxpidindex-1, success));
218+ }
219+ }
220+ if (usunsetlock(count_lock) < 0)
221+ perror("usunsetlock (count_lock)");
222+ return success;
223+}
224+
225+long PyThread_get_thread_ident(void)
226+{
227+ return getpid();
228+}
229+
230+static void do_PyThread_exit_thread(int no_cleanup)
231+{
232+ dprintf(("PyThread_exit_thread called\n"));
233+ if (!initialized)
234+ if (no_cleanup)
235+ _exit(0);
236+ else
237+ exit(0);
238+ if (ussetlock(count_lock) < 0)
239+ perror("ussetlock (count_lock)");
240+ nthreads--;
241+ if (getpid() == my_pid) {
242+ /* main thread; wait for other threads to exit */
243+ exiting = 1;
244+#ifndef NO_EXIT_PROG
245+ if (do_exit) {
246+ int i;
247+
248+ /* notify other threads */
249+ clean_threads();
250+ if (nthreads >= 0) {
251+ dprintf(("kill other threads\n"));
252+ for (i = 0; i < maxpidindex; i++)
253+ if (pidlist[i].child > 0)
254+ (void) kill(pidlist[i].child,
255+ SIGKILL);
256+ _exit(exit_status);
257+ }
258+ }
259+#endif /* NO_EXIT_PROG */
260+ waiting_for_threads = 1;
261+ if (ussetlock(wait_lock) < 0)
262+ perror("ussetlock (wait_lock)");
263+ for (;;) {
264+ if (nthreads < 0) {
265+ dprintf(("really exit (%d)\n", exit_status));
266+ if (no_cleanup)
267+ _exit(exit_status);
268+ else
269+ exit(exit_status);
270+ }
271+ if (usunsetlock(count_lock) < 0)
272+ perror("usunsetlock (count_lock)");
273+ dprintf(("waiting for other threads (%d)\n", nthreads));
274+ if (ussetlock(wait_lock) < 0)
275+ perror("ussetlock (wait_lock)");
276+ if (ussetlock(count_lock) < 0)
277+ perror("ussetlock (count_lock)");
278+ }
279+ }
280+ /* not the main thread */
281+ if (waiting_for_threads) {
282+ dprintf(("main thread is waiting\n"));
283+ if (usunsetlock(wait_lock) < 0)
284+ perror("usunsetlock (wait_lock)");
285+ }
286+#ifndef NO_EXIT_PROG
287+ else if (do_exit)
288+ (void) kill(my_pid, SIGUSR1);
289+#endif /* NO_EXIT_PROG */
290+ if (usunsetlock(count_lock) < 0)
291+ perror("usunsetlock (count_lock)");
292+ _exit(0);
293+}
294+
295+void PyThread_exit_thread(void)
296+{
297+ do_PyThread_exit_thread(0);
298+}
299+
300+void PyThread__exit_thread(void)
301+{
302+ do_PyThread_exit_thread(1);
303+}
304+
305+#ifndef NO_EXIT_PROG
306+static void do_PyThread_exit_prog(int status, int no_cleanup)
307+{
308+ dprintf(("PyThread_exit_prog(%d) called\n", status));
309+ if (!initialized)
310+ if (no_cleanup)
311+ _exit(status);
312+ else
313+ exit(status);
314+ do_exit = 1;
315+ exit_status = status;
316+ do_PyThread_exit_thread(no_cleanup);
317+}
318+
319+void PyThread_exit_prog(int status)
320+{
321+ do_PyThread_exit_prog(status, 0);
322+}
323+
324+void PyThread__exit_prog(int status)
325+{
326+ do_PyThread_exit_prog(status, 1);
327+}
328+#endif /* NO_EXIT_PROG */
329+
330+/*
331+ * Lock support.
332+ */
333+PyThread_type_lock PyThread_allocate_lock(void)
334+{
335+ ulock_t lock;
336+
337+ dprintf(("PyThread_allocate_lock called\n"));
338+ if (!initialized)
339+ PyThread_init_thread();
340+
341+ if ((lock = usnewlock(shared_arena)) == NULL)
342+ perror("usnewlock");
343+ (void) usinitlock(lock);
344+ dprintf(("PyThread_allocate_lock() -> %p\n", lock));
345+ return (PyThread_type_lock) lock;
346+}
347+
348+void PyThread_free_lock(PyThread_type_lock lock)
349+{
350+ dprintf(("PyThread_free_lock(%p) called\n", lock));
351+ usfreelock((ulock_t) lock, shared_arena);
352+}
353+
354+int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
355+{
356+ int success;
357+
358+ dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
359+ errno = 0; /* clear it just in case */
360+ if (waitflag)
361+ success = ussetlock((ulock_t) lock);
362+ else
363+ success = uscsetlock((ulock_t) lock, 1); /* Try it once */
364+ if (success < 0)
365+ perror(waitflag ? "ussetlock" : "uscsetlock");
366+ dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
367+ return success;
368+}
369+
370+void PyThread_release_lock(PyThread_type_lock lock)
371+{
372+ dprintf(("PyThread_release_lock(%p) called\n", lock));
373+ if (usunsetlock((ulock_t) lock) < 0)
374+ perror("usunsetlock");
375+}