- 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);
+ /* 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