diff --git a/src/threads.c b/src/threads.c index f11e3d42b9f910f61f58c4f53fc20f45a89b0683..842716c07be1ccc7315c9091c8f3843e75fb1791 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.24 1997/08/30 18:36:01 grubba Exp $"); +RCSID("$Id: threads.c,v 1.25 1997/08/31 22:24:00 per Exp $"); int num_threads = 1; int threads_disabled = 0; @@ -14,11 +14,12 @@ int threads_disabled = 0; #include "constants.h" #include "program.h" +#include <errno.h> struct object *thread_id; static struct callback *threads_evaluator_callback=0; -MUTEX_T interpreter_lock = PTHREAD_MUTEX_INITIALIZER; +MUTEX_T interpreter_lock; struct program *mutex_key = 0; struct program *thread_id_prog = 0; #ifdef POSIX_THREADS @@ -42,16 +43,21 @@ static void check_threads(struct callback *cb, void *arg, void * arg2) void *new_thread_func(void * data) { -/* static int dbt;*/ +#ifdef MASSIVE_DEBUG + static int dbt; +#endif struct thread_starter arg = *(struct thread_starter *)data; JMP_BUF back; INT32 tmp; -/* fprintf(stderr, "Thread create[%d]...",dbt++);*/ +#ifdef MASSIVE_DEBUG + fprintf(stderr, "Thread create[%d:%p]...",dbt++,data); +#endif if((tmp=mt_lock( & interpreter_lock))) fatal("Failed to lock interpreter, errno %d\n",tmp); -/* fprintf(stderr,"Created[%d]...",dbt);*/ - free((char *)data); /* Moved by per, to avoid some bugs.... */ +#ifdef MASSIVE_DEBUG + fprintf(stderr,"Created[%d:%p]...",dbt,data); +#endif init_interpreter(); thread_id=arg.id; @@ -61,6 +67,10 @@ void *new_thread_func(void * data) ONERROR tmp; SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!"); assign_svalue_no_free(sp++, & throw_value); + free((char *)data); /* Moved by per, to avoid some bugs.... */ +#ifdef MASSIVE_DEBUG + fprintf(stderr,"Error [%d:%p]\n",dbt,data); +#endif APPLY_MASTER("handle_error", 1); pop_stack(); UNSET_ONERROR(tmp); @@ -69,7 +79,11 @@ void *new_thread_func(void * data) push_array_items(arg.args); arg.args=0; f_call_function(args); +#ifdef MASSIVE_DEBUG + fprintf(stderr,"Called [%d:%p]\n",dbt,data); +#endif pop_stack(); /* Discard the return value. /Per */ + free((char *)data); /* Moved by per, to avoid some bugs.... */ } UNSETJMP(back); @@ -86,7 +100,9 @@ void *new_thread_func(void * data) remove_callback(threads_evaluator_callback); threads_evaluator_callback=0; } -/* fprintf(stderr,"Done[%d]\n",dbt--);*/ +#ifdef MASSIVE_DEBUG + fprintf(stderr,"Done[%d:%p]\n",dbt--,data); +#endif mt_unlock(& interpreter_lock); th_exit(0); /* NOT_REACHED, but removes a warning */ @@ -137,7 +153,7 @@ void f_thread_set_concurrency(INT32 args) if(args) c=sp[-args].u.integer; else error("No argument to thread_set_concurrency(int concurrency);\n"); pop_n_elems(args); - num_threads=c; + num_lwps=c; th_setconcurrency(c); } @@ -159,7 +175,11 @@ void f_this_thread(INT32 args) struct mutex_storage { +#ifdef SOLARIS + sema_t sema; +#else COND_T condition; +#endif struct object *key; }; @@ -167,9 +187,10 @@ struct key_storage { struct mutex_storage *mut; int initialized; + struct object *owner; }; -static MUTEX_T mutex_kluge = PTHREAD_MUTEX_INITIALIZER; +static MUTEX_T mutex_kluge; #define OB2KEY(X) ((struct key_storage *)((X)->storage)) @@ -180,14 +201,25 @@ void f_mutex_lock(INT32 args) pop_n_elems(args); m=THIS_MUTEX; + if(m->key && OB2KEY(m->key)->owner == thread_id) + error("Recursive mutex locks!\n"); o=clone_object(mutex_key,0); - mt_lock(& mutex_kluge); +#ifdef SOLARIS THREADS_ALLOW(); - while(m->key) co_wait(& m->condition, & mutex_kluge); + // Might be interrupted by signals. + while((sema_wait( &m->sema )) && (errno==EAGAIN)); + THREADS_DISALLOW(); OB2KEY(o)->mut=m; m->key=o; +#else + THREADS_ALLOW(); + mt_lock(& mutex_kluge); + while(m->key) co_wait(& m->condition, & mutex_kluge); mt_unlock(&mutex_kluge); THREADS_DISALLOW(); + OB2KEY(o)->mut=m; + m->key=o; +#endif push_object(o); } @@ -200,17 +232,14 @@ void f_mutex_trylock(INT32 args) o=clone_object(mutex_key,0); m=THIS_MUTEX; - mt_lock(& mutex_kluge); - THREADS_ALLOW(); + if(m->key && OB2KEY(m->key)->owner == thread_id) + error("Recursive mutex locks!\n"); if(!m->key) { OB2KEY(o)->mut=m; m->key=o; i=1; } - mt_unlock(&mutex_kluge); - THREADS_DISALLOW(); - if(i) { push_object(o); @@ -223,14 +252,22 @@ void f_mutex_trylock(INT32 args) void init_mutex_obj(struct object *o) { +#ifdef SOLARIS + sema_init(& THIS_MUTEX->sema, 1, USYNC_THREAD, NULL ); +#else co_init(& THIS_MUTEX->condition); +#endif THIS_MUTEX->key=0; } void exit_mutex_obj(struct object *o) { if(THIS_MUTEX->key) destruct(THIS_MUTEX->key); +#ifdef SOLARIS + sema_destroy( & THIS_MUTEX->sema ); +#else co_destroy(& THIS_MUTEX->condition); +#endif } #define THIS_KEY ((struct key_storage *)(fp->current_storage)) @@ -238,23 +275,35 @@ void init_mutex_key_obj(struct object *o) { THIS_KEY->mut=0; THIS_KEY->initialized=1; + THIS_KEY->owner=thread_id; } void exit_mutex_key_obj(struct object *o) { - mt_lock(& mutex_kluge); if(THIS_KEY->mut) { #ifdef DEBUG if(THIS_KEY->mut->key != o) fatal("Mutex unlock from wrong key %p != %p!\n",THIS_KEY->mut->key,o); #endif + +#ifdef SOLARIS + sema_post( &THIS_KEY->mut->sema ); + THIS_KEY->mut->key=0; +#else + mt_lock(& mutex_kluge); +#endif THIS_KEY->mut->key=0; +#ifndef SOLARIS co_signal(& THIS_KEY->mut->condition); +#endif THIS_KEY->mut=0; + THIS_KEY->owner=0; THIS_KEY->initialized=0; } +#ifndef SOLARIS mt_unlock(& mutex_kluge); +#endif } #define THIS_COND ((COND_T *)(fp->current_storage)) @@ -279,18 +328,23 @@ void f_cond_wait(INT32 args) if(key->prog != mutex_key) error("Bad argument 1 to condition->wait()\n"); - mt_lock(&mutex_kluge); mut=OB2KEY(key)->mut; THREADS_ALLOW(); - +#ifdef SOLARIS + mut->key=0; + sema_post( &mut->sema ); + /* Wait and allow mutex operations */ + co_wait(c,0); + while((sema_wait( &mut->sema )) && (errno==EAGAIN)); + mut->key=key; +#else + mt_lock(&mutex_kluge); /* Unlock mutex */ mut->key=0; OB2KEY(key)->mut=0; co_signal(& mut->condition); - /* Wait and allow mutex operations */ co_wait(c,&mutex_kluge); - if(OB2KEY(key)->initialized) { /* Lock mutex */ @@ -299,6 +353,7 @@ void f_cond_wait(INT32 args) OB2KEY(key)->mut=mut; } mt_unlock(&mutex_kluge); +#endif THREADS_DISALLOW(); pop_stack(); } else {