diff -r ffa851df0825 -r 2fb8b9db1c86 symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_sgi.h --- /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 +#include +#include +#include +#include +#include +#include +#include + +#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"); +}