+ int result;
+ FSHOW((stderr,"/creating thread %lu\n", thread_self()));
+ function = th->no_tls_value_marker;
+ th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG;
+ if(arch_os_thread_init(th)==0) {
+ /* FIXME: handle error */
+ lose("arch_os_thread_init failed\n");
+ }
+
+ th->os_thread=thread_self();
+ protect_control_stack_guard_page(1);
+ /* Since GC can only know about this thread from the all_threads
+ * list and we're just adding this thread to it there is no danger
+ * of deadlocking even with SIG_STOP_FOR_GC blocked (which it is
+ * not). */
+ pthread_mutex_lock(&all_threads_lock);
+ link_thread(th);
+ pthread_mutex_unlock(&all_threads_lock);
+
+ result = funcall0(function);
+ th->state=STATE_DEAD;
+
+ /* SIG_STOP_FOR_GC is blocked and GC might be waiting for this
+ * thread, but since we are already dead it won't wait long. */
+ pthread_mutex_lock(&all_threads_lock);
+ gc_alloc_update_page_tables(0, &th->alloc_region);
+ unlink_thread(th);
+ pthread_mutex_unlock(&all_threads_lock);
+
+ if(th->tls_cookie>=0) arch_os_thread_cleanup(th);
+ os_invalidate((os_vm_address_t)th->interrupt_data,
+ (sizeof (struct interrupt_data)));
+ free_thread_stack_later(th);
+ FSHOW((stderr,"/exiting thread %lu\n", thread_self()));
+ return result;
+}