diff --git a/src/threads.c b/src/threads.c
index e26e8b5c931170dfb68be5bcebf32635be0d7e6e..dba3beb649fedd0cb1bfb801988adf9440cba8c1 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.27 1997/09/01 14:14:30 per Exp $");
+RCSID("$Id: threads.c,v 1.28 1997/09/02 22:18:07 grubba Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -42,15 +42,13 @@ static void check_threads(struct callback *cb, void *arg, void * arg2)
 
 void *new_thread_func(void * data)
 {
-/*  static int dbt;*/
   struct thread_starter arg = *(struct thread_starter *)data;
   JMP_BUF back;
   INT32 tmp;
 
-/*  fprintf(stderr, "Thread create[%d]...",dbt++);*/
   if((tmp=mt_lock( & interpreter_lock)))
     fatal("Failed to lock interpreter, errno %d\n",tmp);
-/*  fprintf(stderr,"Created[%d]...",dbt);*/
+  THREADS_FPRINTF((stderr,"THREADS_DISALLOW() Thread created...\n"));
   init_interpreter();
 
   thread_id=arg.id;
@@ -86,7 +84,7 @@ void *new_thread_func(void * data)
     remove_callback(threads_evaluator_callback);
     threads_evaluator_callback=0;
   }
-/*  fprintf(stderr,"Done[%d]\n",dbt--);*/
+  THREADS_FPRINTF((stderr,"THREADS_ALLOW() Thread done\n"));
   mt_unlock(& interpreter_lock);
   th_exit(0);
   /* NOT_REACHED, but removes a warning */
@@ -181,27 +179,35 @@ void f_mutex_lock(INT32 args)
 
   pop_n_elems(args);
   m=THIS_MUTEX;
+  /* Needs to be cloned here, since create()
+   * might use threads.
+   */
   o=clone_object(mutex_key,0);
   mt_lock(& mutex_kluge);
   if(m->key && OB2KEY(m->key)->owner == thread_id)
   {
-    m->key->refs++;
-    push_object(m->key);
-    mt_unlock(&mutex_kluge);
-    return;
-
+    THREADS_FPRINTF((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,
+		     (unsigned int) thread_id));
     mt_unlock(&mutex_kluge);
+    free_object(o);
     error("Recursive mutex locks!\n");
   }
 
   THREADS_ALLOW();
   while(m->key) co_wait(& m->condition, & mutex_kluge);
-  OB2KEY(o)->mut=m;
-  OB2KEY(o)->owner=thread_id;
   m->key=o;
+  OB2KEY(o)->mut=m;
   
   mt_unlock(&mutex_kluge);
   THREADS_DISALLOW();
+  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));
   push_object(o);
 }
 
@@ -217,21 +223,23 @@ void f_mutex_trylock(INT32 args)
 
   mt_lock(& mutex_kluge);
 
+  /* No reason to release the interpreter lock here
+   * since we aren't calling any functions that take time.
+   */
+
   if(m->key && OB2KEY(m->key)->owner == thread_id)
   {
     mt_unlock(&mutex_kluge);
+    free_object(o);
     error("Recursive mutex locks!\n");
   }
-  THREADS_ALLOW();
   if(!m->key)
   {
     OB2KEY(o)->mut=m;
-    OB2KEY(o)->owner=thread_id;
     m->key=o;
     i=1;
   }
   mt_unlock(&mutex_kluge);
-  THREADS_DISALLOW();
   
   if(i)
   {
@@ -258,13 +266,21 @@ 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));
   THIS_KEY->mut=0;
-  THIS_KEY->owner=0;
+  THIS_KEY->owner=thread_id;
+  thread_id->refs++;
   THIS_KEY->initialized=1;
 }
 
 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));
   mt_lock(& mutex_kluge);
   if(THIS_KEY->mut)
   {
@@ -273,7 +289,10 @@ void exit_mutex_key_obj(struct object *o)
       fatal("Mutex unlock from wrong key %p != %p!\n",THIS_KEY->mut->key,o);
 #endif
     THIS_KEY->mut->key=0;
-    THIS_KEY->owner=0;
+    if (THIS_KEY->owner) {
+      free_object(THIS_KEY->owner);
+      THIS_KEY->owner=0;
+    }
     co_signal(& THIS_KEY->mut->condition);
     THIS_KEY->mut=0;
     THIS_KEY->initialized=0;
@@ -342,6 +361,7 @@ void exit_cond_obj(struct object *o) { co_destroy(THIS_COND); }
 void th_init(void)
 {
   struct program *tmp;
+  INT32 mutex_key_offset;
 
 #ifdef SGI_SPROC_THREADS
 #error /* Need to specify a filename */
@@ -375,7 +395,12 @@ void th_init(void)
   end_class("mutex", 0);
 
   start_new_program();
-  add_storage(sizeof(struct key_storage));
+  mutex_key_offset = add_storage(sizeof(struct key_storage));
+  /* This is needed to allow the gc to find the possible circular reference.
+   * It also allows a process to take over ownership of a key.
+   */
+  map_variable("_owner", "object", 0,
+	       mutex_key_offset + OFFSETOF(key_storage, owner), T_OBJECT);
   set_init_callback(init_mutex_key_obj);
   set_exit_callback(exit_mutex_key_obj);
   mutex_key=end_program();