+ protect_control_stack_guard_page(th,1);
+ /* child will not start until this is set */
+ th->os_thread=kid_tid;
+}
+
+void create_initial_thread(lispobj initial_function) {
+ struct thread *th=create_thread_struct(initial_function);
+ os_thread_t kid_tid=thread_self();
+ if(th && kid_tid>0) {
+ link_thread(th,kid_tid);
+ initial_thread_trampoline(all_threads); /* no return */
+ } else lose("can't create initial thread");
+}
+
+#ifdef LISP_FEATURE_SB_THREAD
+
+boolean create_os_thread(struct thread *th,os_thread_t *kid_tid)
+{
+ /* The new thread inherits the restrictive signal mask set here,
+ * and enables signals again when it is set up properly. */
+ pthread_attr_t attr;
+ sigset_t newset,oldset;
+ boolean r=1;
+ sigemptyset(&newset);
+ sigaddset_blockable(&newset);
+ thread_sigmask(SIG_BLOCK, &newset, &oldset);
+
+ if((pthread_attr_init(&attr)) ||
+ (pthread_attr_setstack(&attr,th->control_stack_start,
+ THREAD_CONTROL_STACK_SIZE-16)) ||
+ (pthread_create
+ (kid_tid,&attr,(void *(*)(void *))new_thread_trampoline,th)))
+ r=0;
+ thread_sigmask(SIG_SETMASK,&oldset,0);
+ return r;
+}
+
+struct thread *create_thread(lispobj initial_function) {
+ struct thread *th;
+ os_thread_t kid_tid=0;
+ boolean success;
+
+ if(linux_no_threads_p) return 0;
+
+ th=create_thread_struct(initial_function);
+ if(th==0) return 0;
+
+ /* we must not be interrupted here after a successful
+ * create_os_thread, because the kid will be waiting for its
+ * thread struct to be linked */
+ GET_ALL_THREADS_LOCK("create_thread")
+
+ success=create_os_thread(th,&kid_tid);
+ if (success)
+ link_thread(th,kid_tid);
+ else
+ os_invalidate((os_vm_address_t) th->control_stack_start,
+ ((sizeof (lispobj))
+ * (th->control_stack_end-th->control_stack_start)) +
+ BINDING_STACK_SIZE+ALIEN_STACK_SIZE+dynamic_values_bytes+
+ 32*SIGSTKSZ);
+
+ RELEASE_ALL_THREADS_LOCK("create_thread")