/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * 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/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.scheduler; import org.jikesrvm.VM; import static org.jikesrvm.runtime.SysCall.sysCall; import org.vmmagic.pragma.NonMoving; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.pragma.UninterruptibleNoWarn; /** * The timer thread. Although we are using purely native threading, threads * need to occasionally be poked for the purposes of sampling and OSR. * <p> * It should be noted that the implementation of this class prioritizes * unobtrusiveness and lock-freedom over precision. For example, on any given * timer release some threads may be missed or poked more than once, with the * understanding that if they are missed on one release then they will (with * high probability) not be missed on a future release. * <p> * It may be that to make the system scale, more than one timer thread will * be needed. But for now, this should suffice. */ @Uninterruptible @NonMoving public class TimerThread extends SystemThread { private static final int verbose = 0; public TimerThread() { super("TimerThread"); } // NOTE: this runs concurrently with stop-the-world GC // TODO: consider allowing GC to be sampled to enable profile-directed optimization of MMTk. @Override public void run() { VM.disableYieldpoints(); if (verbose >= 1) VM.sysWriteln("TimerThread run routine entered"); try { for (;;) { sysCall.sysNanoSleep(1000L * 1000L * VM.interruptQuantum); if (VM.BuildForAdaptiveSystem) { // grab the lock to prevent threads from getting GC'd while we are // iterating (since this thread doesn't stop for GC) RVMThread.acctLock.lockNoHandshake(); RVMThread.timerTicks++; for (int i = 0; i < RVMThread.numThreads; ++i) { RVMThread candidate = RVMThread.threads[i]; if (candidate != null && candidate.shouldBeSampled()) { candidate.timeSliceExpired++; candidate.takeYieldpoint = 1; } } RVMThread.acctLock.unlock(); } RVMThread.checkDebugRequest(); } } catch (Throwable e) { printExceptionAndDie(e); } } @UninterruptibleNoWarn private static void printExceptionAndDie(Throwable e) { VM.sysWriteln("Unexpected exception thrown in timer thread: ",e.toString()); e.printStackTrace(); VM.sysFail("Died in timer thread."); } }