001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.scheduler; 014 015 import org.jikesrvm.VM; 016 import static org.jikesrvm.runtime.SysCall.sysCall; 017 import org.vmmagic.pragma.NonMoving; 018 import org.vmmagic.pragma.Uninterruptible; 019 import org.vmmagic.pragma.UninterruptibleNoWarn; 020 021 /** 022 * The timer thread. Although we are using purely native threading, threads 023 * need to occasionally be poked for the purposes of sampling and OSR. 024 * <p> 025 * It should be noted that the implementation of this class prioritizes 026 * unobtrusiveness and lock-freedom over precision. For example, on any given 027 * timer release some threads may be missed or poked more than once, with the 028 * understanding that if they are missed on one release then they will (with 029 * high probability) not be missed on a future release. 030 * <p> 031 * It may be that to make the system scale, more than one timer thread will 032 * be needed. But for now, this should suffice. 033 */ 034 @Uninterruptible 035 @NonMoving 036 public class TimerThread extends SystemThread { 037 private static final int verbose = 0; 038 public TimerThread() { 039 super("TimerThread"); 040 } 041 // NOTE: this runs concurrently with stop-the-world GC 042 // TODO: consider allowing GC to be sampled to enable profile-directed optimization of MMTk. 043 @Override 044 public void run() { 045 VM.disableYieldpoints(); 046 if (verbose>=1) VM.sysWriteln("TimerThread run routine entered"); 047 try { 048 for (;;) { 049 sysCall.sysNanoSleep(1000L*1000L*VM.interruptQuantum); 050 051 if (VM.BuildForAdaptiveSystem) { 052 // grab the lock to prevent threads from getting GC'd while we are 053 // iterating (since this thread doesn't stop for GC) 054 RVMThread.acctLock.lockNoHandshake(); 055 RVMThread.timerTicks++; 056 for (int i=0;i<RVMThread.numThreads;++i) { 057 RVMThread candidate=RVMThread.threads[i]; 058 if (candidate!=null && candidate.shouldBeSampled()) { 059 candidate.timeSliceExpired++; 060 candidate.takeYieldpoint=1; 061 } 062 } 063 RVMThread.acctLock.unlock(); 064 } 065 066 RVMThread.checkDebugRequest(); 067 } 068 } catch (Throwable e) { 069 printExceptionAndDie(e); 070 } 071 } 072 @UninterruptibleNoWarn 073 private static void printExceptionAndDie(Throwable e) { 074 VM.sysWriteln("Unexpected exception thrown in timer thread: ",e.toString()); 075 e.printStackTrace(); 076 VM.sysFail("Died in timer thread."); 077 } 078 } 079