symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_sgi.h
changeset 1 2fb8b9db1c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_sgi.h	Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,375 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+#include <ulocks.h>
+#include <errno.h>
+
+#define HDR_SIZE	2680	/* sizeof(ushdr_t) */
+#define MAXPROC		100	/* max # of threads that can be started */
+
+static usptr_t *shared_arena;
+static ulock_t count_lock;	/* protection for some variables */
+static ulock_t wait_lock;	/* lock used to wait for other threads */
+static int waiting_for_threads;	/* protected by count_lock */
+static int nthreads;		/* protected by count_lock */
+static int exit_status;
+#ifndef NO_EXIT_PROG
+static int do_exit;		/* indicates that the program is to exit */
+#endif
+static int exiting;		/* we're already exiting (for maybe_exit) */
+static pid_t my_pid;		/* PID of main thread */
+static struct pidlist {
+	pid_t parent;
+	pid_t child;
+} pidlist[MAXPROC];	/* PIDs of other threads; protected by count_lock */
+static int maxpidindex;		/* # of PIDs in pidlist */
+
+#ifndef NO_EXIT_PROG
+/*
+ * This routine is called as a signal handler when another thread
+ * exits.  When that happens, we must see whether we have to exit as
+ * well (because of an PyThread_exit_prog()) or whether we should continue on.
+ */
+static void exit_sig(void)
+{
+	d2printf(("exit_sig called\n"));
+	if (exiting && getpid() == my_pid) {
+		d2printf(("already exiting\n"));
+		return;
+	}
+	if (do_exit) {
+		d2printf(("exiting in exit_sig\n"));
+#ifdef Py_DEBUG
+		if ((thread_debug & 8) == 0)
+			thread_debug &= ~1; /* don't produce debug messages */
+#endif
+		PyThread_exit_thread();
+	}
+}
+
+/*
+ * This routine is called when a process calls exit().  If that wasn't
+ * done from the library, we do as if an PyThread_exit_prog() was intended.
+ */
+static void maybe_exit(void)
+{
+	dprintf(("maybe_exit called\n"));
+	if (exiting) {
+		dprintf(("already exiting\n"));
+		return;
+	}
+	PyThread_exit_prog(0);
+}
+#endif /* NO_EXIT_PROG */
+
+/*
+ * Initialization.
+ */
+static void PyThread__init_thread(void)
+{
+#ifndef NO_EXIT_PROG
+	struct sigaction s;
+#endif /* NO_EXIT_PROG */
+#ifdef USE_DL
+	long addr, size;
+#endif /* USE_DL */
+
+
+#ifdef USE_DL
+	if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
+		perror("usconfig - CONF_INITSIZE (check)");
+	if (usconfig(CONF_INITSIZE, size) < 0)
+		perror("usconfig - CONF_INITSIZE (reset)");
+	addr = (long) dl_getrange(size + HDR_SIZE);
+	dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
+	errno = 0;
+	if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
+		perror("usconfig - CONF_ATTACHADDR (set)");
+#endif /* USE_DL */
+	if (usconfig(CONF_INITUSERS, 16) < 0)
+		perror("usconfig - CONF_INITUSERS");
+	my_pid = getpid();	/* so that we know which is the main thread */
+#ifndef NO_EXIT_PROG
+	atexit(maybe_exit);
+	s.sa_handler = exit_sig;
+	sigemptyset(&s.sa_mask);
+	/*sigaddset(&s.sa_mask, SIGUSR1);*/
+	s.sa_flags = 0;
+	sigaction(SIGUSR1, &s, 0);
+	if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
+		perror("prctl - PR_SETEXITSIG");
+#endif /* NO_EXIT_PROG */
+	if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
+		perror("usconfig - CONF_ARENATYPE");
+	usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
+#ifdef Py_DEBUG
+	if (thread_debug & 4)
+		usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
+	else if (thread_debug & 2)
+		usconfig(CONF_LOCKTYPE, US_DEBUG);
+#endif /* Py_DEBUG */
+	if ((shared_arena = usinit(tmpnam(0))) == 0)
+		perror("usinit");
+#ifdef USE_DL
+	if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
+		perror("usconfig - CONF_ATTACHADDR (reset)");
+#endif /* USE_DL */
+	if ((count_lock = usnewlock(shared_arena)) == NULL)
+		perror("usnewlock (count_lock)");
+	(void) usinitlock(count_lock);
+	if ((wait_lock = usnewlock(shared_arena)) == NULL)
+		perror("usnewlock (wait_lock)");
+	dprintf(("arena start: %p, arena size: %ld\n",  shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
+}
+
+/*
+ * Thread support.
+ */
+
+static void clean_threads(void)
+{
+	int i, j;
+	pid_t mypid, pid;
+
+	/* clean up any exited threads */
+	mypid = getpid();
+	i = 0;
+	while (i < maxpidindex) {
+		if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
+			pid = waitpid(pid, 0, WNOHANG);
+			if (pid > 0) {
+				/* a thread has exited */
+				pidlist[i] = pidlist[--maxpidindex];
+				/* remove references to children of dead proc */
+				for (j = 0; j < maxpidindex; j++)
+					if (pidlist[j].parent == pid)
+						pidlist[j].child = -1;
+				continue; /* don't increment i */
+			}
+		}
+		i++;
+	}
+	/* clean up the list */
+	i = 0;
+	while (i < maxpidindex) {
+		if (pidlist[i].child == -1) {
+			pidlist[i] = pidlist[--maxpidindex];
+			continue; /* don't increment i */
+		}
+		i++;
+	}
+}
+
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
+{
+#ifdef USE_DL
+	long addr, size;
+	static int local_initialized = 0;
+#endif /* USE_DL */
+	int success = 0;	/* init not needed when SOLARIS_THREADS and */
+				/* C_THREADS implemented properly */
+
+	dprintf(("PyThread_start_new_thread called\n"));
+	if (!initialized)
+		PyThread_init_thread();
+	switch (ussetlock(count_lock)) {
+	case 0: return 0;
+	case -1: perror("ussetlock (count_lock)");
+	}
+	if (maxpidindex >= MAXPROC)
+		success = -1;
+	else {
+#ifdef USE_DL
+		if (!local_initialized) {
+			if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
+				perror("usconfig - CONF_INITSIZE (check)");
+			if (usconfig(CONF_INITSIZE, size) < 0)
+				perror("usconfig - CONF_INITSIZE (reset)");
+			addr = (long) dl_getrange(size + HDR_SIZE);
+			dprintf(("trying to use addr %p-%p for sproc\n",
+				 addr, addr+size));
+			errno = 0;
+			if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
+			    errno != 0)
+				perror("usconfig - CONF_ATTACHADDR (set)");
+		}
+#endif /* USE_DL */
+		clean_threads();
+		if ((success = sproc(func, PR_SALL, arg)) < 0)
+			perror("sproc");
+#ifdef USE_DL
+		if (!local_initialized) {
+			if (usconfig(CONF_ATTACHADDR, addr) < 0)
+				/* reset address */
+				perror("usconfig - CONF_ATTACHADDR (reset)");
+			local_initialized = 1;
+		}
+#endif /* USE_DL */
+		if (success >= 0) {
+			nthreads++;
+			pidlist[maxpidindex].parent = getpid();
+			pidlist[maxpidindex++].child = success;
+			dprintf(("pidlist[%d] = %d\n",
+				 maxpidindex-1, success));
+		}
+	}
+	if (usunsetlock(count_lock) < 0)
+		perror("usunsetlock (count_lock)");
+	return success;
+}
+
+long PyThread_get_thread_ident(void)
+{
+	return getpid();
+}
+
+static void do_PyThread_exit_thread(int no_cleanup)
+{
+	dprintf(("PyThread_exit_thread called\n"));
+	if (!initialized)
+		if (no_cleanup)
+			_exit(0);
+		else
+			exit(0);
+	if (ussetlock(count_lock) < 0)
+		perror("ussetlock (count_lock)");
+	nthreads--;
+	if (getpid() == my_pid) {
+		/* main thread; wait for other threads to exit */
+		exiting = 1;
+#ifndef NO_EXIT_PROG
+		if (do_exit) {
+			int i;
+
+			/* notify other threads */
+			clean_threads();
+			if (nthreads >= 0) {
+				dprintf(("kill other threads\n"));
+				for (i = 0; i < maxpidindex; i++)
+					if (pidlist[i].child > 0)
+						(void) kill(pidlist[i].child,
+							    SIGKILL);
+				_exit(exit_status);
+			}
+		}
+#endif /* NO_EXIT_PROG */
+		waiting_for_threads = 1;
+		if (ussetlock(wait_lock) < 0)
+			perror("ussetlock (wait_lock)");
+		for (;;) {
+			if (nthreads < 0) {
+				dprintf(("really exit (%d)\n", exit_status));
+				if (no_cleanup)
+					_exit(exit_status);
+				else
+					exit(exit_status);
+			}
+			if (usunsetlock(count_lock) < 0)
+				perror("usunsetlock (count_lock)");
+			dprintf(("waiting for other threads (%d)\n", nthreads));
+			if (ussetlock(wait_lock) < 0)
+				perror("ussetlock (wait_lock)");
+			if (ussetlock(count_lock) < 0)
+				perror("ussetlock (count_lock)");
+		}
+	}
+	/* not the main thread */
+	if (waiting_for_threads) {
+		dprintf(("main thread is waiting\n"));
+		if (usunsetlock(wait_lock) < 0)
+			perror("usunsetlock (wait_lock)");
+	}
+#ifndef NO_EXIT_PROG
+	else if (do_exit)
+		(void) kill(my_pid, SIGUSR1);
+#endif /* NO_EXIT_PROG */
+	if (usunsetlock(count_lock) < 0)
+		perror("usunsetlock (count_lock)");
+	_exit(0);
+}
+
+void PyThread_exit_thread(void)
+{
+	do_PyThread_exit_thread(0);
+}
+
+void PyThread__exit_thread(void)
+{
+	do_PyThread_exit_thread(1);
+}
+
+#ifndef NO_EXIT_PROG
+static void do_PyThread_exit_prog(int status, int no_cleanup)
+{
+	dprintf(("PyThread_exit_prog(%d) called\n", status));
+	if (!initialized)
+		if (no_cleanup)
+			_exit(status);
+		else
+			exit(status);
+	do_exit = 1;
+	exit_status = status;
+	do_PyThread_exit_thread(no_cleanup);
+}
+
+void PyThread_exit_prog(int status)
+{
+	do_PyThread_exit_prog(status, 0);
+}
+
+void PyThread__exit_prog(int status)
+{
+	do_PyThread_exit_prog(status, 1);
+}
+#endif /* NO_EXIT_PROG */
+
+/*
+ * Lock support.
+ */
+PyThread_type_lock PyThread_allocate_lock(void)
+{
+	ulock_t lock;
+
+	dprintf(("PyThread_allocate_lock called\n"));
+	if (!initialized)
+		PyThread_init_thread();
+
+	if ((lock = usnewlock(shared_arena)) == NULL)
+		perror("usnewlock");
+	(void) usinitlock(lock);
+	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
+	return (PyThread_type_lock) lock;
+}
+
+void PyThread_free_lock(PyThread_type_lock lock)
+{
+	dprintf(("PyThread_free_lock(%p) called\n", lock));
+	usfreelock((ulock_t) lock, shared_arena);
+}
+
+int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+{
+	int success;
+
+	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
+	errno = 0;		/* clear it just in case */
+	if (waitflag)
+		success = ussetlock((ulock_t) lock);
+	else
+		success = uscsetlock((ulock_t) lock, 1); /* Try it once */
+	if (success < 0)
+		perror(waitflag ? "ussetlock" : "uscsetlock");
+	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
+	return success;
+}
+
+void PyThread_release_lock(PyThread_type_lock lock)
+{
+	dprintf(("PyThread_release_lock(%p) called\n", lock));
+	if (usunsetlock((ulock_t) lock) < 0)
+		perror("usunsetlock");
+}