+
+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 kills _itself_ with SIGSTOP.
+ */
+
+void gc_stop_the_world()
+{
+ /* stop all other threads by sending them SIG_STOP_FOR_GC */
+ struct thread *p,*th=arch_os_get_current_thread();
+ pid_t old_pid;
+ int finished;
+ do {
+ finished=1;
+ for(p=all_threads,old_pid=p->pid; p; p=p->next) {
+ if(p==th) continue;
+ if(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;
+ }
+ }
+ if((p->state!=STATE_STOPPED) &&
+ (p->state!=STATE_DEAD)) {
+ finished=0;
+ }
+ }
+ if(old_pid!=all_threads->pid) {
+ finished=0;
+ }
+ } while(!finished);
+}
+
+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_lock, but it won't have been stopped so won't need
+ * restarting */
+ for(p=all_threads;p;p=p->next) {
+ if((p==th) || (p->state==STATE_DEAD)) continue;
+ p->state=STATE_RUNNING;
+ kill(p->pid,SIG_STOP_FOR_GC);
+ }
+}