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 {