+ struct thread *p,*th=arch_os_get_current_thread();
+ int status;
+ FSHOW_SIGNAL((stderr,"/gc_stop_the_world:waiting on lock, thread=%lu\n",
+ th->os_thread));
+ /* keep threads from starting while the world is stopped. */
+ pthread_mutex_lock(&all_threads_lock); \
+ FSHOW_SIGNAL((stderr,"/gc_stop_the_world:got lock, thread=%lu\n",
+ th->os_thread));
+ /* stop all other threads by sending them SIG_STOP_FOR_GC */
+ for(p=all_threads; p; p=p->next) {
+ while(p->state==STATE_STARTING) sched_yield();
+ if((p!=th) && (p->state==STATE_RUNNING)) {
+ FSHOW_SIGNAL((stderr,"/gc_stop_the_world: suspending %lu\n",
+ p->os_thread));
+ status=kill_thread_safely(p->os_thread,SIG_STOP_FOR_GC);
+ if (status==ESRCH) {
+ /* This thread has exited. */
+ gc_assert(p->state==STATE_DEAD);
+ } else if (status) {
+ lose("cannot send suspend thread=%lu: %d, %s",
+ p->os_thread,status,strerror(status));
+ }
+ }
+ }
+ FSHOW_SIGNAL((stderr,"/gc_stop_the_world:signals sent\n"));
+ /* wait for the running threads to stop or finish */
+ for(p=all_threads;p;) {
+ gc_assert(p->os_thread!=0);
+ gc_assert(p->state!=STATE_STARTING);
+ if((p==th) || (p->state==STATE_SUSPENDED) ||
+ (p->state==STATE_DEAD)) {
+ p=p->next;
+ } else {
+ sched_yield();
+ }
+ }
+ FSHOW_SIGNAL((stderr,"/gc_stop_the_world:end\n"));
+}
+
+void gc_start_the_world()
+{
+ struct thread *p,*th=arch_os_get_current_thread();
+ int status;
+ /* 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 */
+ FSHOW_SIGNAL((stderr,"/gc_start_the_world:begin\n"));
+ for(p=all_threads;p;p=p->next) {
+ gc_assert(p->os_thread!=0);
+ if((p!=th) && (p->state!=STATE_DEAD)) {
+ if(p->state!=STATE_SUSPENDED) {
+ lose("gc_start_the_world: wrong thread state is %d\n",
+ fixnum_value(p->state));
+ }
+ FSHOW_SIGNAL((stderr, "/gc_start_the_world: resuming %lu\n",
+ p->os_thread));
+ p->state=STATE_RUNNING;
+ status=kill_thread_safely(p->os_thread,SIG_STOP_FOR_GC);
+ if (status) {
+ lose("cannot resume thread=%lu: %d, %s",
+ p->os_thread,status,strerror(status));
+ }
+ }
+ }
+ /* If we waited here until all threads leave STATE_SUSPENDED, then
+ * SIG_STOP_FOR_GC wouldn't need to be a rt signal. That has some
+ * performance implications, but does away with the 'rt signal
+ * queue full' problem. */
+ pthread_mutex_unlock(&all_threads_lock); \
+ FSHOW_SIGNAL((stderr,"/gc_start_the_world:end\n"));