VM_SysCall.sysVirtualProcessorCreate(VM_Magic.getTocPointer(),
VM_Address toc = VM_Magic.getTocPointer(); VM_SysCall.sysVirtualProcessorCreate(toc,
  static void boot () throws VM_PragmaInterruptible {    if (VM.VerifyAssertions) VM._assert(1 <= numProcessors && numProcessors <= MAX_PROCESSORS);    if (VM.TraceThreads)      trace("VM_Scheduler.boot","numProcessors =", numProcessors);    // Create a VM_Processor object for each virtual cpu that we'll be running.    // Note that the VM_Processor object for the primordial processor    // (the virtual cpu in whose context we are currently running)    // was already created in the boot image by init(), above.    //    VM_Processor primordialProcessor = processors[PRIMORDIAL_PROCESSOR_ID];    VM_Processor [] origProcs = processors;    processors = new VM_Processor[1 + numProcessors + 1];  // first slot unused; then normal processors; then 1 ndp    //-#if RVM_WITH_HPM    // boot primordial virtual processor's HPM producer    primordialProcessor.hpm.boot();        //-#endif    for (int i = PRIMORDIAL_PROCESSOR_ID; i <= numProcessors; i++) {	VM_Processor p = (i < origProcs.length) ? origProcs[i] : null;	if (p == null) 	  processors[i] = new VM_Processor(i, VM_Processor.RVM);	else { 	  // XXXX setting of vpStatusAddress during JDK building of bootimage is not valid	  // so reset here...maybe change everything to just use index	  processors[i] = p;	  //-#if RVM_FOR_IA32	  p.jtoc = VM_Magic.getJTOC();  // only needed for EXTRA_PROCS	  //-#endif	  p.vpStatusAddress = VM_Magic.objectAsAddress(VM_Processor.vpStatus).add(p.vpStatusIndex<<LOG_BYTES_IN_INT);	}      //-#if RVM_WITH_HPM      // boot virtual processor's HPM producer      processors[i].hpm.boot();          //-#endif    }    // Create NativeDaemonProcessor as N+1st processor in the processors array.    // It is NOT included in "numProcessors" which is the index of the last RVM processor.    //    nativeDPndx = numProcessors + 1;		// the last entry in processors[]                                              if (VM.BuildWithNativeDaemonProcessor) {      processors[nativeDPndx] = new VM_Processor(numProcessors + 1, VM_Processor.NATIVEDAEMON);      if (VM.TraceThreads)	trace("VM_Scheduler.boot","created nativeDaemonProcessor with id",nativeDPndx);    } else {      processors[nativeDPndx] = null;      if (VM.TraceThreads)	trace("VM_Scheduler.boot","NativeDaemonProcessor not created");    }    // Create work queues.    //    wakeupQueue     = new VM_ProxyWakeupQueue(VM_EventLogger.WAKEUP_QUEUE);    wakeupMutex     = new VM_ProcessorLock();    debuggerQueue   = new VM_ThreadQueue(VM_EventLogger.DEBUGGER_QUEUE);    debuggerMutex   = new VM_ProcessorLock();    attachThreadQueue = new VM_ThreadQueue(VM_EventLogger.ATTACHTHREAD_QUEUE);    attachThreadMutex = new VM_ProcessorLock();    collectorQueue  = new VM_ThreadQueue(VM_EventLogger.COLLECTOR_QUEUE);    collectorMutex  = new VM_ProcessorLock();    finalizerQueue  = new VM_ThreadQueue(VM_EventLogger.FINALIZER_QUEUE);    finalizerMutex  = new VM_ProcessorLock();    nativeProcessorQueue  = new VM_ProcessorQueue(VM_EventLogger.DEAD_VP_QUEUE);    nativeProcessorMutex  = new VM_ProcessorLock();    deadVPQueue     = new VM_ProcessorQueue(VM_EventLogger.DEAD_VP_QUEUE);    availableProcessorQueue     = new VM_ProcessorQueue(VM_EventLogger.DEAD_VP_QUEUE);    VM_CollectorThread.boot(numProcessors);    // Create one one idle thread per processor.    //    for (int i = 0; i < numProcessors; ++i) {      VM_Thread t = new VM_IdleThread(processors[1+i]);      t.start(processors[1+i].idleQueue);    }    if (VM.BuildWithNativeDaemonProcessor) {      // Create one idle thread for the NATIVEDAEMON processor      VM_Thread t = new VM_IdleThread(processors[nativeDPndx]);      t.start(processors[nativeDPndx].idleQueue);      // create the NativeDaemonThread that runs on the NativeDaemonProcessor      t = new VM_NativeDaemonThread(processors[nativeDPndx]);      t.start(processors[nativeDPndx].readyQueue);    }    // JNI support    attachThreadRequested = VM_Address.zero();    terminated = false;             // the one we're running on    processors[PRIMORDIAL_PROCESSOR_ID].isInitialized = true;     // Create virtual cpu's.    //    //-#if RVM_FOR_SINGLE_VIRTUAL_PROCESSOR    //-#else    //-#if RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS     //-#else    // Create thread-specific data key which will allow us to find    // the correct VM_Processor from an arbitrary pthread.    VM_SysCall.sysCreateThreadSpecificDataKeys();    // enable spoofing of blocking native select calls    System.loadLibrary("syswrap");    //-#endif    if (VM.BuildWithNativeDaemonProcessor)      VM_SysCall.sysInitializeStartupLocks( numProcessors + 1 );    else      VM_SysCall.sysInitializeStartupLocks( numProcessors );    if (cpuAffinity != NO_CPU_AFFINITY)      VM_SysCall.sysVirtualProcessorBind(cpuAffinity + PRIMORDIAL_PROCESSOR_ID - 1); // bind it to a physical cpu    for (int i = PRIMORDIAL_PROCESSOR_ID; ++i <= numProcessors; ) {      // create VM_Thread for virtual cpu to execute      //      VM_Thread target = new VM_StartupThread(MM_Interface.newStack(STACK_SIZE_NORMAL>>2));       // create virtual cpu and wait for execution to enter target's code/stack.      // this is done with gc disabled to ensure that garbage collector doesn't move      // code or stack before the C startoff function has a chance      // to transfer control into vm image.      //      if (VM.TraceThreads)        trace("VM_Scheduler.boot", "starting processor id", i);      processors[i].activeThread = target;      processors[i].activeThreadStackLimit = target.stackLimit;      target.registerThread(); // let scheduler know that thread is active.      if (VM.BuildForPowerPC) {        //-#if RVM_FOR_POWERPC        VM_SysCall.sysVirtualProcessorCreate(VM_Magic.getTocPointer(),					     VM_Magic.objectAsAddress(processors[i]),					     target.contextRegisters.gprs.get(THREAD_ID_REGISTER).toAddress(),					     target.contextRegisters.getInnermostFramePointer());        //-#endif      } else if (VM.BuildForIA32) {        VM_SysCall.sysVirtualProcessorCreate(VM_Magic.getTocPointer(),					     VM_Magic.objectAsAddress(processors[i]),					     target.contextRegisters.ip, 					     target.contextRegisters.getInnermostFramePointer());      }    }    if (VM.BuildWithNativeDaemonProcessor) {      VM_Thread target = new VM_StartupThread(MM_Interface.newStack(STACK_SIZE_NORMAL>>LOG_BYTES_IN_ADDRESS));      processors[nativeDPndx].activeThread = target;      processors[nativeDPndx].activeThreadStackLimit = target.stackLimit;      target.registerThread(); // let scheduler know that thread is active.      if (VM.TraceThreads)        trace("VM_Scheduler.boot", "starting native daemon processor id", nativeDPndx);      if (VM.BuildForPowerPC) {        //-#if RVM_FOR_POWERPC        VM_SysCall.sysVirtualProcessorCreate(VM_Magic.getTocPointer(),					     VM_Magic.objectAsAddress(processors[nativeDPndx]),					     target.contextRegisters.gprs.get(THREAD_ID_REGISTER).toAddress(),					     target.contextRegisters.getInnermostFramePointer());        //-#endif      } else if (VM.BuildForIA32) {        VM_SysCall.sysVirtualProcessorCreate(VM_Magic.getTocPointer(),					     VM_Magic.objectAsAddress(processors[nativeDPndx]),					     target.contextRegisters.ip,					     target.contextRegisters.getInnermostFramePointer());      }      if (VM.TraceThreads)        trace("VM_Scheduler.boot", "started native daemon processor id", nativeDPndx);    }    // wait for everybody to start up    //    VM_SysCall.sysWaitForVirtualProcessorInitialization();    //-#endif    allProcessorsInitialized = true;    //    for (int i = PRIMORDIAL_PROCESSOR_ID; i <= numProcessors; ++i)    //      processors[i].enableThreadSwitching();    VM_Processor.getCurrentProcessor().enableThreadSwitching();    // Start interrupt driven timeslicer to improve threading fairness and responsiveness.    //    if (!VM.BuildForDeterministicThreadSwitching)       VM_SysCall.sysVirtualProcessorEnableTimeSlicing(VM.schedulingQuantum);    // Start event logger.    //    if (VM.BuildForEventLogging)      VM_EventLogger.boot();    // Allow virtual cpus to commence feeding off the work queues.    //    //-#if RVM_FOR_SINGLE_VIRTUAL_PROCESSOR    //-#else    VM_SysCall.sysWaitForMultithreadingStart();    //-#endif    //-#if RVM_WITH_OSR    OSR_ObjectHolder.boot();    //-#endif    // Start collector threads on each VM_Processor.    for (int i = 0; i < numProcessors; ++i) {      VM_Thread t = VM_CollectorThread.createActiveCollectorThread(processors[1+i]);      t.start(processors[1+i].readyQueue);    }    // Start the G.C. system.    // Start collector thread for native daemon processor (if configured).    if (VM.BuildWithNativeDaemonProcessor) {      VM_Thread t = VM_CollectorThread.createActiveCollectorThread(processors[nativeDPndx]);      t.start(processors[nativeDPndx].readyQueue);    }    // Create the FinalizerThread    FinalizerThread tt = new FinalizerThread();    tt.makeDaemon(true);    tt.start();    //-#if RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS    //-#else    // Store VM_Processor in pthread    VM_Processor.getCurrentProcessor().stashProcessorInPthread();    //-#endif  }