+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
+}
+#endif