From 2c8cb9f3d240fd2acd098590d2e18445bd8a40bb Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 9 May 1994 15:12:46 +0000 Subject: [PATCH] Split thread.c into a number of system-specific files. Added Tim Peters' pthread version. --- Python/thread_cthread.h | 158 +++++++++++++++ Python/thread_foobar.h | 148 ++++++++++++++ Python/thread_lwp.h | 198 +++++++++++++++++++ Python/thread_pthread.h | 272 ++++++++++++++++++++++++++ Python/thread_sgi.h | 414 ++++++++++++++++++++++++++++++++++++++++ Python/thread_solaris.h | 219 +++++++++++++++++++++ 6 files changed, 1409 insertions(+) create mode 100644 Python/thread_cthread.h create mode 100644 Python/thread_foobar.h create mode 100644 Python/thread_lwp.h create mode 100644 Python/thread_pthread.h create mode 100644 Python/thread_sgi.h create mode 100644 Python/thread_solaris.h diff --git a/Python/thread_cthread.h b/Python/thread_cthread.h new file mode 100644 index 00000000000..7710bdfec32 --- /dev/null +++ b/Python/thread_cthread.h @@ -0,0 +1,158 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +#include + + +/* + * Initialization. + */ +static void _init_thread _P0() +{ + cthread_init(); +} + +/* + * Thread support. + */ +int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg) +{ +#if defined(SGI_THREADS) && defined(USE_DL) + long addr, size; + static int local_initialized = 0; +#endif /* SGI_THREADS and USE_DL */ + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ + + dprintf(("start_new_thread called\n")); + if (!initialized) + init_thread(); + (void) cthread_fork(func, arg); + return success < 0 ? 0 : 1; +} + +static void do_exit_thread _P1(no_cleanup, int no_cleanup) +{ + dprintf(("exit_thread called\n")); + if (!initialized) + if (no_cleanup) + _exit(0); + else + exit(0); + cthread_exit(0); +} + +void exit_thread _P0() +{ + do_exit_thread(0); +} + +void _exit_thread _P0() +{ + do_exit_thread(1); +} + +#ifndef NO_EXIT_PROG +static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup) +{ + dprintf(("exit_prog(%d) called\n", status)); + if (!initialized) + if (no_cleanup) + _exit(status); + else + exit(status); +} + +void exit_prog _P1(status, int status) +{ + do_exit_prog(status, 0); +} + +void _exit_prog _P1(status, int status) +{ + do_exit_prog(status, 1); +} +#endif /* NO_EXIT_PROG */ + +/* + * Lock support. + */ +type_lock allocate_lock _P0() +{ + + dprintf(("allocate_lock called\n")); + if (!initialized) + init_thread(); + + dprintf(("allocate_lock() -> %lx\n", (long)lock)); + return (type_lock) lock; +} + +void free_lock _P1(lock, type_lock lock) +{ + dprintf(("free_lock(%lx) called\n", (long)lock)); +} + +int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag) +{ + int success; + + dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag)); + dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); + return success; +} + +void release_lock _P1(lock, type_lock lock) +{ + dprintf(("release_lock(%lx) called\n", (long)lock)); +} + +/* + * Semaphore support. + */ +type_sema allocate_sema _P1(value, int value) +{ + dprintf(("allocate_sema called\n")); + if (!initialized) + init_thread(); + + dprintf(("allocate_sema() -> %lx\n", (long) sema)); + return (type_sema) sema; +} + +void free_sema _P1(sema, type_sema sema) +{ + dprintf(("free_sema(%lx) called\n", (long) sema)); +} + +void down_sema _P1(sema, type_sema sema) +{ + dprintf(("down_sema(%lx) called\n", (long) sema)); + dprintf(("down_sema(%lx) return\n", (long) sema)); +} + +void up_sema _P1(sema, type_sema sema) +{ + dprintf(("up_sema(%lx)\n", (long) sema)); +} diff --git a/Python/thread_foobar.h b/Python/thread_foobar.h new file mode 100644 index 00000000000..492096aa68e --- /dev/null +++ b/Python/thread_foobar.h @@ -0,0 +1,148 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* + * Initialization. + */ +static void _init_thread _P0() +{ +} + +/* + * Thread support. + */ +int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg) +{ + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ + + dprintf(("start_new_thread called\n")); + if (!initialized) + init_thread(); + return success < 0 ? 0 : 1; +} + +static void do_exit_thread _P1(no_cleanup, int no_cleanup) +{ + dprintf(("exit_thread called\n")); + if (!initialized) + if (no_cleanup) + _exit(0); + else + exit(0); +} + +void exit_thread _P0() +{ + do_exit_thread(0); +} + +void _exit_thread _P0() +{ + do_exit_thread(1); +} + +#ifndef NO_EXIT_PROG +static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup) +{ + dprintf(("exit_prog(%d) called\n", status)); + if (!initialized) + if (no_cleanup) + _exit(status); + else + exit(status); +} + +void exit_prog _P1(status, int status) +{ + do_exit_prog(status, 0); +} + +void _exit_prog _P1(status, int status) +{ + do_exit_prog(status, 1); +} +#endif /* NO_EXIT_PROG */ + +/* + * Lock support. + */ +type_lock allocate_lock _P0() +{ + + dprintf(("allocate_lock called\n")); + if (!initialized) + init_thread(); + + dprintf(("allocate_lock() -> %lx\n", (long)lock)); + return (type_lock) lock; +} + +void free_lock _P1(lock, type_lock lock) +{ + dprintf(("free_lock(%lx) called\n", (long)lock)); +} + +int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag) +{ + int success; + + dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag)); + dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); + return success; +} + +void release_lock _P1(lock, type_lock lock) +{ + dprintf(("release_lock(%lx) called\n", (long)lock)); +} + +/* + * Semaphore support. + */ +type_sema allocate_sema _P1(value, int value) +{ + dprintf(("allocate_sema called\n")); + if (!initialized) + init_thread(); + + dprintf(("allocate_sema() -> %lx\n", (long) sema)); + return (type_sema) sema; +} + +void free_sema _P1(sema, type_sema sema) +{ + dprintf(("free_sema(%lx) called\n", (long) sema)); +} + +void down_sema _P1(sema, type_sema sema) +{ + dprintf(("down_sema(%lx) called\n", (long) sema)); + dprintf(("down_sema(%lx) return\n", (long) sema)); +} + +void up_sema _P1(sema, type_sema sema) +{ + dprintf(("up_sema(%lx)\n", (long) sema)); +} diff --git a/Python/thread_lwp.h b/Python/thread_lwp.h new file mode 100644 index 00000000000..0462cbf93ec --- /dev/null +++ b/Python/thread_lwp.h @@ -0,0 +1,198 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +#include +#include +#include + +#define STACKSIZE 1000 /* stacksize for a thread */ +#define NSTACKS 2 /* # stacks to be put in cache initialy */ + +struct lock { + int lock_locked; + cv_t lock_condvar; + mon_t lock_monitor; +}; + + +/* + * Initialization. + */ +static void _init_thread _P0() +{ + lwp_setstkcache(STACKSIZE, NSTACKS); +} + +/* + * Thread support. + */ + + +int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg) +{ + thread_t tid; +#if defined(SGI_THREADS) && defined(USE_DL) + long addr, size; + static int local_initialized = 0; +#endif /* SGI_THREADS and USE_DL */ + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ + + dprintf(("start_new_thread called\n")); + if (!initialized) + init_thread(); + success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg); + return success < 0 ? 0 : 1; +} + +static void do_exit_thread _P1(no_cleanup, int no_cleanup) +{ + dprintf(("exit_thread called\n")); + if (!initialized) + if (no_cleanup) + _exit(0); + else + exit(0); + lwp_destroy(SELF); +} + +void exit_thread _P0() +{ + do_exit_thread(0); +} + +void _exit_thread _P0() +{ + do_exit_thread(1); +} + +#ifndef NO_EXIT_PROG +static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup) +{ + dprintf(("exit_prog(%d) called\n", status)); + if (!initialized) + if (no_cleanup) + _exit(status); + else + exit(status); + pod_exit(status); +} + +void exit_prog _P1(status, int status) +{ + do_exit_prog(status, 0); +} + +void _exit_prog _P1(status, int status) +{ + do_exit_prog(status, 1); +} +#endif /* NO_EXIT_PROG */ + +/* + * Lock support. + */ +type_lock allocate_lock _P0() +{ + struct lock *lock; + extern char *malloc(); + + dprintf(("allocate_lock called\n")); + if (!initialized) + init_thread(); + + lock = (struct lock *) malloc(sizeof(struct lock)); + lock->lock_locked = 0; + (void) mon_create(&lock->lock_monitor); + (void) cv_create(&lock->lock_condvar, lock->lock_monitor); + dprintf(("allocate_lock() -> %lx\n", (long)lock)); + return (type_lock) lock; +} + +void free_lock _P1(lock, type_lock lock) +{ + dprintf(("free_lock(%lx) called\n", (long)lock)); + mon_destroy(((struct lock *) lock)->lock_monitor); + free((char *) lock); +} + +int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag) +{ + int success; + + dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag)); + success = 0; + + (void) mon_enter(((struct lock *) lock)->lock_monitor); + if (waitflag) + while (((struct lock *) lock)->lock_locked) + cv_wait(((struct lock *) lock)->lock_condvar); + if (!((struct lock *) lock)->lock_locked) { + success = 1; + ((struct lock *) lock)->lock_locked = 1; + } + cv_broadcast(((struct lock *) lock)->lock_condvar); + mon_exit(((struct lock *) lock)->lock_monitor); + dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); + return success; +} + +void release_lock _P1(lock, type_lock lock) +{ + dprintf(("release_lock(%lx) called\n", (long)lock)); + (void) mon_enter(((struct lock *) lock)->lock_monitor); + ((struct lock *) lock)->lock_locked = 0; + cv_broadcast(((struct lock *) lock)->lock_condvar); + mon_exit(((struct lock *) lock)->lock_monitor); +} + +/* + * Semaphore support. + */ +type_sema allocate_sema _P1(value, int value) +{ + type_sema sema = 0; + dprintf(("allocate_sema called\n")); + if (!initialized) + init_thread(); + + dprintf(("allocate_sema() -> %lx\n", (long) sema)); + return (type_sema) sema; +} + +void free_sema _P1(sema, type_sema sema) +{ + dprintf(("free_sema(%lx) called\n", (long) sema)); +} + +void down_sema _P1(sema, type_sema sema) +{ + dprintf(("down_sema(%lx) called\n", (long) sema)); + dprintf(("down_sema(%lx) return\n", (long) sema)); +} + +void up_sema _P1(sema, type_sema sema) +{ + dprintf(("up_sema(%lx)\n", (long) sema)); +} diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h new file mode 100644 index 00000000000..b98c12f0a16 --- /dev/null +++ b/Python/thread_pthread.h @@ -0,0 +1,272 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +#ifdef sun +#define FLORIDA_HACKS +#endif + +#ifdef FLORIDA_HACKS +/* Hacks for Florida State Posix threads implementation */ +#undef _POSIX_THREADS +#include "/ufs/guido/src/python/Contrib/pthreads/pthreads/pthread.h" +#define pthread_attr_default ((pthread_attr_t *)0) +#define pthread_mutexattr_default ((pthread_mutexattr_t *)0) +#define pthread_condattr_default ((pthread_condattr_t *)0) +#define TRYLOCK_OFFSET 1 +#else /* !FLORIDA_HACKS */ +#include +#define TRYLOCK_OFFSET 0 +#endif /* FLORIDA_HACKS */ +#include + +/* A pthread mutex isn't sufficient to model the Python lock type (at + * least not the way KSR did 'em -- haven't dug thru the docs to verify), + * because a thread that locks a mutex can't then do a pthread_mutex_lock + * on it (to wait for another thread to unlock it). + * In any case, pthread mutexes are designed for serializing threads over + * short pieces of code, so wouldn't be an appropriate implementation of + * Python's locks regardless. + * The pthread_lock struct below implements a Python lock as a pthread + * mutex and a pair. In general, if the mutex can be + * be acquired instantly, it is, else the pair is used to block the + * thread until the mutex is released. 7 May 1994 tim@ksr.com + */ +typedef struct { + /* the lock */ + pthread_mutex_t mutex; + /* a pair to handle an acquire of a locked mutex */ + pthread_cond_t cond; + pthread_mutex_t cmutex; +} pthread_lock; + +/* + * Initialization. + */ +static void _init_thread _P0() +{ +} + +/* + * Thread support. + */ +int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg) +{ +#if defined(SGI_THREADS) && defined(USE_DL) + long addr, size; + static int local_initialized = 0; +#endif /* SGI_THREADS and USE_DL */ + pthread_t th; + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ + + dprintf(("start_new_thread called\n")); + if (!initialized) + init_thread(); + success = pthread_create(&th, pthread_attr_default, func, arg); + return success < 0 ? 0 : 1; +} + +static void do_exit_thread _P1(no_cleanup, int no_cleanup) +{ + dprintf(("exit_thread called\n")); + if (!initialized) + if (no_cleanup) + _exit(0); + else + exit(0); +} + +void exit_thread _P0() +{ + do_exit_thread(0); +} + +void _exit_thread _P0() +{ + do_exit_thread(1); +} + +#ifndef NO_EXIT_PROG +static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup) +{ + dprintf(("exit_prog(%d) called\n", status)); + if (!initialized) + if (no_cleanup) + _exit(status); + else + exit(status); +} + +void exit_prog _P1(status, int status) +{ + do_exit_prog(status, 0); +} + +void _exit_prog _P1(status, int status) +{ + do_exit_prog(status, 1); +} +#endif /* NO_EXIT_PROG */ + +/* + * Lock support. + */ +type_lock allocate_lock _P0() +{ + pthread_lock *lock; + + dprintf(("allocate_lock called\n")); + if (!initialized) + init_thread(); + + lock = (pthread_lock *) malloc(sizeof(pthread_lock)); + { + int err = 0; + if ( pthread_mutex_init(&lock->mutex, + pthread_mutexattr_default) ) { + perror("pthread_mutex_init"); + err = 1; + } + if ( pthread_cond_init(&lock->cond, + pthread_condattr_default) ) { + perror("pthread_cond_init"); + err = 1; + } + if ( pthread_mutex_init(&lock->cmutex, + pthread_mutexattr_default)) { + perror("pthread_mutex_init"); + err = 1; + } + if (err) { + free((void *)lock); + lock = 0; + } + } + + dprintf(("allocate_lock() -> %lx\n", (long)lock)); + return (type_lock) lock; +} + +void free_lock _P1(lock, type_lock lock) +{ + dprintf(("free_lock(%lx) called\n", (long)lock)); + if ( pthread_mutex_destroy(&((pthread_lock *)lock)->mutex) ) + perror("pthread_mutex_destroy"); + if ( pthread_cond_destroy(&((pthread_lock *)lock)->cond) ) + perror("pthread_cond_destroy"); + if ( pthread_mutex_destroy(&((pthread_lock *)lock)->cmutex) ) + perror("pthread_mutex_destroy"); + free((void *)lock); +} + +int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag) +{ + int success; + + dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag)); + { + pthread_lock *thelock = (pthread_lock *)lock; + success = TRYLOCK_OFFSET + + pthread_mutex_trylock( &thelock->mutex ); + if (success < 0) { + perror("pthread_mutex_trylock [1]"); + success = 0; + } else if ( success == 0 && waitflag ) { + /* continue trying until we get the lock */ + + /* cmutex must be locked by me -- part of the condition + * protocol */ + if ( pthread_mutex_lock( &thelock->cmutex ) ) + perror("pthread_mutex_lock"); + while ( 0 == (success = TRYLOCK_OFFSET + + pthread_mutex_trylock(&thelock->mutex)) ) { + if ( pthread_cond_wait(&thelock->cond, + &thelock->cmutex) ) + perror("pthread_cond_wait"); + } + if (success < 0) + perror("pthread_mutex_trylock [2]"); + /* now ->mutex & ->cmutex are both locked by me */ + if ( pthread_mutex_unlock( &thelock->cmutex ) ) + perror("pthread_mutex_unlock"); + } + } + dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); + return success; +} + +void release_lock _P1(lock, type_lock lock) +{ + dprintf(("release_lock(%lx) called\n", (long)lock)); + { + pthread_lock *thelock = (pthread_lock *)lock; + + /* tricky: if the release & signal occur between the + * pthread_mutex_trylock(&thelock->mutex)) + * and pthread_cond_wait during the acquire, the acquire + * will miss the signal it's waiting for; locking cmutex + * around the release prevents that + */ + if (pthread_mutex_lock( &thelock->cmutex )) + perror("pthread_mutex_lock"); + if (pthread_mutex_unlock( &thelock->mutex )) + perror("pthread_mutex_unlock"); + if (pthread_mutex_unlock( &thelock->cmutex )) + perror("pthread_mutex_unlock"); + + /* wake up someone (anyone, if any) waiting on the lock */ + if (pthread_cond_signal( &thelock->cond )) + perror("pthread_cond_signal"); + } +} + +/* + * Semaphore support. + */ +type_sema allocate_sema _P1(value, int value) +{ + char *sema = 0; + dprintf(("allocate_sema called\n")); + if (!initialized) + init_thread(); + + dprintf(("allocate_sema() -> %lx\n", (long) sema)); + return (type_sema) sema; +} + +void free_sema _P1(sema, type_sema sema) +{ + dprintf(("free_sema(%lx) called\n", (long) sema)); +} + +void down_sema _P1(sema, type_sema sema) +{ + dprintf(("down_sema(%lx) called\n", (long) sema)); + dprintf(("down_sema(%lx) return\n", (long) sema)); +} + +void up_sema _P1(sema, type_sema sema) +{ + dprintf(("up_sema(%lx)\n", (long) sema)); +} diff --git a/Python/thread_sgi.h b/Python/thread_sgi.h new file mode 100644 index 00000000000..6f6334e5349 --- /dev/null +++ b/Python/thread_sgi.h @@ -0,0 +1,414 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +#ifdef WITH_SGI_DL +#define USE_DL +#endif + +#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 pid_t pidlist[MAXPROC]; /* PIDs of other threads */ +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 exit_prog()) or whether we should continue on. + */ +static void exit_sig _P0() +{ + 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 DEBUG + if ((thread_debug & 8) == 0) + thread_debug &= ~1; /* don't produce debug messages */ +#endif + exit_thread(); + } +} + +/* + * This routine is called when a process calls exit(). If that wasn't + * done from the library, we do as if an exit_prog() was intended. + */ +static void maybe_exit _P0() +{ + dprintf(("maybe_exit called\n")); + if (exiting) { + dprintf(("already exiting\n")); + return; + } + exit_prog(0); +} +#endif /* NO_EXIT_PROG */ + +/* + * Initialization. + */ +static void _init_thread _P0() +{ +#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 %lx-%lx 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 DEBUG + if (thread_debug & 4) + usconfig(CONF_LOCKTYPE, US_DEBUGPLUS); + else if (thread_debug & 2) + usconfig(CONF_LOCKTYPE, US_DEBUG); +#endif /* 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: %lx, arena size: %ld\n", (long) shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena))); +} + +/* + * Thread support. + */ + +static void clean_threads _P0() +{ + int i; + pid_t pid; + + /* clean up any exited threads */ + i = 0; + while (i < maxpidindex) { + if ((pid = pidlist[i]) > 0) { + pid = waitpid(pid, 0, WNOHANG); + if (pid < 0) + return; + if (pid != 0) { + /* a thread has exited */ + pidlist[i] = pidlist[--maxpidindex]; + continue; /* don't increment i */ + } + } + i++; + } +} + +int start_new_thread _P2(func, void (*func) _P((void *)), arg, 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(("start_new_thread called\n")); + if (!initialized) + 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 %lx-%lx 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++] = success; + dprintf(("pidlist[%d] = %d\n", maxpidindex-1, success)); + } + } + if (usunsetlock(count_lock) < 0) + perror("usunsetlock (count_lock)"); + return success < 0 ? 0 : 1; +} + +static void do_exit_thread _P1(no_cleanup, int no_cleanup) +{ + dprintf(("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] > 0) + (void) kill(pidlist[i], + 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 exit_thread _P0() +{ + do_exit_thread(0); +} + +void _exit_thread _P0() +{ + do_exit_thread(1); +} + +#ifndef NO_EXIT_PROG +static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup) +{ + dprintf(("exit_prog(%d) called\n", status)); + if (!initialized) + if (no_cleanup) + _exit(status); + else + exit(status); + do_exit = 1; + exit_status = status; + do_exit_thread(no_cleanup); +} + +void exit_prog _P1(status, int status) +{ + do_exit_prog(status, 0); +} + +void _exit_prog _P1(status, int status) +{ + do_exit_prog(status, 1); +} +#endif /* NO_EXIT_PROG */ + +/* + * Lock support. + */ +type_lock allocate_lock _P0() +{ + ulock_t lock; + + dprintf(("allocate_lock called\n")); + if (!initialized) + init_thread(); + + if ((lock = usnewlock(shared_arena)) == NULL) + perror("usnewlock"); + (void) usinitlock(lock); + dprintf(("allocate_lock() -> %lx\n", (long)lock)); + return (type_lock) lock; +} + +void free_lock _P1(lock, type_lock lock) +{ + dprintf(("free_lock(%lx) called\n", (long)lock)); + usfreelock((ulock_t) lock, shared_arena); +} + +int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag) +{ + int success; + + dprintf(("acquire_lock(%lx, %d) called\n", (long)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(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); + return success; +} + +void release_lock _P1(lock, type_lock lock) +{ + dprintf(("release_lock(%lx) called\n", (long)lock)); + if (usunsetlock((ulock_t) lock) < 0) + perror("usunsetlock"); +} + +/* + * Semaphore support. + */ +type_sema allocate_sema _P1(value, int value) +{ + usema_t *sema; + dprintf(("allocate_sema called\n")); + if (!initialized) + init_thread(); + + if ((sema = usnewsema(shared_arena, value)) == NULL) + perror("usnewsema"); + dprintf(("allocate_sema() -> %lx\n", (long) sema)); + return (type_sema) sema; +} + +void free_sema _P1(sema, type_sema sema) +{ + dprintf(("free_sema(%lx) called\n", (long) sema)); + usfreesema((usema_t *) sema, shared_arena); +} + +void down_sema _P1(sema, type_sema sema) +{ + dprintf(("down_sema(%lx) called\n", (long) sema)); + if (uspsema((usema_t *) sema) < 0) + perror("uspsema"); + dprintf(("down_sema(%lx) return\n", (long) sema)); +} + +void up_sema _P1(sema, type_sema sema) +{ + dprintf(("up_sema(%lx)\n", (long) sema)); + if (usvsema((usema_t *) sema) < 0) + perror("usvsema"); +} diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h new file mode 100644 index 00000000000..08cf6dd0519 --- /dev/null +++ b/Python/thread_solaris.h @@ -0,0 +1,219 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +#include +#include +#include +#include + + +/* + * Initialization. + */ +static void _init_thread _P0() +{ +} + +/* + * Thread support. + */ +struct func_arg { + void (*func) _P((void *)); + void *arg; +}; + +static void *new_func _P1(funcarg, void *funcarg) +{ + void (*func) _P((void *)); + void *arg; + + func = ((struct func_arg *) funcarg)->func; + arg = ((struct func_arg *) funcarg)->arg; + free(funcarg); + (*func)(arg); + return 0; +} + + +int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg) +{ + struct func_arg *funcarg; + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ + + dprintf(("start_new_thread called\n")); + if (!initialized) + init_thread(); + funcarg = (struct func_arg *) malloc(sizeof(struct func_arg)); + funcarg->func = func; + funcarg->arg = arg; + if (thr_create(0, 0, new_func, funcarg, THR_NEW_LWP, 0)) { + perror("thr_create"); + free((void *) funcarg); + success = -1; + } + return success < 0 ? 0 : 1; +} + +static void do_exit_thread _P1(no_cleanup, int no_cleanup) +{ + dprintf(("exit_thread called\n")); + if (!initialized) + if (no_cleanup) + _exit(0); + else + exit(0); + thr_exit(0); +} + +void exit_thread _P0() +{ + do_exit_thread(0); +} + +void _exit_thread _P0() +{ + do_exit_thread(1); +} + +#ifndef NO_EXIT_PROG +static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup) +{ + dprintf(("exit_prog(%d) called\n", status)); + if (!initialized) + if (no_cleanup) + _exit(status); + else + exit(status); + if (no_cleanup) + _exit(status); + else + exit(status); +} + +void exit_prog _P1(status, int status) +{ + do_exit_prog(status, 0); +} + +void _exit_prog _P1(status, int status) +{ + do_exit_prog(status, 1); +} +#endif /* NO_EXIT_PROG */ + +/* + * Lock support. + */ +type_lock allocate_lock _P0() +{ + mutex_t *lock; + + dprintf(("allocate_lock called\n")); + if (!initialized) + init_thread(); + + lock = (mutex_t *) malloc(sizeof(mutex_t)); + if (mutex_init(lock, USYNC_THREAD, 0)) { + perror("mutex_init"); + free((void *) lock); + lock = 0; + } + dprintf(("allocate_lock() -> %lx\n", (long)lock)); + return (type_lock) lock; +} + +void free_lock _P1(lock, type_lock lock) +{ + dprintf(("free_lock(%lx) called\n", (long)lock)); + mutex_destroy((mutex_t *) lock); + free((void *) lock); +} + +int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag) +{ + int success; + + dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag)); + if (waitflag) + success = mutex_lock((mutex_t *) lock); + else + success = mutex_trylock((mutex_t *) lock); + if (success < 0) + perror(waitflag ? "mutex_lock" : "mutex_trylock"); + else + success = !success; /* solaris does it the other way round */ + dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); + return success; +} + +void release_lock _P1(lock, type_lock lock) +{ + dprintf(("release_lock(%lx) called\n", (long)lock)); + if (mutex_unlock((mutex_t *) lock)) + perror("mutex_unlock"); +} + +/* + * Semaphore support. + */ +type_sema allocate_sema _P1(value, int value) +{ + sema_t *sema; + dprintf(("allocate_sema called\n")); + if (!initialized) + init_thread(); + + sema = (sema_t *) malloc(sizeof(sema_t)); + if (sema_init(sema, value, USYNC_THREAD, 0)) { + perror("sema_init"); + free((void *) sema); + sema = 0; + } + dprintf(("allocate_sema() -> %lx\n", (long) sema)); + return (type_sema) sema; +} + +void free_sema _P1(sema, type_sema sema) +{ + dprintf(("free_sema(%lx) called\n", (long) sema)); + if (sema_destroy((sema_t *) sema)) + perror("sema_destroy"); + free((void *) sema); +} + +void down_sema _P1(sema, type_sema sema) +{ + dprintf(("down_sema(%lx) called\n", (long) sema)); + if (sema_wait((sema_t *) sema)) + perror("sema_wait"); + dprintf(("down_sema(%lx) return\n", (long) sema)); +} + +void up_sema _P1(sema, type_sema sema) +{ + dprintf(("up_sema(%lx)\n", (long) sema)); + if (sema_post((sema_t *) sema)) + perror("sema_post"); +}