diff --git a/src/threads.c b/src/threads.c
index 54658718ddf981ddc784c936464a406c18ef14dc..7c879223ec2923038a750d72e46156e7029576e7 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.29 1997/09/03 03:39:58 per Exp $");
+RCSID("$Id: threads.c,v 1.30 1997/09/03 04:58:17 per Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -18,7 +18,7 @@ int threads_disabled = 0;
 struct object *thread_id;
 static struct callback *threads_evaluator_callback=0;
 
-MUTEX_T interpreter_lock = PTHREAD_MUTEX_INITIALIZER;
+MUTEX_T interpreter_lock /*= PTHREAD_MUTEX_INITIALIZER*/;
 struct program *mutex_key = 0;
 struct program *thread_id_prog = 0;
 #ifdef POSIX_THREADS
@@ -50,8 +50,9 @@ void *new_thread_func(void * data)
     fatal("Failed to lock interpreter, errno %d\n",tmp);
   THREADS_FPRINTF((stderr,"THREADS_DISALLOW() Thread created...\n"));
   init_interpreter();
-
   thread_id=arg.id;
+  SWAP_OUT_THREAD((struct thread_state *)thread_id->storage); /* Init struct */
+  ((struct thread_state *)thread_id->storage)->swapped=0;
 
   if(SETJMP(back))
   {
@@ -168,7 +169,7 @@ struct key_storage
   int initialized;
 };
 
-static MUTEX_T mutex_kluge = PTHREAD_MUTEX_INITIALIZER;
+static MUTEX_T mutex_kluge/* = PTHREAD_MUTEX_INITIALIZER*/;
 
 #define OB2KEY(X) ((struct key_storage *)((X)->storage))
 
@@ -361,6 +362,34 @@ void f_cond_broadcast(INT32 args) { pop_n_elems(args); co_broadcast(THIS_COND);
 void init_cond_obj(struct object *o) { co_init(THIS_COND); }
 void exit_cond_obj(struct object *o) { co_destroy(THIS_COND); }
 
+void f_thread_backtrace(INT32 args)
+{
+  struct thread_state *foo = (struct thread_state *)fp->current_object->storage;
+  struct thread_state *bar = (struct thread_state *)thread_id->storage;
+  struct svalue *osp = sp;
+  pop_n_elems(args);
+  if(foo->sp)
+  {
+    SWAP_OUT_THREAD(bar);
+    SWAP_IN_THREAD(foo);
+    sp=osp;
+    f_backtrace(0);
+    osp=sp;
+    sp=foo->sp;
+    SWAP_OUT_THREAD(foo);
+    SWAP_IN_THREAD(bar);
+    sp=osp;
+  } else {
+    push_int(0);
+    f_allocate(1);
+  }
+}
+
+void init_thread_obj(struct object *o)
+{
+  MEMSET(o->storage, 0, sizeof(struct thread_state));
+}
+
 void th_init(void)
 {
   struct program *tmp;
@@ -420,6 +449,9 @@ void th_init(void)
   end_class("condition", 0);
 
   start_new_program();
+  add_storage(sizeof(struct thread_state));
+  add_function("backtrace",f_thread_backtrace,"function(:array)",0);
+  set_init_callback(init_thread_obj);
   thread_id_prog=end_program();
   if(!mutex_key)
     fatal("Failed to initialize thread program!\n");
diff --git a/src/threads.h b/src/threads.h
index d97cb2f34a351b8a39ba485b37c072be1b67193a..17368d5ed8e3dfff06d6e734441e483759cdbc62 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -3,6 +3,7 @@
 
 #include "machine.h"
 #include "interpret.h"
+#include "object.h"
 #include "error.h"
 #ifdef HAVE_SYS_TYPES_H
 /* Needed for pthread_t on OSF/1 */
@@ -176,41 +177,50 @@ struct thread_state {
 #define THREADS_FPRINTF(X)	fprintf X
 #endif /* VERBOSE_THREADS_DEBUG */
 
+#define SWAP_OUT_THREAD(_tmp) do { \
+       (_tmp)->swapped=1; \
+\
+       (_tmp)->evaluator_stack=evaluator_stack;\
+       (_tmp)->evaluator_stack_malloced=evaluator_stack_malloced;\
+       (_tmp)->fp=fp;\
+       (_tmp)->mark_sp=mark_sp;\
+       (_tmp)->mark_stack=mark_stack;\
+       (_tmp)->mark_stack_malloced=mark_stack_malloced;\
+       (_tmp)->recoveries=recoveries;\
+       (_tmp)->sp=sp; \
+       (_tmp)->thread_id=thread_id;\
+      } while(0)
+
+#define SWAP_IN_THREAD(_tmp) do {\
+       (_tmp)->swapped=0; \
+\
+       evaluator_stack=(_tmp)->evaluator_stack;\
+       evaluator_stack_malloced=(_tmp)->evaluator_stack_malloced;\
+       fp=(_tmp)->fp;\
+       mark_sp=(_tmp)->mark_sp;\
+       mark_stack=(_tmp)->mark_stack;\
+       mark_stack_malloced=(_tmp)->mark_stack_malloced;\
+       recoveries=(_tmp)->recoveries;\
+       sp=(_tmp)->sp;\
+       thread_id=(_tmp)->thread_id;\
+     } while(0)
+
 #define THREADS_ALLOW() \
   do {\
-     struct thread_state _tmp; \
-     _tmp.swapped=0; \
+     struct thread_state *_tmp=(struct thread_state *)thread_id->storage; \
      if(num_threads > 1 && !threads_disabled) { \
-       _tmp.swapped=1; \
-       _tmp.sp=sp; \
-       _tmp.evaluator_stack=evaluator_stack; \
-       _tmp.mark_sp=mark_sp; \
-       _tmp.mark_stack=mark_stack; \
-       _tmp.fp=fp; \
-       _tmp.recoveries=recoveries; \
-       _tmp.evaluator_stack_malloced=evaluator_stack_malloced; \
-       _tmp.mark_stack_malloced=mark_stack_malloced; \
-       _tmp.thread_id = thread_id; \
+       SWAP_OUT_THREAD(_tmp); \
        THREADS_FPRINTF((stderr, "THREADS_ALLOW() %s:%d t:%08x\n", \
-			__FILE__, __LINE__, (unsigned int)_tmp.thread_id)); \
+			__FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \
        mt_unlock(& interpreter_lock); \
-       /*th_yield();*/\
      }
 
 #define THREADS_DISALLOW() \
-     if(_tmp.swapped) { \
+     if(_tmp->swapped) { \
        mt_lock(& interpreter_lock); \
        THREADS_FPRINTF((stderr, "THREADS_DISALLOW() %s:%d ... t:%08x\n", \
-			__FILE__, __LINE__, (unsigned int)_tmp.thread_id)); \
-       sp=_tmp.sp; \
-       evaluator_stack=_tmp.evaluator_stack; \
-       mark_sp=_tmp.mark_sp; \
-       mark_stack=_tmp.mark_stack; \
-       fp=_tmp.fp; \
-       recoveries=_tmp.recoveries; \
-       evaluator_stack_malloced=_tmp.evaluator_stack_malloced; \
-       mark_stack_malloced=_tmp.mark_stack_malloced; \
-       thread_id = _tmp.thread_id; \
+			__FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \
+       SWAP_IN_THREAD(_tmp);\
      } \
    } while(0)