/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.scheduler.greenthreads; import org.jikesrvm.VM; import org.jikesrvm.runtime.VM_Magic; import static org.jikesrvm.runtime.VM_SysCall.sysCall; import org.jikesrvm.runtime.VM_Time; import org.jikesrvm.scheduler.VM_Scheduler; import org.vmmagic.pragma.Uninterruptible; /** * Low priority thread to run when there's nothing else to do. * This thread also handles initializing the virtual processor * for execution. * * This follows the Singleton pattern. */ final class VM_SubArchIdleThread extends VM_GreenThread { /** * A thread to run if there is no other work for a virtual processor. */ VM_SubArchIdleThread(VM_GreenSubArchProcessor processorAffinity) { super("VM_SubArchIdleThread"); makeDaemon(true); super.processorAffinity = processorAffinity; setPriority(Thread.MIN_PRIORITY); } /** * Is this the idle thread? * @return true */ @Uninterruptible @Override public boolean isIdleThread() { return true; } @Override public void run() { // overrides VM_Thread if (state != State.RUNNABLE) changeThreadState(State.NEW, State.RUNNABLE); VM_GreenSubArchProcessor myProcessor = VM_GreenSubArchProcessor.getCurrentProcessor(); if (VM.ExtremeAssertions) VM._assert(myProcessor == processorAffinity); myProcessor.initializeProcessor(); // Only perform load balancing if there is more than one processor. final boolean loadBalancing = VM_GreenScheduler.numSubArchProcessors > 1; main: while (true) { if (VM_Scheduler.terminated) terminate(); // FIXME: if (VM.VerifyAssertions) VM._assert(processorAffinity.idleQueue.isEmpty()); for ( ; ; ) { VM_GreenSubArchProcessor.idleProcessor = myProcessor; if (availableWork(myProcessor)) { if (VM.ExtremeAssertions) { VM._assert(myProcessor == VM_GreenSubArchProcessor.getCurrentProcessor()); } VM_GreenThread.yield(VM_GreenSubArchProcessor.getCurrentProcessor().idleQueue); continue main; } } } } /** * @return true, if there appears to be a runnable thread for the processor to execute */ private static boolean availableWork(VM_GreenSubArchProcessor p) { if (!p.readyQueue.isEmpty()) return true; VM_Magic.isync(); if (!p.transferQueue.isEmpty()) return true; if (VM_GreenScheduler.wakeupQueue.isReady()) { VM_GreenScheduler.wakeupMutex.lock("wakeup mutex"); VM_GreenThread t = VM_GreenScheduler.wakeupQueue.dequeue(); VM_GreenScheduler.wakeupMutex.unlock(); if (t != null) { t.schedule(); return true; } } return false; } }