From a91ca08061772d46b266776f56201c5f1fc58885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Fri, 10 Jul 1998 17:52:10 +0200 Subject: [PATCH] Added support for interleaved mutexes. Rev: src/main.c:1.55 Rev: src/modules/system/passwords.c:1.17 Rev: src/program.c:1.96 Rev: src/threads.c:1.75 Rev: src/threads.h:1.45 --- src/main.c | 4 +- src/modules/system/passwords.c | 108 +++++++++++------- src/program.c | 15 +-- src/threads.c | 199 ++++++++++++++++++++++++--------- src/threads.h | 91 +++++++++++---- 5 files changed, 294 insertions(+), 123 deletions(-) diff --git a/src/main.c b/src/main.c index 9e7563d17a..0f30eee002 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: main.c,v 1.54 1998/05/25 19:34:11 grubba Exp $"); +RCSID("$Id: main.c,v 1.55 1998/07/10 15:52:03 grubba Exp $"); #include "fdlib.h" #include "backend.h" #include "module.h" @@ -321,6 +321,8 @@ int dbm_main(int argc, char **argv) init_cpp(); init_lex(); + low_th_init(); + init_modules(); master(); call_callback(& post_master_callbacks, 0); diff --git a/src/modules/system/passwords.c b/src/modules/system/passwords.c index 6236624975..7a9d64e5c2 100644 --- a/src/modules/system/passwords.c +++ b/src/modules/system/passwords.c @@ -1,5 +1,5 @@ /* - * $Id: passwords.c,v 1.16 1998/07/09 21:03:22 grubba Exp $ + * $Id: passwords.c,v 1.17 1998/07/10 15:52:10 grubba Exp $ * * Password handling for Pike. * @@ -22,7 +22,7 @@ #include "system_machine.h" #include "system.h" -RCSID("$Id: passwords.c,v 1.16 1998/07/09 21:03:22 grubba Exp $"); +RCSID("$Id: passwords.c,v 1.17 1998/07/10 15:52:10 grubba Exp $"); #include "module_support.h" #include "interpret.h" @@ -53,7 +53,7 @@ RCSID("$Id: passwords.c,v 1.16 1998/07/09 21:03:22 grubba Exp $"); * Emulation */ -DEFINE_MUTEX(password_protection_mutex); +DEFINE_IMUTEX(password_protection_mutex); #ifdef HAVE_GETPWENT #ifndef HAVE_GETPWNAM @@ -120,9 +120,9 @@ void push_pwent(struct passwd *ent) if(!strcmp(ent->pw_passwd, "x")) { struct spwd *foo; - THREADS_ALLOW_UID(); + THREADS_ALLOW(); foo = getspnam(ent->pw_name); - THREADS_DISALLOW_UID(); + THREADS_DISALLOW(); if(foo) push_text(foo->sp_pwdp); else @@ -171,13 +171,16 @@ void f_getgrgid(INT32 args) int gid; struct group *foo; get_all_args("getgrgid", args, "%d", &gid); + + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); foo = getgrgid( gid ); THREADS_DISALLOW_UID(); pop_n_elems( args ); push_grent( foo ); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); } #endif /* HAVE_GETGRGID */ @@ -188,13 +191,16 @@ void f_getgrnam(INT32 args) char *str; struct group *foo; get_all_args("getgrnam", args, "%s", &str); + + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); foo = getgrnam( str ); THREADS_DISALLOW_UID(); pop_n_elems( args ); push_grent( foo ); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); } #endif /* HAVE_GETGRNAM */ @@ -207,14 +213,16 @@ void f_getpwnam(INT32 args) get_all_args("getpwnam", args, "%s", &str); + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); foo = getpwnam(str); THREADS_DISALLOW_UID(); pop_n_elems(args); push_pwent(foo); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); } #endif /* HAVE_GETPWNAM */ @@ -227,14 +235,16 @@ void f_getpwuid(INT32 args) get_all_args("getpwuid", args, "%i", &uid); + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); foo = getpwuid(uid); THREADS_DISALLOW_UID(); pop_n_elems(args); push_pwent(foo); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); } #endif /* HAVE_GETPWUID */ @@ -242,13 +252,15 @@ void f_getpwuid(INT32 args) /* int setpwent() */ void f_setpwent(INT32 args) { + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); setpwent(); - mt_unlock(&password_protection_mutex); THREADS_DISALLOW_UID(); pop_n_elems(args); push_int(0); + + UNLOCK_IMUTEX(&password_protection_mutex); } #endif /* HAVE_SETPWENT */ @@ -256,13 +268,15 @@ void f_setpwent(INT32 args) /* int endpwent() */ void f_endpwent(INT32 args) { + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); endpwent(); - mt_unlock(&password_protection_mutex); THREADS_DISALLOW_UID(); pop_n_elems(args); push_int(0); + + UNLOCK_IMUTEX(&password_protection_mutex); } #endif /* HAVE_ENDPWENT */ @@ -272,8 +286,10 @@ void f_getpwent(INT32 args) { struct passwd *foo; pop_n_elems(args); + + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); foo = getpwent(); THREADS_DISALLOW_UID(); if(!foo) @@ -283,7 +299,8 @@ void f_getpwent(INT32 args) return; } push_pwent(foo); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); } void f_get_all_users(INT32 args) @@ -293,12 +310,7 @@ void f_get_all_users(INT32 args) pop_n_elems(args); a = low_allocate_array(0, 10); - /* NOTE: We need THREADS_ALLOW_UID()/THREADS_DISALLOW_UID() here - * to avoid deadlocks. - */ - THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); - THREADS_DISALLOW_UID(); + LOCK_IMUTEX(&password_protection_mutex); setpwent(); while(1) @@ -318,7 +330,7 @@ void f_get_all_users(INT32 args) } endpwent(); - mt_unlock(&password_protection_mutex); + UNLOCK_IMUTEX(&password_protection_mutex); push_array(a); } @@ -329,11 +341,14 @@ void f_get_all_users(INT32 args) /* int setgrent() */ void f_setgrent(INT32 args) { + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); setgrent(); - mt_unlock(&password_protection_mutex); THREADS_DISALLOW_UID(); + + UNLOCK_IMUTEX(&password_protection_mutex); + pop_n_elems(args); push_int(0); } @@ -343,11 +358,14 @@ void f_setgrent(INT32 args) /* int endgrent() */ void f_endgrent(INT32 args) { + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); endgrent(); - mt_unlock(&password_protection_mutex); THREADS_DISALLOW_UID(); + + UNLOCK_IMUTEX(&password_protection_mutex); + pop_n_elems(args); push_int(0); } @@ -359,8 +377,10 @@ void f_getgrent(INT32 args) { struct group *foo; pop_n_elems(args); + + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); foo = getgrent(); THREADS_DISALLOW_UID(); if(!foo) @@ -369,7 +389,8 @@ void f_getgrent(INT32 args) return; } push_grent(foo); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); } void f_get_all_groups(INT32 args) @@ -380,12 +401,7 @@ void f_get_all_groups(INT32 args) a = low_allocate_array(0, 10); - /* NOTE: We need THREADS_ALLOW_UID()/THREADS_DISALLOW_UID() here - * to avoid deadlocks. - */ - THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); - THREADS_DISALLOW_UID(); + LOCK_IMUTEX(&password_protection_mutex); setgrent(); while(1) @@ -404,7 +420,7 @@ void f_get_all_groups(INT32 args) } endgrent(); - mt_unlock(&password_protection_mutex); + UNLOCK_IMUTEX(&password_protection_mutex); push_array(a); } @@ -425,8 +441,10 @@ void f_get_groups_for_user(INT32 arg) if(sp[-1].type == T_INT) { int uid=sp[-1].u.integer; + + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); pw=getpwuid(uid); THREADS_DISALLOW_UID(); @@ -435,8 +453,10 @@ void f_get_groups_for_user(INT32 arg) user=sp[-1].u.string->str; }else{ user=sp[-1].u.string->str; + + LOCK_IMUTEX(&password_protection_mutex); + THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); pw=getpwnam(user); THREADS_DISALLOW_UID(); } @@ -479,7 +499,9 @@ void f_get_groups_for_user(INT32 arg) pop_stack(); } endgrent(); - mt_unlock(&password_protection_mutex); + + UNLOCK_IMUTEX(&password_protection_mutex); + pop_stack(); push_array(a); } @@ -488,6 +510,8 @@ void f_get_groups_for_user(INT32 arg) void init_passwd(void) { + init_interleave_mutex(&password_protection_mutex); + /* * From passwords.c */ diff --git a/src/program.c b/src/program.c index fd07cf4eed..8f37cedc69 100644 --- a/src/program.c +++ b/src/program.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: program.c,v 1.95 1998/06/24 04:56:46 hubbe Exp $"); +RCSID("$Id: program.c,v 1.96 1998/07/10 15:52:04 grubba Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -507,7 +507,8 @@ void low_start_new_program(struct program *p, { int e,id=0; - threads_disabled++; + init_threads_disable(NULL); + compilation_depth++; /* fprintf(stderr, "low_start_new_program(): compilation_depth:%d\n", compilation_depth); */ @@ -945,8 +946,8 @@ struct program *end_first_pass(int finish) compilation_depth--; - if(!--threads_disabled) - co_broadcast(&threads_disabled_change); + + exit_threads_disable(NULL); /* fprintf(stderr, "end_first_pass(): compilation_depth:%d\n", compilation_depth); */ @@ -2307,10 +2308,10 @@ struct program *compile(struct pike_string *prog) threads_disabled, saved_threads_disabled); } #endif /* DEBUG */ - threads_disabled = saved_threads_disabled; + threads_disabled = saved_threads_disabled + 1; /* fprintf(stderr, "compile() Leave: threads_disabled:%d, compilation_depth:%d\n", threads_disabled, compilation_depth); */ - if(!threads_disabled) - co_broadcast(&threads_disabled_change); + + exit_threads_disable(NULL); free_string(lex.current_file); lex=save_lex; diff --git a/src/threads.c b/src/threads.c index c1f3db6f7d..9bbe58862c 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.74 1998/07/09 21:50:37 grubba Exp $"); +RCSID("$Id: threads.c,v 1.75 1998/07/10 15:52:06 grubba Exp $"); int num_threads = 1; int threads_disabled = 0; @@ -142,7 +142,7 @@ struct object *thread_id; static struct callback *threads_evaluator_callback=0; int thread_id_result_variable; -MUTEX_T interpreter_lock, thread_table_lock; +MUTEX_T interpreter_lock, thread_table_lock, interleave_lock; struct program *mutex_key = 0; struct program *thread_id_prog = 0; #ifdef POSIX_THREADS @@ -156,13 +156,86 @@ struct thread_starter struct array *args; }; +static volatile IMUTEX_T *interleave_list = NULL; + +void init_threads_disable(struct object *o) +{ + /* Serious black magic to avoid dead-locks */ + + if (!threads_disabled) { + THREADS_FPRINTF(0, (stderr, "init_threads_disable(): Locking IM's...\n")); + + if (thread_id) { + IMUTEX_T *im; + + THREADS_ALLOW(); + + /* Keep this the entire session. */ + mt_lock(&interleave_lock); + + im = (IMUTEX_T *)interleave_list; + + while(im) { + mt_lock(&(im->lock)); + + im = im->next; + } + + THREADS_DISALLOW(); + } else { + IMUTEX_T *im; + + /* Keep this the entire session. */ + mt_lock(&interleave_lock); + + im = (IMUTEX_T *)interleave_list; + + while(im) { + mt_lock(&(im->lock)); + + im = im->next; + } + } + + THREADS_FPRINTF(0, + (stderr, "init_threads_disable(): Disabling threads.\n")); + + threads_disabled = 1; + } else { + threads_disabled++; + } + + THREADS_FPRINTF(0, (stderr, "init_threads_disable(): threads_disabled:%d\n", + threads_disabled)); + while (live_threads) { + THREADS_FPRINTF(0, + (stderr, + "_disable_threads(): Waiting for %d threads to finish\n", + live_threads)); + co_wait(&live_threads_change, &interpreter_lock); + } +} + void exit_threads_disable(struct object *o) { - THREADS_FPRINTF((stderr, "exit_threads_disable(): threads_disabled:%d\n", - threads_disabled)); + THREADS_FPRINTF(0, (stderr, "exit_threads_disable(): threads_disabled:%d\n", + threads_disabled)); if(threads_disabled) { if(!--threads_disabled) { - THREADS_FPRINTF((stderr, "_exit_threads_disable(): Wake up!\n")); + IMUTEX_T *im = (IMUTEX_T *)interleave_list; + + /* Order shouldn't matter for unlock, so no need to do it backwards. */ + while(im) { + THREADS_FPRINTF(0, + (stderr, + "exit_threads_disable(): Unlocking IM 0x%08p\n", im)); + mt_unlock(&(im->lock)); + im = im->next; + } + + mt_unlock(&interleave_lock); + + THREADS_FPRINTF(0, (stderr, "_exit_threads_disable(): Wake up!\n")); co_broadcast(&threads_disabled_change); } #ifdef DEBUG @@ -172,32 +245,51 @@ void exit_threads_disable(struct object *o) } } -void init_threads_disable(struct object *o) +void init_interleave_mutex(IMUTEX_T *im) { - /* Serious black magic to avoid dead-locks */ + mt_init(&(im->lock)); - if (!threads_disabled) { - extern MUTEX_T password_protection_mutex; + THREADS_FPRINTF(0, (stderr, + "init_interleave_mutex(): init_threads_disable()\n")); - THREADS_ALLOW_UID(); - mt_lock(&password_protection_mutex); - THREADS_DISALLOW_UID(); + init_threads_disable(NULL); - threads_disabled = 1; + THREADS_FPRINTF(0, (stderr, + "init_interleave_mutex(): Locking IM 0x%08p\n", im)); - mt_unlock(&password_protection_mutex); - } else { - threads_disabled++; + /* Lock it so that it can be unlocked by exit_threads_disable() */ + mt_lock(&(im->lock)); + + im->next = (IMUTEX_T *)interleave_list; + if (interleave_list) { + interleave_list->prev = im; } + interleave_list = im; + im->prev = NULL; - THREADS_FPRINTF((stderr, "init_threads_disable(): threads_disabled:%d\n", - threads_disabled)); - while (live_threads) { - THREADS_FPRINTF((stderr, - "_disable_threads(): Waiting for %d threads to finish\n", - live_threads)); - co_wait(&live_threads_change, &interpreter_lock); + THREADS_FPRINTF(0, (stderr, + "init_interleave_mutex(): exit_threads_disable()\n")); + + exit_threads_disable(NULL); +} + +void exit_interleave_mutex(IMUTEX_T *im) +{ + init_threads_disable(NULL); + + if (im->prev) { + im->prev->next = im->next; + } else { + interleave_list = im->next; + } + if (im->next) { + im->next->prev = im->prev; } + + /* Just to be nice... */ + mt_unlock(&(im->lock)); + + exit_threads_disable(NULL); } /* Thread hashtable */ @@ -329,8 +421,8 @@ void *new_thread_func(void * data) JMP_BUF back; INT32 tmp; - THREADS_FPRINTF((stderr,"THREADS_DISALLOW() Thread %08x created...\n", - (unsigned int)arg.id)); + THREADS_FPRINTF(0, (stderr,"THREADS_DISALLOW() Thread %08x created...\n", + (unsigned int)arg.id)); if((tmp=mt_lock( & interpreter_lock))) fatal("Failed to lock interpreter, errno %d\n",tmp); @@ -344,7 +436,7 @@ void *new_thread_func(void * data) } #endif /* THREAD_TRACE */ - THREADS_FPRINTF((stderr,"THREAD %08x INITED\n",(unsigned int)thread_id)); + THREADS_FPRINTF(0, (stderr,"THREAD %08x INITED\n",(unsigned int)thread_id)); if(SETJMP(back)) { if(throw_severity < THROW_EXIT) @@ -380,8 +472,8 @@ void *new_thread_func(void * data) free((char *)data); /* Moved by per, to avoid some bugs.... */ UNSETJMP(back); - THREADS_FPRINTF((stderr,"THREADS_ALLOW() Thread %08x done\n", - (unsigned int)thread_id)); + THREADS_FPRINTF(0, (stderr,"THREADS_ALLOW() Thread %08x done\n", + (unsigned int)thread_id)); thread_table_delete(thread_id); free_object(thread_id); @@ -428,7 +520,8 @@ void f_thread_create(INT32 args) check_threads, 0,0); } ref_push_object(arg->id); - THREADS_FPRINTF((stderr,"THREAD_CREATE -> t:%08x\n",(unsigned int)arg->id)); + THREADS_FPRINTF(0, (stderr, "THREAD_CREATE -> t:%08x\n", + (unsigned int)arg->id)); } else { free_object(arg->id); free_array(arg->args); @@ -493,7 +586,8 @@ void f_mutex_lock(INT32 args) { if(m->key && OB2KEY(m->key)->owner == thread_id) { - THREADS_FPRINTF((stderr, "Recursive LOCK k:%08x, m:%08x(%08x), t:%08x\n", + THREADS_FPRINTF(0, + (stderr, "Recursive LOCK k:%08x, m:%08x(%08x), t:%08x\n", (unsigned int)OB2KEY(m->key), (unsigned int)m, (unsigned int)OB2KEY(m->key)->mut, @@ -508,7 +602,7 @@ void f_mutex_lock(INT32 args) SWAP_OUT_CURRENT_THREAD(); do { - THREADS_FPRINTF((stderr,"WAITING TO LOCK m:%08x\n",(unsigned int)m)); + THREADS_FPRINTF(1, (stderr,"WAITING TO LOCK m:%08x\n",(unsigned int)m)); co_wait(& m->condition, & interpreter_lock); }while(m->key); SWAP_IN_CURRENT_THREAD(); @@ -516,11 +610,11 @@ void f_mutex_lock(INT32 args) m->key=o; OB2KEY(o)->mut=m; - THREADS_FPRINTF((stderr, "LOCK k:%08x, m:%08x(%08x), t:%08x\n", - (unsigned int)OB2KEY(o), - (unsigned int)m, - (unsigned int)OB2KEY(m->key)->mut, - (unsigned int)thread_id)); + THREADS_FPRINTF(1, (stderr, "LOCK k:%08x, m:%08x(%08x), t:%08x\n", + (unsigned int)OB2KEY(o), + (unsigned int)m, + (unsigned int)OB2KEY(m->key)->mut, + (unsigned int)thread_id)); pop_n_elems(args); push_object(o); } @@ -573,7 +667,8 @@ void init_mutex_obj(struct object *o) void exit_mutex_obj(struct object *o) { - THREADS_FPRINTF((stderr,"DESTROYING MUTEX m:%08x\n",(unsigned int)THIS_MUTEX)); + THREADS_FPRINTF(1, (stderr, "DESTROYING MUTEX m:%08x\n", + (unsigned int)THIS_MUTEX)); if(THIS_MUTEX->key) destruct(THIS_MUTEX->key); THIS_MUTEX->key=0; co_destroy(& THIS_MUTEX->condition); @@ -582,8 +677,8 @@ void exit_mutex_obj(struct object *o) #define THIS_KEY ((struct key_storage *)(fp->current_storage)) void init_mutex_key_obj(struct object *o) { - THREADS_FPRINTF((stderr, "KEY k:%08x, o:%08x\n", - (unsigned int)THIS_KEY, (unsigned int)thread_id)); + THREADS_FPRINTF(1, (stderr, "KEY k:%08x, o:%08x\n", + (unsigned int)THIS_KEY, (unsigned int)thread_id)); THIS_KEY->mut=0; add_ref(THIS_KEY->owner=thread_id); THIS_KEY->initialized=1; @@ -591,11 +686,11 @@ void init_mutex_key_obj(struct object *o) void exit_mutex_key_obj(struct object *o) { - THREADS_FPRINTF((stderr, "UNLOCK k:%08x m:(%08x) t:%08x o:%08x\n", - (unsigned int)THIS_KEY, - (unsigned int)THIS_KEY->mut, - (unsigned int)thread_id, - (unsigned int)THIS_KEY->owner)); + THREADS_FPRINTF(1, (stderr, "UNLOCK k:%08x m:(%08x) t:%08x o:%08x\n", + (unsigned int)THIS_KEY, + (unsigned int)THIS_KEY->mut, + (unsigned int)thread_id, + (unsigned int)THIS_KEY->owner)); if(THIS_KEY->mut) { struct mutex_storage *mut = THIS_KEY->mut; @@ -741,17 +836,14 @@ static void thread_was_marked(struct object *o) } #endif -void th_init(void) +void low_th_init(void) { - struct program *tmp; - INT32 mutex_key_offset; - #ifdef SGI_SPROC_THREADS #error /* Need to specify a filename */ us_cookie = usinit(""); #endif /* SGI_SPROC_THREADS */ - THREADS_FPRINTF((stderr, "THREADS_DISALLOW() Initializing threads.\n")); + THREADS_FPRINTF(0, (stderr, "THREADS_DISALLOW() Initializing threads.\n")); #ifdef POSIX_THREADS #ifdef HAVE_PTHREAD_INIT @@ -762,6 +854,7 @@ void th_init(void) mt_init( & interpreter_lock); mt_lock( & interpreter_lock); mt_init( & thread_table_lock); + mt_init( & interleave_lock); co_init( & live_threads_change); co_init( & threads_disabled_change); thread_table_init(); @@ -779,7 +872,13 @@ void th_init(void) pthread_attr_setdetachstate(&small_pattr, PTHREAD_CREATE_DETACHED); #endif - +} + +void th_init(void) +{ + struct program *tmp; + INT32 mutex_key_offset; + add_efun("thread_create",f_thread_create,"function(mixed ...:object)", OPT_SIDE_EFFECT); #ifdef UNIX_THREADS diff --git a/src/threads.h b/src/threads.h index 982adb1397..d5ed226e3f 100644 --- a/src/threads.h +++ b/src/threads.h @@ -1,5 +1,5 @@ /* - * $Id: threads.h,v 1.44 1998/07/05 13:48:58 grubba Exp $ + * $Id: threads.h,v 1.45 1998/07/10 15:52:08 grubba Exp $ */ #ifndef THREADS_H #define THREADS_H @@ -231,6 +231,37 @@ extern COND_T threads_disabled_change; /* Used by _disable_threads */ struct svalue; struct frame; +extern MUTEX_T interleave_lock; + +struct interleave_mutex +{ + struct interleave_mutex *next; + struct interleave_mutex *prev; + MUTEX_T lock; +}; + +#define IMUTEX_T struct interleave_mutex + +#define DEFINE_IMUTEX(name) IMUTEX_T name + +/* If threads are disabled, we already hold the lock. */ +#define LOCK_IMUTEX(im) do { \ + if (!threads_disabled) { \ + THREADS_FPRINTF(0, (stderr, "Locking IMutex 0x%08p...\n", (im))); \ + THREADS_ALLOW(); \ + mt_lock(&((im)->lock)); \ + THREADS_DISALLOW(); \ + } \ + } while(0) + +/* If threads are disabled, the lock will be released later. */ +#define UNLOCK_IMUTEX(im) do { \ + if (!threads_disabled) { \ + THREADS_FPRINTF(0, (stderr, "Unlocking IMutex 0x%08p...\n", (im))); \ + mt_unlock(&((im)->lock)); \ + } \ + } while(0) + #define THREAD_NOT_STARTED -1 #define THREAD_RUNNING 0 #define THREAD_EXITED 1 @@ -272,12 +303,15 @@ struct thread_state { #endif /* Define to get a debug-trace of some of the threads operations. */ -/* #define VERBOSE_THREADS_DEBUG */ +/* #define VERBOSE_THREADS_DEBUG 0 */ /* Some debug */ +/* #define VERBOSE_THREADS_DEBUG 1 */ /* Lots of debug */ #ifndef VERBOSE_THREADS_DEBUG -#define THREADS_FPRINTF(X) +#define THREADS_FPRINTF(L,X) #else -#define THREADS_FPRINTF(X) fprintf X +#define THREADS_FPRINTF(L,X) do { \ + if ((VERBOSE_THREADS_DEBUG + 0) >= (L)) fprintf X; \ + } while(0) #endif /* VERBOSE_THREADS_DEBUG */ #ifdef THREAD_TRACE @@ -320,12 +354,12 @@ struct thread_state { do {\ struct thread_state *_tmp=(struct thread_state *)thread_id->storage; \ SWAP_OUT_THREAD(_tmp); \ - THREADS_FPRINTF((stderr, "SWAP_OUT_CURRENT_THREAD() %s:%d t:%08x\n", \ - __FILE__, __LINE__, (unsigned int)_tmp->thread_id)) \ + THREADS_FPRINTF(1, (stderr, "SWAP_OUT_CURRENT_THREAD() %s:%d t:%08x\n", \ + __FILE__, __LINE__, (unsigned int)_tmp->thread_id)) \ #define SWAP_IN_CURRENT_THREAD() \ - THREADS_FPRINTF((stderr, "SWAP_IN_CURRENT_THREAD() %s:%d ... t:%08x\n", \ - __FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \ + THREADS_FPRINTF(1, (stderr, "SWAP_IN_CURRENT_THREAD() %s:%d ... t:%08x\n", \ + __FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \ SWAP_IN_THREAD(_tmp);\ } while(0) @@ -341,7 +375,7 @@ struct thread_state { int recoveries = 0, thread_id = 0; \ int error = 0, xalloc = 0, low_my_putchar = 0, low_my_binary_strcat = 0; \ int low_make_buf_space = 0, pop_n_elems = 0; \ - int push_sp_mark = 0, pop_sp_mark = 0 + int push_sp_mark = 0, pop_sp_mark = 0, threads_disabled = 1 /* Note that the semi-colon below is needed to add an empty statement * in case there is a label before the macro. @@ -357,9 +391,9 @@ struct thread_state { struct thread_state *_tmp=(struct thread_state *)thread_id->storage; \ if(num_threads > 1 && !threads_disabled) { \ SWAP_OUT_THREAD(_tmp); \ - THREADS_FPRINTF((stderr, "THREADS_ALLOW() %s:%d t:%08x(#%d)\n", \ - __FILE__, __LINE__, \ - (unsigned int)_tmp->thread_id, live_threads)); \ + THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW() %s:%d t:%08x(#%d)\n", \ + __FILE__, __LINE__, \ + (unsigned int)_tmp->thread_id, live_threads)); \ mt_unlock(& interpreter_lock); \ } else {} \ HIDE_GLOBAL_VARIABLES() @@ -368,11 +402,12 @@ struct thread_state { REVEAL_GLOBAL_VARIABLES(); \ if(_tmp->swapped) { \ mt_lock(& interpreter_lock); \ - THREADS_FPRINTF((stderr, "THREADS_DISALLOW() %s:%d t:%08x(#%d)\n", \ - __FILE__, __LINE__, \ - (unsigned int)_tmp->thread_id, live_threads)); \ + THREADS_FPRINTF(1, (stderr, "THREADS_DISALLOW() %s:%d t:%08x(#%d)\n", \ + __FILE__, __LINE__, \ + (unsigned int)_tmp->thread_id, live_threads)); \ while (threads_disabled) { \ - THREADS_FPRINTF((stderr, "THREADS_DISALLOW(): Threads disabled\n")); \ + THREADS_FPRINTF(1, (stderr, \ + "THREADS_DISALLOW(): Threads disabled\n")); \ co_wait(&threads_disabled_change, &interpreter_lock); \ } \ SWAP_IN_THREAD(_tmp);\ @@ -384,9 +419,9 @@ struct thread_state { if(num_threads > 1 && !threads_disabled) { \ SWAP_OUT_THREAD(_tmp_uid); \ live_threads++; \ - THREADS_FPRINTF((stderr, "THREADS_ALLOW_UID() %s:%d t:%08x(#%d)\n", \ - __FILE__, __LINE__, \ - (unsigned int)_tmp_uid->thread_id, live_threads)); \ + THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW_UID() %s:%d t:%08x(#%d)\n", \ + __FILE__, __LINE__, \ + (unsigned int)_tmp_uid->thread_id, live_threads)); \ mt_unlock(& interpreter_lock); \ } else {} \ HIDE_GLOBAL_VARIABLES() @@ -396,12 +431,13 @@ struct thread_state { if(_tmp_uid->swapped) { \ mt_lock(& interpreter_lock); \ live_threads--; \ - THREADS_FPRINTF((stderr, "THREADS_DISALLOW_UID() %s:%d t:%08x(#%d)\n", \ - __FILE__, __LINE__, \ - (unsigned int)_tmp_uid->thread_id, live_threads)); \ + THREADS_FPRINTF(1, (stderr, \ + "THREADS_DISALLOW_UID() %s:%d t:%08x(#%d)\n", \ + __FILE__, __LINE__, \ + (unsigned int)_tmp_uid->thread_id, live_threads)); \ co_broadcast(&live_threads_change); \ while (threads_disabled) { \ - THREADS_FPRINTF((stderr, "THREADS_DISALLOW_UID(): Wait...\n")); \ + THREADS_FPRINTF(1, (stderr, "THREADS_DISALLOW_UID(): Wait...\n")); \ co_wait(&threads_disabled_change, &interpreter_lock); \ } \ SWAP_IN_THREAD(_tmp_uid);\ @@ -433,6 +469,7 @@ void init_thread_obj(struct object *o); void exit_thread_obj(struct object *o); void th_farm(void (*fun)(void *), void *); void th_init(void); +void low_th_init(void); void th_cleanup(void); void thread_table_insert(struct object *o); void thread_table_delete(struct object *o); @@ -443,11 +480,18 @@ void f_all_threads(INT32 args); void init_threads_disable(struct object *o); void exit_threads_disable(struct object *o); +void init_interleave_mutex(IMUTEX_T *im); +void exit_interleave_mutex(IMUTEX_T *im); + /* Prototypes end here */ #else #define th_setconcurrency(X) #define DEFINE_MUTEX(X) +#define DEFINE_IMUTEX(X) +#define init_interleave_mutex(X) +#define LOCK_IMUTEX(X) +#define UNLOCK_IMUTEX(X) #define mt_init(X) #define mt_lock(X) #define mt_unlock(X) @@ -459,6 +503,7 @@ void exit_threads_disable(struct object *o); #define HIDE_GLOBAL_VARIABLES() #define REVEAL_GLOBAL_VARIABLES() #define th_init() +#define low_th_init() #define th_cleanup() #define th_init_programs() #define th_self() ((void*)0) -- GitLab