diff options
Diffstat (limited to 'Modules/threadmodule.c')
-rw-r--r-- | Modules/threadmodule.c | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c new file mode 100644 index 0000000..c4de295 --- /dev/null +++ b/Modules/threadmodule.c @@ -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(); +} |