+ struct thread *th,*next,*prev=0;
+ th=all_threads;
+ while(th) {
+ next=th->next;
+ if(th->state==STATE_DEAD) {
+ funcall1(SymbolFunction(HANDLE_THREAD_EXIT),make_fixnum(th->pid));
+#ifdef LISP_FEATURE_GENCGC
+ gc_alloc_update_page_tables(0, &th->alloc_region);
+#endif
+ get_spinlock(&all_threads_lock,th->pid);
+ if(prev) prev->next=next;
+ else all_threads=next;
+ release_spinlock(&all_threads_lock);
+ if(th->tls_cookie>=0) arch_os_thread_cleanup(th);
+ 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);
+ } else
+ prev=th;
+ th=next;
+ }
+}
+
+int interrupt_thread(pid_t pid, lispobj function)
+{
+ union sigval sigval;
+ struct thread *th;
+ sigval.sival_int=function;
+ for_each_thread(th)
+ if((th->pid==pid) && (th->state != STATE_DEAD))
+ return sigqueue(pid, SIG_INTERRUPT_THREAD, sigval);
+ errno=EPERM; return -1;
+}
+
+int signal_thread_to_dequeue (pid_t pid)
+{
+ return kill (pid, SIG_DEQUEUE);
+}
+
+
+/* stopping the world is a two-stage process. From this thread we signal
+ * all the others with SIG_STOP_FOR_GC. The handler for this signal does
+ * the usual pseudo-atomic checks (we don't want to stop a thread while
+ * it's in the middle of allocation) then waits for another SIG_STOP_FOR_GC.
+ */
+
+void gc_stop_the_world()
+{
+#ifdef QSHOW_SIGNALS
+ SHOW("gc_stop_the_world:begin");
+#endif
+ struct thread *p,*th=arch_os_get_current_thread();
+ /* keep threads from starting while the world is stopped. */
+ get_spinlock(&thread_start_lock,th->pid);
+#ifdef QSHOW_SIGNALS
+ SHOW("gc_stop_the_world:locked");
+#endif
+ /* stop all other threads by sending them SIG_STOP_FOR_GC */
+ for(p=all_threads; p; p=p->next) {
+ if((p!=th) && (p->pid!=0) && (p->state==STATE_RUNNING)) {
+ p->state=STATE_STOPPING;
+ if(kill(p->pid,SIG_STOP_FOR_GC)==-1) {
+ /* we can't kill the process; assume because it
+ * died already (and its parent is dead so never
+ * saw the SIGCHLD) */
+ p->state=STATE_DEAD;
+ }
+ }
+ }
+#ifdef QSHOW_SIGNALS
+ SHOW("gc_stop_the_world:signals sent");
+#endif
+ /* wait for the running threads to stop */
+ for(p=all_threads;p;) {
+ if((p==th) || (p->pid==0) || (p->state==STATE_STARTING) ||
+ (p->state==STATE_DEAD) || (p->state==STATE_STOPPED)) {
+ p=p->next;
+ }
+ }
+#ifdef QSHOW_SIGNALS
+ SHOW("gc_stop_the_world:end");
+#endif
+}
+
+void gc_start_the_world()
+{
+ struct thread *p,*th=arch_os_get_current_thread();
+ /* if a resumed thread creates a new thread before we're done with
+ * this loop, the new thread will get consed on the front of
+ * all_threads, but it won't have been stopped so won't need
+ * restarting; there can be threads just starting from before
+ * gc_stop_the_world, though */
+#ifdef QSHOW_SIGNALS
+ SHOW("gc_start_the_world:begin");
+#endif
+ for(p=all_threads;p;p=p->next) {
+ if((p!=th) && (p->pid!=0) && (p->state!=STATE_STARTING) &&
+ (p->state!=STATE_DEAD)) {
+ if(p->state!=STATE_STOPPED) {
+ lose("gc_start_the_world: wrong thread state is %ld\n",
+ fixnum_value(p->state));
+ }
+ kill(p->pid,SIG_STOP_FOR_GC);
+ }
+ }
+ /* we must wait for all threads to leave stopped state else we
+ * risk signal accumulation and lose any meaning of
+ * thread->state */
+ for(p=all_threads;p;) {
+ gc_assert(p->state!=STATE_STOPPING);
+ if((p==th) || (p->pid==0) || (p->state!=STATE_STOPPED)) {
+ p=p->next;
+ }
+ }
+ release_spinlock(&thread_start_lock);
+#ifdef QSHOW_SIGNALS
+ SHOW("gc_start_the_world:end");
+#endif