]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Split thread.c into a number of system-specific files.
authorGuido van Rossum <guido@python.org>
Mon, 9 May 1994 15:12:46 +0000 (15:12 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 9 May 1994 15:12:46 +0000 (15:12 +0000)
Added Tim Peters' pthread version.

Python/thread_cthread.h [new file with mode: 0644]
Python/thread_foobar.h [new file with mode: 0644]
Python/thread_lwp.h [new file with mode: 0644]
Python/thread_pthread.h [new file with mode: 0644]
Python/thread_sgi.h [new file with mode: 0644]
Python/thread_solaris.h [new file with mode: 0644]

diff --git a/Python/thread_cthread.h b/Python/thread_cthread.h
new file mode 100644 (file)
index 0000000..7710bdf
--- /dev/null
@@ -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 <cthreads.h>
+
+
+/*
+ * 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 (file)
index 0000000..492096a
--- /dev/null
@@ -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 (file)
index 0000000..0462cbf
--- /dev/null
@@ -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 <stdlib.h>
+#include <lwp/lwp.h>
+#include <lwp/stackdep.h>
+
+#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 (file)
index 0000000..b98c12f
--- /dev/null
@@ -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 <pthread.h>
+#define TRYLOCK_OFFSET 0
+#endif /* FLORIDA_HACKS */
+#include <stdlib.h>
+
+/* 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 <condition, mutex> 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 <cond, mutex> 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 (file)
index 0000000..6f6334e
--- /dev/null
@@ -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 <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 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 (file)
index 0000000..08cf6dd
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include </usr/include/thread.h>
+
+
+/*
+ * 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");
+}