/* * 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.mmtk.harness.scheduler; import org.mmtk.harness.Collector; import org.mmtk.harness.Harness; import org.mmtk.harness.Mutator; import org.mmtk.harness.scheduler.javathreads.JavaThreadModel; import org.mmtk.harness.scheduler.rawthreads.RawThreadModel; import org.mmtk.utility.Log; /** * Facade class for the command-line selectable threading models available * in the MMTk harness. */ public class Scheduler { /** * Possible threading models */ public enum Model { /** Schedule using the Java thread scheduler */ JAVA, /** Schedule in the harness using deterministic algorithms */ DETERMINISTIC; /** @return The values of this enum, converted to strings */ public static String[] valueNames() { String[] result = new String[Scheduler.Model.values().length]; for (int i=0; i < Scheduler.Model.values().length; i++) { result[i] = Scheduler.Model.values()[i].toString(); } return result; } } /** * Possible thread-scheduling policies */ public enum SchedPolicy { /** Reschedule every nth yield point */ FIXED, /** Reschedule on a pseudo-random sequence of intervals */ RANDOM, /** Only reschedule when the thread is blocked */ NEVER; /** @return The values of this enum, converted to strings */ public static String[] valueNames() { String[] result = new String[Scheduler.SchedPolicy.values().length]; for (int i=0; i < Scheduler.SchedPolicy.values().length; i++) { result[i] = Scheduler.SchedPolicy.values()[i].toString(); } return result; } } /** * Thread Model factory - returns the thread model selected by user options. */ private static ThreadModel selectedThreadModel() { switch (Harness.scheduler.model()) { case JAVA: return new JavaThreadModel(); case DETERMINISTIC: return new RawThreadModel(); default: throw new RuntimeException("Unknown thread model"); } } private static ThreadModel model; /** * Yield policy factory - return an instance of the the command-line * selected yield policy * @param thread The Java thread * @return A new policy for the given thread */ public static Policy yieldPolicy(Thread thread) { switch (Harness.policy.policy()) { case FIXED: int yieldInterval = Harness.yieldInterval.getValue(); if (yieldInterval == 1) { return new YieldAlways(thread); } return new YieldEvery(thread,yieldInterval); case RANDOM: return new YieldRandomly(thread, Harness.randomPolicySeed.getValue(), Harness.randomPolicyLength.getValue(), Harness.randomPolicyMin.getValue(), Harness.randomPolicyMax.getValue()); case NEVER: return new YieldNever(thread); default: throw new RuntimeException("Unknown scheduler policy"); } } /** * Initialization */ public static void init() { model = selectedThreadModel(); } /** * Advance collector threads to their initial 'wait for collection' barrier */ public static void initCollectors() { model.initCollectors(); } /** * A yield-point. */ public static void yield() { model.yield(); } /** * Create and start a new Mutator thread * @param item The executable code to run in this thread */ public static void scheduleMutator(Schedulable item) { model.scheduleMutator(item); } /** * Create and start a new collector thread */ public static void scheduleCollector() { model.scheduleCollector(); } /** * Create and start a new collector thread running a particular code * sequence. Used to schedule unit tests in collector context. * * @param item The schedulable object * @return A java thread for the item */ public static Thread scheduleCollector(Schedulable item) { return model.scheduleCollector(item); } /** * @return The current Log object. */ public static Log currentLog() { return ((MMTkThread)Thread.currentThread()).getLog(); } /** * @return The current mutator object (if the current thread is a Mutator) */ public static Mutator currentMutator() { return model.currentMutator(); } /** * @return The current collector object (if the current thread is a Collector) */ public static Collector currentCollector() { return model.currentCollector(); } /* schedule GC */ /** * Request a GC. Once requested, mutator threads block at * 'waitForGC' until a collection is performed. * @param why Reason code */ public static void triggerGC(int why) { model.triggerGC(why); } /** * A collector thread informs the scheduler that it has completed * its GC work by calling this. */ public static void exitGC() { model.exitGC(); } /** * Collector threads call this method to wait for a GC to be triggered. */ public static void waitForGCStart() { model.waitForGCStart(); } /** * @see #triggerGC(int) * @return Why was the current GC triggered ? */ public static int getTriggerReason() { return model.getTriggerReason(); } /** * @return Are there no threads currently in GC? */ public static boolean noThreadsInGC() { return model.noThreadsInGC(); } /** * @return Has a GC been triggered? */ public static boolean gcTriggered() { return model.gcTriggered(); } /** * Collector thread synchronization barrier * @param where Rendezvous ID * @return The order of arrival at the barrier */ public static int rendezvous(int where) { return model.rendezvous(where); } public static int mutatorRendezvous(String name, int expected) { return model.mutatorRendezvous(name,expected); } /** * Cause the current thread to wait for a triggered GC to proceed. */ public static void waitForGC() { model.waitForGC(); } /** * Schedule the threads */ public static void schedule() { model.schedule(); } /** * Schedule the GC threads as though a GC had been triggered * Used to run unit tests that must run in collector context. */ public static void scheduleGcThreads() { model.scheduleGcThreads(); } /** * An MMTk lock - a factory method. * @param name The name of the lock * @return The newly created lock */ public static Lock newLock(String name) { return model.newLock(name); } }