if (count > 0) VM_Processor.getCurrentProcessor().enableThreadSwitching();
if (count > 0) { Plan.collectionComplete(); VM_Processor.getCurrentProcessor().enableThreadSwitching(); }
   public void run()       throws VM_PragmaNoOptCompile, // refs stored in registers by opt compiler will not be relocated by GC 	      VM_PragmaLogicallyUninterruptible,  // due to call to snipObsoleteCompiledMethods	      VM_PragmaUninterruptible {    for (int count = 0; ; count++) {      /* suspend this thread: it will resume when scheduled by       * VM_Handshake initiateCollection().  while suspended,       * collector threads reside on the schedulers collectorQueue */      VM_Scheduler.collectorMutex.lock();      if (verbose >= 1) VM.sysWriteln("GC Message: VM_CT.run yielding");      if (count > 0) // resume normal scheduling	VM_Processor.getCurrentProcessor().enableThreadSwitching();        VM_Thread.getCurrentThread().yield(VM_Scheduler.collectorQueue,					 VM_Scheduler.collectorMutex);            /* block mutators from running on the current processor */      VM_Processor.getCurrentProcessor().disableThreadSwitching();            if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run waking up");      gcOrdinal = VM_Synchronization.fetchAndAdd(participantCount, 0, 1) + 1;            if (verbose > 2) VM.sysWriteln("GC Message: VM_CT.run entering first rendezvous - gcOrdinal =", gcOrdinal);      /* the first RVM VP will wait for all the native VPs not blocked       * in nativeto reach a SIGWAIT state */      if (gcOrdinal == 1) {        if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run quiescing native VPs");        for (int i = 1; i <= VM_Processor.numberNativeProcessors; i++) {          if (VM_Processor.vpStatus[VM_Processor.nativeProcessors[i].vpStatusIndex] != VM_Processor.BLOCKED_IN_NATIVE) {	    if (verbose >= 2) VM.sysWriteln("GC Mesage: VM_CollectorThread.run found one not blocked in native");	    	    while (VM_Processor.vpStatus[VM_Processor.nativeProcessors[i].vpStatusIndex] != VM_Processor.IN_SIGWAIT) {	      if (verbose >= 2)		VM.sysWriteln("GC Message: VM_CT.run  WAITING FOR NATIVE PROCESSOR", i,			      " with vpstatus = ",			      VM_Processor.vpStatus[VM_Processor.nativeProcessors[i].vpStatusIndex]);	      VM.sysVirtualProcessorYield();	    }	    /* Note: threads contextRegisters (ip & fp) are set by	     * thread before entering SIGWAIT, so nothing needs to be	     * done here */	  } else {	    /* BLOCKED_IN_NATIVE - set context regs so that scan of	     * threads stack will start at the java to C transition	     * frame. ip is not used for these frames, so can be set	     * to 0. */	    VM_Thread t = VM_Processor.nativeProcessors[i].activeThread;	    t.contextRegisters.setInnermost( VM_Address.zero() /*ip*/, t.jniEnv.topJavaFP() );	  }        }	/* quiesce any attached processors, blocking then IN_NATIVE or	 * IN_SIGWAIT */	quiesceAttachedProcessors();      }  // gcOrdinal==1      /* wait for other collector threads to arrive or be made       * non-participants */      if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run  initializing rendezvous");      gcBarrier.startupRendezvous();      /* actually perform the GC... */      if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run  starting collection");      if (isActive) VM_Interface.getPlan().collect(); // gc      if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run  finished collection");            /* wait for other collector threads to arrive here */      gcBarrier.rendezvous(5200);            /* Wake up mutators waiting for this gc cycle and create new       * collection handshake object to be used for next gc cycle.       * Note that mutators will not run until after thread switching       * is enabled, so no mutators can possibly arrive at old       * handshake object: it's safe to replace it with a new one. */      if (gcOrdinal == 1) {	/* Snip reference to any methods that are still marked	 * obsolete after we've done stack scans. This allows	 * reclaiming them on next GC. */	VM_CompiledMethods.snipObsoleteCompiledMethods();	collectionCount += 1;	/* notify mutators waiting on previous handshake object -	 * actually we don't notify anymore, mutators are simply in	 * processor ready queues waiting to be dispatched. */	handshake.notifyCompletion();	handshake.reset();	/* schedule the FinalizerThread, if there is work to do & it is idle */	VM_Interface.scheduleFinalizerThread();      }             /* wait for other collector threads to arrive here */      gcBarrier.rendezvous(5210);      if (verbose > 2) VM.sysWriteln("VM_CollectorThread: past rendezvous 1 after collection");      /* final cleanup for initial collector thread */      if (gcOrdinal == 1) {	/* unblock any native processors executing in native that were	 * blocked in native at the start of GC */	if (verbose > 3) VM.sysWriteln("VM_CollectorThread: unblocking native procs");	for (int i = 1; i <= VM_Processor.numberNativeProcessors; i++) {	  VM_Processor vp = VM_Processor.nativeProcessors[i];	  if (VM.VerifyAssertions) VM._assert(vp != null);	  if (VM_Processor.vpStatus[vp.vpStatusIndex] == VM_Processor.BLOCKED_IN_NATIVE ) {	    VM_Processor.vpStatus[vp.vpStatusIndex] = VM_Processor.IN_NATIVE;	    if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run unblocking Native Processor", vp.id);	  }	}	/* It is VERY unlikely, but possible that some RVM processors	 * were found in C, and were BLOCKED_IN_NATIVE, during the	 * collection, and now need to be unblocked. */	if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run unblocking native procs blocked during GC");	for (int i = 1; i <= VM_Scheduler.numProcessors; i++) {	  VM_Processor vp = VM_Scheduler.processors[i];	  if (VM.VerifyAssertions) VM._assert(vp != null);	  if (VM_Processor.vpStatus[vp.vpStatusIndex] == VM_Processor.BLOCKED_IN_NATIVE ) {	    VM_Processor.vpStatus[vp.vpStatusIndex] = VM_Processor.IN_NATIVE;	    if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run unblocking RVM Processor", vp.id);	  }	}		if (!VM.BuildForSingleVirtualProcessor) {	  /* if NativeDaemonProcessor was BLOCKED_IN_SIGWAIT, unblock it */	  VM_Processor ndvp = VM_Scheduler.processors[VM_Scheduler.nativeDPndx];	  if (ndvp!=null && VM_Processor.vpStatus[ndvp.vpStatusIndex] == VM_Processor.BLOCKED_IN_SIGWAIT) {	    VM_Processor.vpStatus[ndvp.vpStatusIndex] = VM_Processor.IN_SIGWAIT;	    if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run unblocking Native Daemon Processor");	  }	  /* resume any attached Processors blocked prior to Collection */	  resumeAttachedProcessors();	}	/* clear the GC flag */	if (verbose >= 2) VM.sysWriteln("GC Message: VM_CT.run clearing lock out field");	VM_Magic.setIntAtOffset(VM_BootRecord.the_boot_record, VM_Entrypoints.lockoutProcessorField.getOffset(), 0);      }    }  // end of while(true) loop      }  // run