+static void
+link_thread(struct thread *th)
+{
+ if (all_threads) all_threads->prev=th;
+ th->next=all_threads;
+ th->prev=0;
+ all_threads=th;
+}
+
+#ifdef LISP_FEATURE_SB_THREAD
+static void
+unlink_thread(struct thread *th)
+{
+ if (th->prev)
+ th->prev->next = th->next;
+ else
+ all_threads = th->next;
+ if (th->next)
+ th->next->prev = th->prev;
+}
+#endif
+
+static int
+initial_thread_trampoline(struct thread *th)
+{
+ lispobj function;
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+ lispobj *args = NULL;
+#endif
+#ifdef LISP_FEATURE_SB_THREAD
+ pthread_setspecific(lisp_thread, (void *)1);
+#endif
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_PPC)
+ /* SIG_STOP_FOR_GC defaults to blocked on PPC? */
+ unblock_gc_signals(0,0);
+#endif
+ function = th->no_tls_value_marker;
+ th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG;
+ if(arch_os_thread_init(th)==0) return 1;
+ link_thread(th);
+ th->os_thread=thread_self();
+#ifndef LISP_FEATURE_WIN32
+ protect_control_stack_hard_guard_page(1, NULL);
+ protect_binding_stack_hard_guard_page(1, NULL);
+ protect_alien_stack_hard_guard_page(1, NULL);
+ protect_control_stack_guard_page(1, NULL);
+ protect_binding_stack_guard_page(1, NULL);
+ protect_alien_stack_guard_page(1, NULL);
+#endif
+
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+ return call_into_lisp_first_time(function,args,0);
+#else
+ return funcall0(function);
+#endif
+}
+
+#ifdef LISP_FEATURE_SB_THREAD
+#define THREAD_STATE_LOCK_SIZE \
+ (sizeof(pthread_mutex_t))+(sizeof(pthread_cond_t))
+#else
+#define THREAD_STATE_LOCK_SIZE 0
+#endif
+
+#define THREAD_STRUCT_SIZE (thread_control_stack_size + BINDING_STACK_SIZE + \
+ ALIEN_STACK_SIZE + \
+ THREAD_STATE_LOCK_SIZE + \
+ dynamic_values_bytes + \
+ 32 * SIGSTKSZ + \
+ THREAD_ALIGNMENT_BYTES)
+
+#ifdef LISP_FEATURE_SB_THREAD
+/* THREAD POST MORTEM CLEANUP
+ *
+ * Memory allocated for the thread stacks cannot be reclaimed while
+ * the thread is still alive, so we need a mechanism for post mortem
+ * cleanups. FIXME: We actually have three, for historical reasons as
+ * the saying goes. Do we really need three? Nikodemus guesses that
+ * not anymore, now that we properly call pthread_attr_destroy before
+ * freeing the stack. */
+
+static struct thread_post_mortem *
+plan_thread_post_mortem(struct thread *corpse)
+{
+ if (corpse) {
+ struct thread_post_mortem *post_mortem = malloc(sizeof(struct thread_post_mortem));
+ gc_assert(post_mortem);
+ post_mortem->os_thread = corpse->os_thread;
+ post_mortem->os_attr = corpse->os_attr;
+ post_mortem->os_address = corpse->os_address;
+#ifdef DELAY_THREAD_POST_MORTEM
+ post_mortem->next = NULL;
+#endif
+ return post_mortem;
+ } else {
+ /* FIXME: When does this happen? */
+ return NULL;
+ }
+}