diff --git a/doc/builtin/this_thread b/doc/builtin/this_thread
new file mode 100644
index 0000000000000000000000000000000000000000..f898ec49eef31cab5a258da3ff992f85e2cc85f8
--- /dev/null
+++ b/doc/builtin/this_thread
@@ -0,0 +1,11 @@
+NAME
+	this_thread - return thread id
+
+SYNTAX
+	object thread_id();
+
+DESCRIPTION
+	This function returns the object that identifies this thread.
+
+SEE ALSO
+	thread_create
diff --git a/doc/builtin/thread_create b/doc/builtin/thread_create
index 4431df6271c46c6d7272ace1f40d38722b40c959..5d384b262586aedef8af3a01b8d3eeb15a5acca5 100644
--- a/doc/builtin/thread_create
+++ b/doc/builtin/thread_create
@@ -2,7 +2,7 @@ NAME
 	thread_create - create a thread
 
 SYNTAX
-	int thread_create(function f, mixed ... args);
+	object thread_create(function f, mixed ... args);
 
 DESCRIPTION
 	This function creates a new thread which will run simultaneously
@@ -10,10 +10,11 @@ DESCRIPTION
 	f with the arguments args. When f returns the thread will cease
 	to exist. All Pike functions are 'thread safe' meanting that running
 	a function at the same time from different threads will not corrupt
-	any internal data in the Pike process.
+	any internal data in the Pike process. The returned value will be
+	the same as the return value of this_thread() for the new thread.
 
 NOTA BENE
 	This function is only available on systems with POSIX threads support.
 
 SEE ALSO
-	/precompiled/mutex, /precompiled/condition
\ No newline at end of file
+	/precompiled/mutex, /precompiled/condition, this_thread
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index d1afd4c6afc357be93d908fdc8a00ef7685e5788..99e2e9ff1e77a2f90554c539faa335e896302b5f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -267,6 +267,8 @@ void exit_main()
   void cleanup_pike_types();
   void cleanup_program();
 
+  th_cleanup();
+
   cleanup_objects();
   exit_signals();
   exit_lex();
diff --git a/src/threads.c b/src/threads.c
index a2cdb2df9f9e3579cedf6a480e3020bd326f3eff..03e3aee60b26afed0243741feddcd9ef5be4ba61 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -2,26 +2,36 @@
 #include "threads.h"
 #include "array.h"
 #include "object.h"
+#include "macros.h"
 
 int num_threads = 1;
 int threads_disabled = 0;
+struct object *thread_id;
 
 #ifdef _REENTRANT
 
 MUTEX_T interpreter_lock;
 struct program *mutex_key = 0;
+struct program *thread_id_prog = 0;
 pthread_attr_t pattr;
 
+struct thread_starter
+{
+  struct object *id;
+  struct array *args;
+};
+
 void *new_thread_func(void * data)
 {
+  struct thread_starter arg = *(struct thread_starter *)data;
   JMP_BUF back;
-  struct array *foo;
   INT32 args;
-  foo=(struct array *)data;
-  args=foo->size;
+  free((char *)data);
+  args=arg.args->size;
   mt_lock( & interpreter_lock);
   init_interpreter();
 
+  thread_id=arg.id;
 
   if(SETJMP(back))
   {
@@ -31,38 +41,62 @@ void *new_thread_func(void * data)
     pop_stack();
     automatic_fatal=0;
   } else {
-    push_array_items(foo);
+    push_array_items(arg.args);
+    arg.args=0;
     f_call_function(args);
+
   }
 
   UNSETJMP(back);
 
+  destruct(thread_id);
+  free_object(thread_id);
+  thread_id=0;
+
   cleanup_interpret();
-  mt_unlock(& interpreter_lock);
   num_threads--;
+  mt_unlock(& interpreter_lock);
   th_exit(0);
 }
 
 void f_thread_create(INT32 args)
 {
+  struct thread_starter *arg;
   pthread_t dummy;
   int tmp;
-  struct array *a=aggregate_array(args);
-  num_threads++;
-  tmp=th_create(&dummy,new_thread_func,a);
-  if(tmp) num_threads--;
-  push_int(tmp);
+  arg=ALLOC_STRUCT(thread_starter);
+  arg->args=aggregate_array(args);
+  arg->id=clone(thread_id_prog,0);
+  tmp=th_create(&dummy,new_thread_func,arg);
+  if(!tmp)
+  {
+    num_threads++;
+    push_object(arg->id);
+    arg->id->refs++;
+  } else {
+    free_object(arg->id);
+    free_array(arg->args);
+    free((char *)arg);
+    push_int(0);
+  }
+}
+
+void f_this_thread(INT32 args)
+{
+  pop_n_elems(args);
+  push_object(thread_id);
+  thread_id->refs++;
 }
 
 void th_init()
 {
-  thr_setconcurrency(9);
   mt_lock( & interpreter_lock);
   pthread_attr_init(&pattr);
   pthread_attr_setstacksize(&pattr, 2 * 1024 * 1204);
   pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
 
   add_efun("thread_create",f_thread_create,"function(mixed ...:int)",OPT_SIDE_EFFECT);
+  add_efun("this_thread",f_this_thread,"function(:object)",OPT_EXTERNAL_DEPEND);
 }
 
 
@@ -246,6 +280,7 @@ void th_init_programs()
   set_init_callback(init_mutex_key_obj);
   set_exit_callback(exit_mutex_key_obj);
   mutex_key=end_c_program("/precompiled/mutex_key");
+  mutex_key->refs++;
 
   start_new_program();
   add_storage(sizeof(COND_T));
@@ -255,6 +290,34 @@ void th_init_programs()
   set_init_callback(init_cond_obj);
   set_exit_callback(exit_cond_obj);
   end_c_program("/precompiled/condition");
+
+  start_new_program();
+  thread_id_prog=end_c_program("/precompiled/thread");
+  thread_id_prog->refs++;
+
+  thread_id=clone(thread_id_prog,0);
+}
+
+void th_cleanup()
+{
+  if(mutex_key)
+  {
+    free_program(mutex_key);
+    mutex_key=0;
+  }
+
+  if(thread_id_prog)
+  {
+    free_program(thread_id_prog);
+    thread_id_prog=0;
+  }
+
+  if(thread_id)
+  {
+    destruct(thread_id);
+    free_object(thread_id);
+    thread_id=0;
+  }
 }
 
 #endif
diff --git a/src/threads.h b/src/threads.h
index 3653fade56c17af3df90808a83deaa727f8ca1a6..b143f3ecb5bbcbadedb4799742e79afe2d702860 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -13,6 +13,8 @@
 #endif
 
 extern int num_threads;
+struct object;
+extern struct object *thread_id;
 
 #define MUTEX_T pthread_mutex_t
 #define mt_init(X) pthread_mutex_init((X),0)
@@ -44,6 +46,7 @@ struct thread_state {
   int evaluator_stack_malloced;
   int mark_stack_malloced;
   JMP_BUF *recoveries;
+  struct object * thread_id;
 };
 
 #define THREADS_ALLOW() \
@@ -60,6 +63,7 @@ struct thread_state {
        _tmp.recoveries=recoveries; \
        _tmp.evaluator_stack_malloced=evaluator_stack_malloced; \
        _tmp.mark_stack_malloced=mark_stack_malloced; \
+       _tmp.thread_id = thread_id; \
        mt_unlock(& interpreter_lock); \
      }
 
@@ -74,13 +78,18 @@ struct thread_state {
        recoveries=_tmp.recoveries; \
        evaluator_stack_malloced=_tmp.evaluator_stack_malloced; \
        mark_stack_malloced=_tmp.mark_stack_malloced; \
+       thread_id = _tmp.thread_id; \
      } \
    } while(0)
 
 /* Prototypes begin here */
+struct thread_starter;
 void *new_thread_func(void * data);
 void f_thread_create(INT32 args);
+void f_this_thread();
 void th_init();
+struct mutex_storage;
+struct key_storage;
 void f_mutex_lock(INT32 args);
 void f_mutex_trylock(INT32 args);
 void init_mutex_obj(struct object *o);
@@ -93,6 +102,7 @@ void f_cond_broadcast(INT32 args);
 void init_cond_obj(struct object *o);
 void exit_cond_obj(struct object *o);
 void th_init_programs();
+void th_cleanup();
 /* Prototypes end here */
 
 #else
@@ -102,6 +112,7 @@ void th_init_programs();
 #define THREADS_ALLOW()
 #define THREADS_DISALLOW()
 #define th_init()
+#define th_cleanup()
 #define th_init_programs()
 #endif