]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
* Makefile adapted to changes below.
authorGuido van Rossum <guido@python.org>
Tue, 4 Aug 1992 12:41:02 +0000 (12:41 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 4 Aug 1992 12:41:02 +0000 (12:41 +0000)
* split pythonmain.c in two: most stuff goes to pythonrun.c, in the library.
* new optional built-in threadmodule.c, build upon Sjoerd's thread.{c,h}.
* new module from Sjoerd: mmmodule.c (dynamically loaded).
* new module from Sjoerd: sv (svgen.py, svmodule.c.proto).
* new files thread.{c,h} (from Sjoerd).
* new xxmodule.c (example only).
* myselect.h: bzero -> memset
* select.c: bzero -> memset; removed global variable

Include/pythread.h [new file with mode: 0644]
Include/thread.h [new file with mode: 0644]
Modules/config.c.in
Modules/threadmodule.c [new file with mode: 0644]
Modules/timemodule.c
Modules/xxmodule.c [new file with mode: 0644]
Objects/fileobject.c
Python/ceval.c
Python/pythonmain.c
Python/pythonrun.c [new file with mode: 0644]
Python/thread.c [new file with mode: 0644]

diff --git a/Include/pythread.h b/Include/pythread.h
new file mode 100644 (file)
index 0000000..91bac2a
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _THREAD_H_included
+#define _THREAD_H_included
+
+#ifdef __STDC__
+#define _P(args)       args
+#else
+#define _P(args)       ()
+#endif
+
+void init_thread _P((void));
+int start_new_thread _P((void (*)(void *), void *));
+void exit_thread _P((void));
+
+typedef void *type_lock;
+
+type_lock allocate_lock _P((void));
+void free_lock _P((type_lock));
+int acquire_lock _P((type_lock, int));
+#define WAIT_LOCK      1
+#define NOWAIT_LOCK    0
+void release_lock _P((type_lock));
+
+void exit_prog _P((int));
+
+#undef _P
+
+#endif
diff --git a/Include/thread.h b/Include/thread.h
new file mode 100644 (file)
index 0000000..91bac2a
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _THREAD_H_included
+#define _THREAD_H_included
+
+#ifdef __STDC__
+#define _P(args)       args
+#else
+#define _P(args)       ()
+#endif
+
+void init_thread _P((void));
+int start_new_thread _P((void (*)(void *), void *));
+void exit_thread _P((void));
+
+typedef void *type_lock;
+
+type_lock allocate_lock _P((void));
+void free_lock _P((type_lock));
+int acquire_lock _P((type_lock, int));
+#define WAIT_LOCK      1
+#define NOWAIT_LOCK    0
+void release_lock _P((type_lock));
+
+void exit_prog _P((int));
+
+#undef _P
+
+#endif
index 0973b77b602978f52d7003539a46ae19abaa8a05..8ed889a308ab7f9df9a5a4b8547502fabc922fa0 100644 (file)
@@ -123,6 +123,7 @@ extern void initpwd();
 extern void initgrp();
 extern void initmarshal();
 extern void initselect();
+extern void initsocket();
 
 #ifdef USE_AUDIO
 extern void initaudio();
@@ -148,15 +149,15 @@ extern void initpanel();
 #ifdef USE_STDWIN
 extern void initstdwin();
 #endif
-#ifdef USE_SOCKET
-extern void initsocket();
-#endif
 #ifdef USE_JPEG
 extern void initjpeg();
 #endif
 #ifdef USE_CD
 extern void initcd();
 #endif
+#ifdef USE_THREAD
+extern void initthread();
+#endif
 
 struct {
        char *name;
@@ -173,6 +174,7 @@ struct {
        {"grp",         initgrp},
        {"marshal",     initmarshal},
        {"select",      initselect},
+       {"socket",      initsocket},
 
 
        /* Optional modules */
@@ -206,10 +208,6 @@ struct {
        {"stdwin",      initstdwin},
 #endif
 
-#ifdef USE_SOCKET
-       {"socket",      initsocket},
-#endif
-
 #ifdef USE_JPEG
        {"jpeg",        initjpeg},
 #endif
@@ -218,5 +216,9 @@ struct {
        {"cd",          initcd},
 #endif
 
+#ifdef USE_THREAD
+       {"thread",      initthread},
+#endif
+
        {0,             0}              /* Sentinel */
 };
diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c
new file mode 100644 (file)
index 0000000..c4de295
--- /dev/null
@@ -0,0 +1,294 @@
+/***********************************************************
+Copyright 1991, 1992 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.
+
+******************************************************************/
+
+/* Thread module */
+/* Interface to Sjoerd's portable C thread library */
+
+#include "allobjects.h"
+#include "modsupport.h"
+#include "compile.h"
+#include "ceval.h"
+
+#include "thread.h"
+
+extern void init_save_thread PROTO((void));
+extern void* save_thread PROTO((void));
+extern void restore_thread PROTO((void *));
+
+object *ThreadError;
+
+
+/* Lock objects */
+
+typedef struct {
+       OB_HEAD
+       type_lock lock_lock;
+} lockobject;
+
+extern typeobject Locktype;    /* Really static, forward */
+
+#define is_lockobject(v)               ((v)->ob_type == &Locktype)
+
+static lockobject *
+newlockobject()
+{
+       lockobject *self;
+       self = NEWOBJ(lockobject, &Locktype);
+       if (self == NULL)
+               return NULL;
+       self->lock_lock = allocate_lock();
+       if (self->lock_lock == NULL) {
+               DEL(self);
+               self = NULL;
+               err_setstr(ThreadError, "can't allocate lock");
+       }
+       return self;
+}
+
+static void
+lock_dealloc(self)
+       lockobject *self;
+{
+       /* Unlock the lock so it's safe to free it */
+       acquire_lock(self->lock_lock, 0);
+       release_lock(self->lock_lock);
+       
+       free_lock(self->lock_lock);
+       DEL(self);
+}
+
+static object *
+lock_acquire_lock(self, args)
+       lockobject *self;
+       object *args;
+{
+       void *save;
+       int i;
+
+       if (args != NULL) {
+               if (!getargs(args, "i", &i))
+                       return NULL;
+       }
+       else
+               i = 1;
+
+       save = save_thread();
+
+       i = acquire_lock(self->lock_lock, i);
+
+       restore_thread(save);
+
+       if (args == NULL) {
+               INCREF(None);
+               return None;
+       }
+       else
+               return newintobject((long)i);
+}
+
+static object *
+lock_release_lock(self, args)
+       lockobject *self;
+       object *args;
+{
+       if (!getnoarg(args))
+               return NULL;
+
+       /* Sanity check: the lock must be locked */
+       if (acquire_lock(self->lock_lock, 0)) {
+               release_lock(self->lock_lock);
+               err_setstr(ThreadError, "release unlocked lock");
+               return NULL;
+       }
+
+       release_lock(self->lock_lock);
+       INCREF(None);
+       return None;
+}
+
+static object *
+lock_locked_lock(self, args)
+       lockobject *self;
+       object *args;
+{
+       if (!getnoarg(args))
+               return NULL;
+
+       if (acquire_lock(self->lock_lock, 0)) {
+               release_lock(self->lock_lock);
+               return newintobject(0L);
+       }
+       return newintobject(1L);
+}
+
+static struct methodlist lock_methods[] = {
+       {"acquire_lock",        lock_acquire_lock},
+       {"acquire",             lock_acquire_lock},
+       {"release_lock",        lock_release_lock},
+       {"release",             lock_release_lock},
+       {"locked_lock",         lock_locked_lock},
+       {"locked",              lock_locked_lock},
+       {NULL,                  NULL}           /* sentinel */
+};
+
+static object *
+lock_getattr(self, name)
+       lockobject *self;
+       char *name;
+{
+       return findmethod(lock_methods, (object *)self, name);
+}
+
+static typeobject Locktype = {
+       OB_HEAD_INIT(&Typetype)
+       0,                      /*ob_size*/
+       "lock",                 /*tp_name*/
+       sizeof(lockobject),     /*tp_size*/
+       0,                      /*tp_itemsize*/
+       /* methods */
+       lock_dealloc,   /*tp_dealloc*/
+       0,              /*tp_print*/
+       lock_getattr,   /*tp_getattr*/
+       0,              /*tp_setattr*/
+       0,              /*tp_compare*/
+       0,              /*tp_repr*/
+};
+
+
+/* Module functions */
+
+static void
+t_bootstrap(args_raw)
+       void *args_raw;
+{
+       object *args = (object *) args_raw;
+       object *func, *arg, *res;
+
+       restore_thread((void *)NULL);
+       func = gettupleitem(args, 0);
+       arg = gettupleitem(args, 1);
+       res = call_object(func, arg);
+       DECREF(arg); /* Matches the INCREF(arg) in thread_start_new_thread */
+       if (res == NULL) {
+               fprintf(stderr, "Unhandled exception in thread:\n");
+               print_error(); /* From pythonmain.c */
+               fprintf(stderr, "Exiting the entire program\n");
+               goaway(1);
+       }
+       (void) save_thread();
+       exit_thread();
+}
+
+static object *
+thread_start_new_thread(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       object *func, *arg;
+
+       if (!getargs(args, "(OO)", &func, &arg))
+               return NULL;
+       INCREF(args);
+       if (!start_new_thread(t_bootstrap, (void*) args)) {
+               DECREF(args);
+               err_setstr(ThreadError, "can't start new thread\n");
+               return NULL;
+       }
+       /* Otherwise the DECREF(args) is done by t_bootstrap */
+       INCREF(None);
+       return None;
+}
+
+static object *
+thread_exit_thread(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       if (!getnoarg(args))
+               return NULL;
+       (void) save_thread();
+       exit_thread();
+       for (;;) { } /* Should not be reached */
+}
+
+static object *
+thread_exit_prog(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       int sts;
+       if (!getargs(args, "i", &sts))
+               return NULL;
+       goaway(sts);
+       for (;;) { } /* Should not be reached */
+}
+
+static object *
+thread_allocate_lock(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       if (!getnoarg(args))
+               return NULL;
+       return newlockobject();
+}
+
+static struct methodlist thread_methods[] = {
+       {"start_new_thread",    thread_start_new_thread},
+       {"start_new",           thread_start_new_thread},
+       {"allocate_lock",       thread_allocate_lock},
+       {"allocate",            thread_allocate_lock},
+       {"exit_thread",         thread_exit_thread},
+       {"exit",                thread_exit_thread},
+       {"exit_prog",           thread_exit_prog},
+       {NULL,                  NULL}           /* sentinel */
+};
+
+
+/* Initialization function */
+
+void
+initthread()
+{
+       object *m, *d, *x;
+
+       /* Create the module and add the functions */
+       m = initmodule("thread", thread_methods);
+
+       /* Add a symbolic constant */
+       d = getmoduledict(m);
+       ThreadError = newstringobject("thread.error");
+       INCREF(ThreadError);
+       dictinsert(d, "error", ThreadError);
+
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module thread");
+
+       /* Initialize the C thread library */
+       init_thread();
+
+       /* Initialize the interpreter's stack save/restore mechanism */
+       init_save_thread();
+}
index 4a921f034e7a3a4b7c77ae6958535792c2fde1e0..5a278a9bd3ffa556645ae7ce7ada95be16c3c53f 100644 (file)
@@ -104,11 +104,14 @@ time_sleep(self, args)
        object *self;
        object *args;
 {
+       void *save, *save_thread(), restore_thread();
        int secs;
        SIGTYPE (*sigsave)() = 0; /* Initialized to shut lint up */
        if (!getintarg(args, &secs))
                return NULL;
+       save = save_thread();
        if (setjmp(sleep_intr)) {
+               restore_thread(save);
                signal(SIGINT, sigsave);
                err_set(KeyboardInterrupt);
                return NULL;
@@ -117,6 +120,7 @@ time_sleep(self, args)
        if (sigsave != (SIGTYPE (*)()) SIG_IGN)
                signal(SIGINT, sleep_catcher);
        sleep(secs);
+       restore_thread(save);
        signal(SIGINT, sigsave);
        INCREF(None);
        return None;
@@ -147,11 +151,14 @@ time_millisleep(self, args)
        object *self;
        object *args;
 {
+       void *save, *save_thread(), restore_thread();
        long msecs;
        SIGTYPE (*sigsave)();
        if (!getlongarg(args, &msecs))
                return NULL;
+       save = save_thread();
        if (setjmp(sleep_intr)) {
+               restore_thread(save);
                signal(SIGINT, sigsave);
                err_set(KeyboardInterrupt);
                return NULL;
@@ -160,6 +167,7 @@ time_millisleep(self, args)
        if (sigsave != (SIGTYPE (*)()) SIG_IGN)
                signal(SIGINT, sleep_catcher);
        millisleep(msecs);
+       restore_thread(save);
        signal(SIGINT, sigsave);
        INCREF(None);
        return None;
diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c
new file mode 100644 (file)
index 0000000..070a622
--- /dev/null
@@ -0,0 +1,92 @@
+/***********************************************************
+Copyright 1991, 1992 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.
+
+******************************************************************/
+
+/* xx module */
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+
+/* Function of two integers returning integer */
+
+static object *
+xx_foo(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       long i, j;
+       long res;
+       if (!getargs(args, "(ll)", &i, &j))
+               return NULL;
+       res = i+j; /* XXX Do something here */
+       return newintobject(res);
+}
+
+
+/* Function of no arguments returning None */
+
+static object *
+xx_bar(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       int i, j;
+       if (!getnoarg(args))
+               return NULL;
+       /* XXX Do something here */
+       INCREF(None);
+       return None;
+}
+
+
+/* List of functions defined in the module */
+
+static struct methodlist xx_methods[] = {
+       {"foo",         xx_foo},
+       {"bar",         xx_bar},
+       {NULL,          NULL}           /* sentinel */
+};
+
+
+/* Initialization function for the module (*must* be called initxx) */
+
+void
+initxx()
+{
+       object *m, *d, *x;
+
+       /* Create the module and add the functions */
+       m = initmodule("xx", xx_methods);
+
+       /* Add some symbolic constants to the module */
+       d = getmoduledict(m);
+       x = newstringobject("xx.error");
+       dictinsert(d, "error", x);
+       x = newintobject(42L);
+       dictinsert(d, "magic", x);
+
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module xx");
+}
index b026413a1ab315a9a72c19c80b4a7bd969b00e0b..99f4e5e07a88dd8c44be8312631760fa258ac440 100644 (file)
@@ -321,6 +321,7 @@ getline(f, n)
        fileobject *f;
        int n;
 {
+       void *save, *save_thread(), restore_thread();
        register FILE *fp;
        register int c;
        register char *buf, *end;
@@ -334,16 +335,19 @@ getline(f, n)
                return NULL;
        buf = BUF(v);
        end = buf + n2;
-       
+
+       save = save_thread();
        for (;;) {
                if ((c = getc(fp)) == EOF) {
                        clearerr(fp);
                        if (intrcheck()) {
+                               restore_thread(save);
                                DECREF(v);
                                err_set(KeyboardInterrupt);
                                return NULL;
                        }
                        if (n < 0 && buf == BUF(v)) {
+                               restore_thread(save);
                                DECREF(v);
                                err_setstr(EOFError,
                                           "EOF when reading a line");
@@ -361,13 +365,16 @@ getline(f, n)
                                break;
                        n1 = n2;
                        n2 += 1000;
+                       restore_thread(save);
                        if (resizestring(&v, n2) < 0)
                                return NULL;
+                       save = save_thread();
                        buf = BUF(v) + n1;
                        end = BUF(v) + n2;
                }
        }
-       
+       restore_thread(save);
+
        n1 = buf - BUF(v);
        if (n1 != n2)
                resizestring(&v, n1);
index 0b2f924a84d7d3bfd13dd2775391ebee2f624233..32c52c7352ff7f52864429242a4ff3aea259a531 100644 (file)
@@ -84,6 +84,79 @@ static object *build_class PROTO((object *, object *));
 static frameobject *current_frame;
 
 
+/* Interface for threads.
+
+   A module that plans to do a blocking system call (or something else
+   that lasts a long time and doesn't touch Python data) can allow other
+   threads to run as follows:
+
+       void *x;
+
+       ...preparations here...
+       x = save_thread();
+       ...blocking system call here...
+       restore_thread(x);
+       ...interpretr result here...
+
+   For convenience, that the value of 'errno' is restored across the
+   the call to restore_thread().
+
+   The function init_save_thread() should be called only from
+   initthread() in "threadmodule.c".
+
+   Note that not yet all candidates have been converted to use this
+   mechanism!
+*/
+
+#ifdef USE_THREAD
+#include <errno.h>
+#include "thread.h"
+static type_lock interpreter_lock;
+
+void
+init_save_thread()
+{
+#ifdef USE_THREAD
+       if (interpreter_lock)
+               fatal("2nd call to init_save_thread");
+       interpreter_lock = allocate_lock();
+       acquire_lock(interpreter_lock, 1);
+#endif
+}
+#endif
+
+void *
+save_thread()
+{
+#ifdef USE_THREAD
+       if (interpreter_lock) {
+               void *res;
+               res = (void *)current_frame;
+               current_frame = NULL;
+               release_lock(interpreter_lock);
+               return res;
+       }
+       else
+               return NULL;
+#endif
+}
+
+void
+restore_thread(x)
+       void *x;
+{
+#ifdef USE_THREAD
+       if (interpreter_lock) {
+               int err;
+               err = errno;
+               acquire_lock(interpreter_lock, 1);
+               errno = err;
+               current_frame = (frameobject *)x;
+       }
+#endif
+}
+
+
 /* Status code for main loop (reason for stack unwind) */
 
 enum why_code {
@@ -210,17 +283,34 @@ eval_code(co, globals, locals, arg)
        for (;;) {
                static int ticker;
                
-               /* Do periodic things */
+               /* Do periodic things.
+                  Doing this every time through the loop would add
+                  too much overhead (a function call per instruction).
+                  So we do it only every tenth instruction. */
                
                if (--ticker < 0) {
-                       ticker = 100;
+                       ticker = 10;
                        if (intrcheck()) {
                                err_set(KeyboardInterrupt);
                                why = WHY_EXCEPTION;
                                goto on_error;
                        }
+
+#ifdef USE_THREAD
+                       if (interpreter_lock) {
+                               /* Give another thread a chance */
+
+                               current_frame = NULL;
+                               release_lock(interpreter_lock);
+
+                               /* Other threads may run now */
+
+                               acquire_lock(interpreter_lock, 1);
+                               current_frame = f;
+                       }
+#endif
                }
-               
+
                /* Extract opcode and argument */
                
                opcode = NEXTOP();
index a14116808874e0336ca423c30d7d9577364c733d..0f76bfd2d927196e32d9e6307f327da718ec1c32 100644 (file)
@@ -26,23 +26,10 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include "allobjects.h"
 
-#include "grammar.h"
-#include "node.h"
-#include "parsetok.h"
-#include "graminit.h"
-#include "errcode.h"
-#include "sysmodule.h"
-#include "compile.h"
-#include "ceval.h"
-#include "pythonrun.h"
-#include "import.h"
-
 extern char *getpythonpath();
 
-extern grammar gram; /* From graminit.c */
-
-int debugging; /* Needed by parser.c */
-int verbose; /* Needed by import.c */
+extern int debugging; /* Needed by parser.c */
+extern int verbose; /* Needed by import.c */
 
 /* Interface to getopt(): */
 extern int optind;
@@ -108,12 +95,12 @@ main(argc, argv)
        
        initall();
        
-       setpythonpath(getpythonpath());
        if (command != NULL) {
                /* Backup optind and force sys.argv[0] = '-c' */
                optind--;
                argv[optind] = "-c";
        }
+
        setpythonargv(argc-optind, argv+optind);
 
        if (command) {
@@ -126,368 +113,3 @@ main(argc, argv)
        goaway(sts);
        /*NOTREACHED*/
 }
-
-/* Initialize all */
-
-void
-initall()
-{
-       static int inited;
-       
-       if (inited)
-               return;
-       inited = 1;
-       
-       initimport();
-       
-       /* Modules 'builtin' and 'sys' are initialized here,
-          they are needed by random bits of the interpreter.
-          All other modules are optional and should be initialized
-          by the initcalls() of a specific configuration. */
-       
-       initbuiltin(); /* Also initializes builtin exceptions */
-       initsys();
-       
-       initcalls(); /* Configuration-dependent initializations */
-       
-       initintr(); /* For intrcheck() */
-}
-
-/* Parse input from a file and execute it */
-
-int
-run(fp, filename)
-       FILE *fp;
-       char *filename;
-{
-       if (filename == NULL)
-               filename = "???";
-       if (isatty((int)fileno(fp)))
-               return run_tty_loop(fp, filename);
-       else
-               return run_script(fp, filename);
-}
-
-int
-run_tty_loop(fp, filename)
-       FILE *fp;
-       char *filename;
-{
-       object *v;
-       int ret;
-       v = sysget("ps1");
-       if (v == NULL) {
-               sysset("ps1", v = newstringobject(">>> "));
-               XDECREF(v);
-       }
-       v = sysget("ps2");
-       if (v == NULL) {
-               sysset("ps2", v = newstringobject("... "));
-               XDECREF(v);
-       }
-       for (;;) {
-               ret = run_tty_1(fp, filename);
-#ifdef REF_DEBUG
-               fprintf(stderr, "[%ld refs]\n", ref_total);
-#endif
-               if (ret == E_EOF)
-                       return 0;
-               /*
-               if (ret == E_NOMEM)
-                       return -1;
-               */
-       }
-}
-
-int
-run_tty_1(fp, filename)
-       FILE *fp;
-       char *filename;
-{
-       object *m, *d, *v, *w;
-       node *n;
-       char *ps1, *ps2;
-       int err;
-       v = sysget("ps1");
-       w = sysget("ps2");
-       if (v != NULL && is_stringobject(v)) {
-               INCREF(v);
-               ps1 = getstringvalue(v);
-       }
-       else {
-               v = NULL;
-               ps1 = "";
-       }
-       if (w != NULL && is_stringobject(w)) {
-               INCREF(w);
-               ps2 = getstringvalue(w);
-       }
-       else {
-               w = NULL;
-               ps2 = "";
-       }
-       err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
-       XDECREF(v);
-       XDECREF(w);
-       if (err == E_EOF)
-               return E_EOF;
-       if (err != E_DONE) {
-               err_input(err);
-               print_error();
-               return err;
-       }
-       m = add_module("__main__");
-       if (m == NULL)
-               return -1;
-       d = getmoduledict(m);
-       v = run_node(n, filename, d, d);
-       flushline();
-       if (v == NULL) {
-               print_error();
-               return -1;
-       }
-       DECREF(v);
-       return 0;
-}
-
-int
-run_script(fp, filename)
-       FILE *fp;
-       char *filename;
-{
-       object *m, *d, *v;
-       m = add_module("__main__");
-       if (m == NULL)
-               return -1;
-       d = getmoduledict(m);
-       v = run_file(fp, filename, file_input, d, d);
-       flushline();
-       if (v == NULL) {
-               print_error();
-               return -1;
-       }
-       DECREF(v);
-       return 0;
-}
-
-int
-run_command(command)
-       char *command;
-{
-       object *m, *d, *v;
-       m = add_module("__main__");
-       if (m == NULL)
-               return -1;
-       d = getmoduledict(m);
-       v = run_string(command, file_input, d, d);
-       flushline();
-       if (v == NULL) {
-               print_error();
-               return -1;
-       }
-       DECREF(v);
-       return 0;
-}
-
-void
-print_error()
-{
-       object *exception, *v;
-       err_get(&exception, &v);
-       if (exception == SystemExit) {
-               if (v == NULL || v == None)
-                       goaway(0);
-               if (is_intobject(v))
-                       goaway((int)getintvalue(v));
-               else {
-                       printobject(v, stderr, PRINT_RAW);
-                       fprintf(stderr, "\n");
-                       goaway(1);
-               }
-       }
-       sysset("last_type", exception);
-       sysset("last_value", v);
-       if (printobject(exception, stderr, PRINT_RAW) != 0)
-               err_clear();
-       if (v != NULL && v != None) {
-               fprintf(stderr, ": ");
-               if (printobject(v, stderr, PRINT_RAW) != 0)
-                       err_clear();
-       }
-       fprintf(stderr, "\n");
-       XDECREF(exception);
-       XDECREF(v);
-       printtraceback(stderr);
-}
-
-object *
-run_string(str, start, globals, locals)
-       char *str;
-       int start;
-       /*dict*/object *globals, *locals;
-{
-       node *n;
-       int err;
-       err = parse_string(str, start, &n);
-       return run_err_node(err, n, "<string>", globals, locals);
-}
-
-object *
-run_file(fp, filename, start, globals, locals)
-       FILE *fp;
-       char *filename;
-       int start;
-       /*dict*/object *globals, *locals;
-{
-       node *n;
-       int err;
-       err = parse_file(fp, filename, start, &n);
-       return run_err_node(err, n, filename, globals, locals);
-}
-
-object *
-run_err_node(err, n, filename, globals, locals)
-       int err;
-       node *n;
-       char *filename;
-       /*dict*/object *globals, *locals;
-{
-       if (err != E_DONE) {
-               err_input(err);
-               return NULL;
-       }
-       return run_node(n, filename, globals, locals);
-}
-
-object *
-run_node(n, filename, globals, locals)
-       node *n;
-       char *filename;
-       /*dict*/object *globals, *locals;
-{
-       if (globals == NULL) {
-               globals = getglobals();
-               if (locals == NULL)
-                       locals = getlocals();
-       }
-       else {
-               if (locals == NULL)
-                       locals = globals;
-       }
-       return eval_node(n, filename, globals, locals);
-}
-
-object *
-eval_node(n, filename, globals, locals)
-       node *n;
-       char *filename;
-       object *globals;
-       object *locals;
-{
-       codeobject *co;
-       object *v;
-       co = compile(n, filename);
-       freetree(n);
-       if (co == NULL)
-               return NULL;
-       v = eval_code(co, globals, locals, (object *)NULL);
-       DECREF(co);
-       return v;
-}
-
-/* Simplified interface to parsefile */
-
-int
-parse_file(fp, filename, start, n_ret)
-       FILE *fp;
-       char *filename;
-       int start;
-       node **n_ret;
-{
-       return parsefile(fp, filename, &gram, start,
-                               (char *)0, (char *)0, n_ret);
-}
-
-/* Simplified interface to parsestring */
-
-int
-parse_string(str, start, n_ret)
-       char *str;
-       int start;
-       node **n_ret;
-{
-       int err = parsestring(str, &gram, start, n_ret);
-       /* Don't confuse early end of string with early end of input */
-       if (err == E_EOF)
-               err = E_SYNTAX;
-       return err;
-}
-
-/* Print fatal error message and abort */
-
-void
-fatal(msg)
-       char *msg;
-{
-       fprintf(stderr, "Fatal error: %s\n", msg);
-       abort();
-}
-
-/* Clean up and exit */
-
-void
-goaway(sts)
-       int sts;
-{
-       flushline();
-       
-       /* XXX Call doneimport() before donecalls(), since donecalls()
-          calls wdone(), and doneimport() may close windows */
-       doneimport();
-       donecalls();
-       
-       err_clear();
-
-#ifdef REF_DEBUG
-       fprintf(stderr, "[%ld refs]\n", ref_total);
-#endif
-
-#ifdef TRACE_REFS
-       if (askyesno("Print left references?")) {
-               printrefs(stderr);
-       }
-#endif /* TRACE_REFS */
-
-       exit(sts);
-       /*NOTREACHED*/
-}
-
-#ifdef TRACE_REFS
-/* Ask a yes/no question */
-
-static int
-askyesno(prompt)
-       char *prompt;
-{
-       char buf[256];
-       
-       printf("%s [ny] ", prompt);
-       if (fgets(buf, sizeof buf, stdin) == NULL)
-               return 0;
-       return buf[0] == 'y' || buf[0] == 'Y';
-}
-#endif
-
-#ifdef applec /* MPW (also usable for Think C 3.0) */
-
-/* Check for file descriptor connected to interactive device.
-   Pretend that stdin is always interactive, other files never. */
-
-int
-isatty(fd)
-       int fd;
-{
-       return fd == fileno(stdin);
-}
-
-#endif
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
new file mode 100644 (file)
index 0000000..2a68f24
--- /dev/null
@@ -0,0 +1,424 @@
+/***********************************************************
+Copyright 1991, 1992 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.
+
+******************************************************************/
+
+/* Python interpreter top-level routines, including init/exit */
+
+#include "allobjects.h"
+
+#include "grammar.h"
+#include "node.h"
+#include "parsetok.h"
+#include "graminit.h"
+#include "errcode.h"
+#include "sysmodule.h"
+#include "compile.h"
+#include "ceval.h"
+#include "pythonrun.h"
+#include "import.h"
+
+#ifdef USE_THREAD
+extern void *save_thread();
+#endif
+
+extern char *getpythonpath();
+
+extern grammar gram; /* From graminit.c */
+
+int debugging; /* Needed by parser.c */
+int verbose; /* Needed by import.c */
+
+/* Initialize all */
+
+void
+initall()
+{
+       static int inited;
+       
+       if (inited)
+               return;
+       inited = 1;
+       
+       initimport();
+       
+       /* Modules 'builtin' and 'sys' are initialized here,
+          they are needed by random bits of the interpreter.
+          All other modules are optional and are initialized
+          when they are first imported. */
+       
+       initbuiltin(); /* Also initializes builtin exceptions */
+       initsys();
+       
+       initcalls(); /* Configuration-dependent initializations */
+       
+       initintr(); /* For intrcheck() */
+
+       setpythonpath(getpythonpath());
+}
+
+/* Parse input from a file and execute it */
+
+int
+run(fp, filename)
+       FILE *fp;
+       char *filename;
+{
+       if (filename == NULL)
+               filename = "???";
+       if (isatty((int)fileno(fp)))
+               return run_tty_loop(fp, filename);
+       else
+               return run_script(fp, filename);
+}
+
+int
+run_tty_loop(fp, filename)
+       FILE *fp;
+       char *filename;
+{
+       object *v;
+       int ret;
+       v = sysget("ps1");
+       if (v == NULL) {
+               sysset("ps1", v = newstringobject(">>> "));
+               XDECREF(v);
+       }
+       v = sysget("ps2");
+       if (v == NULL) {
+               sysset("ps2", v = newstringobject("... "));
+               XDECREF(v);
+       }
+       for (;;) {
+               ret = run_tty_1(fp, filename);
+#ifdef REF_DEBUG
+               fprintf(stderr, "[%ld refs]\n", ref_total);
+#endif
+               if (ret == E_EOF)
+                       return 0;
+               /*
+               if (ret == E_NOMEM)
+                       return -1;
+               */
+       }
+}
+
+int
+run_tty_1(fp, filename)
+       FILE *fp;
+       char *filename;
+{
+       void *save, *save_thread(), restore_thread();
+       object *m, *d, *v, *w;
+       node *n;
+       char *ps1, *ps2;
+       int err;
+       v = sysget("ps1");
+       w = sysget("ps2");
+       if (v != NULL && is_stringobject(v)) {
+               INCREF(v);
+               ps1 = getstringvalue(v);
+       }
+       else {
+               v = NULL;
+               ps1 = "";
+       }
+       if (w != NULL && is_stringobject(w)) {
+               INCREF(w);
+               ps2 = getstringvalue(w);
+       }
+       else {
+               w = NULL;
+               ps2 = "";
+       }
+       save = save_thread();
+       err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
+       restore_thread(save);
+       XDECREF(v);
+       XDECREF(w);
+       if (err == E_EOF)
+               return E_EOF;
+       if (err != E_DONE) {
+               err_input(err);
+               print_error();
+               return err;
+       }
+       m = add_module("__main__");
+       if (m == NULL)
+               return -1;
+       d = getmoduledict(m);
+       v = run_node(n, filename, d, d);
+       flushline();
+       if (v == NULL) {
+               print_error();
+               return -1;
+       }
+       DECREF(v);
+       return 0;
+}
+
+int
+run_script(fp, filename)
+       FILE *fp;
+       char *filename;
+{
+       object *m, *d, *v;
+       m = add_module("__main__");
+       if (m == NULL)
+               return -1;
+       d = getmoduledict(m);
+       v = run_file(fp, filename, file_input, d, d);
+       flushline();
+       if (v == NULL) {
+               print_error();
+               return -1;
+       }
+       DECREF(v);
+       return 0;
+}
+
+int
+run_command(command)
+       char *command;
+{
+       object *m, *d, *v;
+       m = add_module("__main__");
+       if (m == NULL)
+               return -1;
+       d = getmoduledict(m);
+       v = run_string(command, file_input, d, d);
+       flushline();
+       if (v == NULL) {
+               print_error();
+               return -1;
+       }
+       DECREF(v);
+       return 0;
+}
+
+void
+print_error()
+{
+       object *exception, *v;
+       err_get(&exception, &v);
+       if (exception == SystemExit) {
+               if (v == NULL || v == None)
+                       goaway(0);
+               if (is_intobject(v))
+                       goaway((int)getintvalue(v));
+               else {
+                       printobject(v, stderr, PRINT_RAW);
+                       fprintf(stderr, "\n");
+                       goaway(1);
+               }
+       }
+       sysset("last_type", exception);
+       sysset("last_value", v);
+       if (printobject(exception, stderr, PRINT_RAW) != 0)
+               err_clear();
+       if (v != NULL && v != None) {
+               fprintf(stderr, ": ");
+               if (printobject(v, stderr, PRINT_RAW) != 0)
+                       err_clear();
+       }
+       fprintf(stderr, "\n");
+       XDECREF(exception);
+       XDECREF(v);
+       printtraceback(stderr);
+}
+
+object *
+run_string(str, start, globals, locals)
+       char *str;
+       int start;
+       /*dict*/object *globals, *locals;
+{
+       node *n;
+       int err;
+       err = parse_string(str, start, &n);
+       return run_err_node(err, n, "<string>", globals, locals);
+}
+
+object *
+run_file(fp, filename, start, globals, locals)
+       FILE *fp;
+       char *filename;
+       int start;
+       /*dict*/object *globals, *locals;
+{
+       node *n;
+       int err;
+       err = parse_file(fp, filename, start, &n);
+       return run_err_node(err, n, filename, globals, locals);
+}
+
+object *
+run_err_node(err, n, filename, globals, locals)
+       int err;
+       node *n;
+       char *filename;
+       /*dict*/object *globals, *locals;
+{
+       if (err != E_DONE) {
+               err_input(err);
+               return NULL;
+       }
+       return run_node(n, filename, globals, locals);
+}
+
+object *
+run_node(n, filename, globals, locals)
+       node *n;
+       char *filename;
+       /*dict*/object *globals, *locals;
+{
+       if (globals == NULL) {
+               globals = getglobals();
+               if (locals == NULL)
+                       locals = getlocals();
+       }
+       else {
+               if (locals == NULL)
+                       locals = globals;
+       }
+       return eval_node(n, filename, globals, locals);
+}
+
+object *
+eval_node(n, filename, globals, locals)
+       node *n;
+       char *filename;
+       object *globals;
+       object *locals;
+{
+       codeobject *co;
+       object *v;
+       co = compile(n, filename);
+       freetree(n);
+       if (co == NULL)
+               return NULL;
+       v = eval_code(co, globals, locals, (object *)NULL);
+       DECREF(co);
+       return v;
+}
+
+/* Simplified interface to parsefile */
+
+int
+parse_file(fp, filename, start, n_ret)
+       FILE *fp;
+       char *filename;
+       int start;
+       node **n_ret;
+{
+       return parsefile(fp, filename, &gram, start,
+                               (char *)0, (char *)0, n_ret);
+}
+
+/* Simplified interface to parsestring */
+
+int
+parse_string(str, start, n_ret)
+       char *str;
+       int start;
+       node **n_ret;
+{
+       int err = parsestring(str, &gram, start, n_ret);
+       /* Don't confuse early end of string with early end of input */
+       if (err == E_EOF)
+               err = E_SYNTAX;
+       return err;
+}
+
+/* Print fatal error message and abort */
+
+void
+fatal(msg)
+       char *msg;
+{
+       fprintf(stderr, "Fatal error: %s\n", msg);
+       abort();
+}
+
+/* Clean up and exit */
+
+void
+goaway(sts)
+       int sts;
+{
+       flushline();
+       
+       /* XXX Call doneimport() before donecalls(), since donecalls()
+          calls wdone(), and doneimport() may close windows */
+       doneimport();
+       donecalls();
+       
+       err_clear();
+
+#ifdef REF_DEBUG
+       fprintf(stderr, "[%ld refs]\n", ref_total);
+#endif
+
+#ifdef TRACE_REFS
+       if (askyesno("Print left references?")) {
+               printrefs(stderr);
+       }
+#endif /* TRACE_REFS */
+
+#ifdef USE_THREAD
+       (void) save_thread();
+       exit_prog(sts);
+#else
+       exit(sts);
+#endif
+       /*NOTREACHED*/
+}
+
+#ifdef TRACE_REFS
+/* Ask a yes/no question */
+
+static int
+askyesno(prompt)
+       char *prompt;
+{
+       char buf[256];
+       
+       printf("%s [ny] ", prompt);
+       if (fgets(buf, sizeof buf, stdin) == NULL)
+               return 0;
+       return buf[0] == 'y' || buf[0] == 'Y';
+}
+#endif
+
+#ifdef applec /* MPW (also usable for Think C 3.0) */
+
+/* Check for file descriptor connected to interactive device.
+   Pretend that stdin is always interactive, other files never. */
+
+int
+isatty(fd)
+       int fd;
+{
+       return fd == fileno(stdin);
+}
+
+#endif
diff --git a/Python/thread.c b/Python/thread.c
new file mode 100644 (file)
index 0000000..1f0633a
--- /dev/null
@@ -0,0 +1,263 @@
+#include "thread.h"
+
+#ifdef __sgi
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <ulocks.h>
+
+static usptr_t *shared_arena;
+static int exit_status;
+static int do_exit;
+static int exiting;
+#endif
+#ifdef sun
+#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;
+};
+#endif
+#ifdef C_THREADS
+#include <cthreads.h>
+#endif
+
+#ifdef __STDC__
+#define _P(args)               args
+#define _P0()                  (void)
+#define _P1(v,t)               (t)
+#define _P2(v1,t1,v2,t2)       (t1,t2)
+#else
+#define _P(args)               ()
+#define _P0()                  ()
+#define _P1(v,t)               (v) t;
+#define _P2(v1,t1,v2,t2)       (v1,v2) t1; t2;
+#endif
+
+static int initialized;
+
+int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
+{
+#ifdef sun
+       thread_t tid;
+#endif
+#ifdef DEBUG
+       printf("start_new_thread called\n");
+#endif
+       if (!initialized)
+               init_thread();
+#ifdef __sgi
+       if (sproc(func, PR_SALL, arg) < 0)
+               return 0;
+       return 1;
+#endif
+#ifdef SOLARIS
+       (void) thread_create(0, 0, func, arg, THREAD_NEW_LWP);
+#endif
+#ifdef sun
+       if (lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg) < 0)
+               return 0;
+       return 1;
+#endif
+#ifdef C_THREADS
+       (void) cthread_fork(func, arg);
+#endif
+}
+
+#ifdef __sgi
+void maybe_exit _P0()
+{
+       if (exiting)
+               return;
+       exit_prog(0);
+}
+#endif
+
+void exit_thread _P0()
+{
+#ifdef DEBUG
+       printf("exit_thread called\n");
+#endif
+       if (!initialized)
+               exit(0);
+#ifdef __sgi
+       exiting = 1;
+       exit(0);
+#endif
+#ifdef SOLARIS
+       thread_exit();
+#endif
+#ifdef sun
+       lwp_destroy(SELF);
+#endif
+#ifdef C_THREADS
+       cthread_exit(0);
+#endif
+}
+
+#ifdef __sgi
+static void exit_sig _P0()
+{
+#ifdef DEBUG
+       printf("exit_sig called\n");
+#endif
+       if (do_exit) {
+#ifdef DEBUG
+               printf("exiting in exit_sig\n");
+#endif
+               exit(exit_status);
+       }
+}
+#endif
+
+void init_thread _P0()
+{
+#ifdef __sgi
+       struct sigaction s;
+#endif
+
+#ifdef DEBUG
+       printf("init_thread called\n");
+#endif
+       initialized = 1;
+
+#ifdef __sgi
+       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);
+       prctl(PR_SETEXITSIG, SIGUSR1);
+       usconfig(CONF_ARENATYPE, US_SHAREDONLY);
+       /*usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);*/
+       shared_arena = usinit(tmpnam(0));
+#endif
+#ifdef sun
+       lwp_setstkcache(STACKSIZE, NSTACKS);
+#endif
+#ifdef C_THREADS
+       cthread_init();
+#endif
+}
+
+type_lock allocate_lock _P0()
+{
+#ifdef __sgi
+       ulock_t lock;
+#endif
+#ifdef sun
+       struct lock *lock;
+       extern char *malloc();
+#endif
+
+#ifdef DEBUG
+       printf("allocate_lock called\n");
+#endif
+       if (!initialized)
+               init_thread();
+
+#ifdef __sgi
+       lock = usnewlock(shared_arena);
+       (void) usinitlock(lock);
+#endif
+#ifdef sun
+       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);
+#endif
+#ifdef DEBUG
+       printf("allocate_lock() -> %lx\n", (long)lock);
+#endif
+       return (type_lock) lock;
+}
+
+void free_lock _P1(lock, type_lock lock)
+{
+#ifdef DEBUG
+       printf("free_lock(%lx) called\n", (long)lock);
+#endif
+#ifdef __sgi
+       usfreelock((ulock_t) lock, shared_arena);
+#endif
+#ifdef sun
+       mon_destroy(((struct lock *) lock)->lock_monitor);
+       free((char *) lock);
+#endif
+}
+
+int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
+{
+       int success;
+
+#ifdef DEBUG
+       printf("acquire_lock(%lx, %d) called\n", (long)lock, waitflag);
+#endif
+#ifdef __sgi
+       if (waitflag)
+               success = ussetlock((ulock_t) lock);
+       else
+               success = uscsetlock((ulock_t) lock, 1); /* Try it once */
+#endif
+#ifdef sun
+       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);
+#endif
+#ifdef DEBUG
+       printf("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success);
+#endif
+       return success;
+}
+
+void release_lock _P1(lock, type_lock lock)
+{
+#ifdef DEBUG
+       printf("release lock(%lx) called\n", (long)lock);
+#endif
+#ifdef __sgi
+       (void) usunsetlock((ulock_t) lock);
+#endif
+#ifdef sun
+       (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);
+#endif
+}
+
+void exit_prog _P1(status, int status)
+{
+#ifdef DEBUG
+       printf("exit_prog(%d) called\n", status);
+#endif
+       if (!initialized)
+               exit(status);
+#ifdef __sgi
+       exiting = 1;
+       do_exit = 1;
+       exit_status = status;
+       exit(status);
+#endif
+#ifdef sun
+       pod_exit(status);
+#endif
+}