VM_Thread.getCurrentThread().jniEnv.JNITopJavaFP = VM_Magic.getFramePointer();
VM_Thread.getCurrentThread().jniEnv.setTopJavaFP(VM_Magic.getFramePointer());
  public void run () throws VM_PragmaNoOptCompile /* refs stored in registers by opt compiler will not be relocated by GC */{    if (trace) VM_Scheduler.trace(" Entering run method of NDT ", "  ");    VM_Processor myProcessor = VM_ProcessorLocalState.getCurrentProcessor();    int i, transferCount=0, stuckCount=0;    // save current frame pointer in threads JNIEnv, and set flag recognized by GC    // which will cause this (NativeIdleThread) thread to have its stack scanned    // starting at this frame    //    VM_Thread.getCurrentThread().jniEnv.JNITopJavaFP = VM_Magic.getFramePointer();    // remember status word index for executing processor. It will remain valid    // even if GC moves the processor object    //    int processorStatusIndex = VM_Processor.getCurrentProcessor().vpStatusIndex;    while (true) {      if (VM.BuildForEventLogging && VM.EventLoggingEnabled) VM_EventLogger.logIdleEvent();      if (trace) VM_Scheduler.trace("NDT:","calling SigWait - transferred",transferCount);      // Save current frame pointer in threads JNIEnv, and set flag recognized by GC      // which will cause this (NativeIdleThread) thread to have its stack scanned      // starting at this frame, if it is in a sigwait syscall during a collection.      //      VM_Thread.getCurrentThread().jniEnv.JNITopJavaFP = VM_Magic.getFramePointer();      inSysWait = true;  // temporary...GC code looks for this flag in native idle threads      VM_Address TOC = VM_Address.fromInt(0);      //-#if RVM_FOR_POWERPC      TOC = VM_BootRecord.the_boot_record.sysTOC;      //-#endif      VM_Magic.sysCallSigWait(VM_BootRecord.the_boot_record.sysPthreadSigWaitIP,			      TOC,		              myProcessor.vpStatusAddress.toInt(),			      VM_Processor.IN_SIGWAIT,			      VM_Thread.getCurrentThread().contextRegisters);      inSysWait = false;      VM_Processor.vpStatus[processorStatusIndex] = VM_Processor.IN_JAVA;      // GC might have happened and my processor object moved      //      VM_ProcessorLocalState.setCurrentProcessor(myProcessor);      if (trace) VM_Scheduler.trace("NDT:","woke up from SigWait");      if (VM_Handshake.queryLockoutLock() != 0) {	// go back to sigwait, probably collided with GC	transferCount = -1;   // to indicate what happened in above trace call	continue;      }      // GET HERE FROM A SIGNAL SENT FROM cSignalHandler in libvm.C -      // iff at least one RVM vp has been found "stuck in C"      //      // Count RVM processors that are stuck, and preallocate sufficient      // native processors, so that transfers can be done without allocation.      stuckCount = 0;   // counts threads observed stuck      transferCount = 0;    // counts threads actually transferred      for (i = VM_Scheduler.PRIMORDIAL_PROCESSOR_ID; i <= VM_Scheduler.numProcessors; i++) {	VM_Processor vp = VM_Scheduler.processors[i];	// WARNING: -2 in next instruction must match MISSES in libvm.C	if (vp.threadSwitchRequested < -2) {	  if (VM_Processor.vpStatus[vp.vpStatusIndex] == VM_Processor.IN_NATIVE) {	    stuckCount++;	    if (trace || (DEBUG && (vp.threadSwitchRequested*-1)%100 == 0)) {	      VM_Scheduler.trace("\n  NDT:","threadSwitchRequested =",				 vp.threadSwitchRequested);	      vp.dumpProcessorState();	    }	  }	}      }      if (trace) VM_Scheduler.trace("NDT:","stuck processor count =",stuckCount);      if (stuckCount == 0) continue;  // false alarm, no processors stuck      // pre allocate required number of native processors, if necessary      // NOTE: resulting allocations may trigger GC, in which case, this      // daemon thread, being IN_JAVA (not IN_SIGWAIT) will participate      //      createNativeProcessors(stuckCount);      // acquire lockoutlock to prevent GC, and other major restructuring      // like AttachVM etc., during the transfer of blocked threads to      // native processors. Yield until available.      VM_Handshake.acquireLockoutLock( 0x0DDDDDDD, false /*yield*/ );      // find the processor(s) stuck in C and move the blocked thread(s)       // (pthread and java thread) to native processors, and take the pthread      // from the native processor to continue execution on the previously      // blocked RVM processor.      for (i = VM_Scheduler.PRIMORDIAL_PROCESSOR_ID; i <= VM_Scheduler.numProcessors; i++) {	VM_Processor vp = VM_Scheduler.processors[i];	// WARNING: -2 in next instruction must match MISSES in libvm.C	if (vp.threadSwitchRequested < -2) {	  boolean result = vp.lockInCIfInC();	  if (result) {	    transfer(vp);	    transferCount++;	    // quit after transferring up to the previously observed stuckCount	    // because we may not have sufficient available NativeProcessors	    // and we do not want to allocate while holding the lockoutLock	    if (transferCount == stuckCount) break;	  }	}      }      VM_Handshake.releaseLockoutLock( 0x0DDDDDDD );    }  // while(true)      }	//run method