/* * 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.runtime.VM_Time; /** * A collection of static methods for waiting on some type of event. * These methods may allocate objects for recordkeeping purposes, * and thus may not be called from within the scheduler proper * (e.g., <code>VM_Thread</code>, which is uninterruptible). */ class VM_Wait { private static boolean noIoWait = false; /** * Called by VM.sysExit() to disable IO waits while the VM is * shutting down (and flushing its output streams). * The reason is that we can't be sure that thread switching * is possible during shutdown. */ public static void disableIoWait() { noIoWait = true; } /** * Given a total number of seconds to wait, computes timestamp * of time when the wait should time out. * Leaves negative times unchanged, since these indicate infinite waits. */ private static long getMaxWaitNano(double totalWaitTimeInSeconds) { // If a non-negative wait time was specified, it specifies the total // number of seconds to wait, so convert it to a timestamp (number of // seconds past the epoch). Negative value indicates indefinite wait, // in which case nothing needs to be done. long maxWaitNano = (long)(totalWaitTimeInSeconds * 1e9); if (maxWaitNano >= 0) { maxWaitNano += VM_Time.nanoTime(); } return maxWaitNano; } /** * Suspend execution of current thread until "fd" can be read without * blocking. * @param fd the native file descriptor to wait on * @param totalWaitTime the number of seconds to wait; negative values * indicate an infinite wait time * @return the wait data object indicating the result of the wait */ public static VM_ThreadIOWaitData ioWaitRead(int fd, double totalWaitTime) { // Create wait data to represent the event the thread is // waiting for long maxWaitNano = getMaxWaitNano(totalWaitTime); VM_ThreadIOWaitData waitData = new VM_ThreadIOWaitData(maxWaitNano); waitData.readFds = new int[]{fd}; if (noIoWait) { waitData.markAllAsReady(); } else { // Put the thread on the ioQueue VM_GreenThread.ioWaitImpl(waitData); } return waitData; } /** * Infinite wait for a read file descriptor to become ready. */ public static VM_ThreadIOWaitData ioWaitRead(int fd) { return ioWaitRead(fd, VM_ThreadEventConstants.WAIT_INFINITE); } /** * Suspend execution of current thread until "fd" can be written without * blocking. * @param fd the native file descriptor to wait on * @param totalWaitTime the number of seconds to wait; negative values * indicate an infinite wait time * @return the wait data object indicating the result of the wait */ public static VM_ThreadIOWaitData ioWaitWrite(int fd, double totalWaitTime) { // Create wait data to represent the event the thread is // waiting for long maxWaitNano = getMaxWaitNano(totalWaitTime); VM_ThreadIOWaitData waitData = new VM_ThreadIOWaitData(maxWaitNano); waitData.writeFds = new int[]{fd}; if (noIoWait) { waitData.markAllAsReady(); } else { // Put the thread on the ioQueue VM_GreenThread.ioWaitImpl(waitData); } return waitData; } /** * Infinite wait for a write file descriptor to become ready. */ public static VM_ThreadIOWaitData ioWaitWrite(int fd) { return ioWaitWrite(fd, VM_ThreadEventConstants.WAIT_INFINITE); } /** * Suspend execution of current thread until any of the given * file descriptors have become ready, or the wait times out. * When this method returns, the file descriptors which are * ready will have * {@link VM_ThreadIOConstants#FD_READY_BIT FD_READY_BIT} set, * and file descriptors which are invalid will have * {@link VM_ThreadIOConstants#FD_INVALID_BIT FD_INVALID_BIT} set. * * @param readFds array of read file descriptors * @param writeFds array of write file descriptors * @param exceptFds array of exception file descriptors * @param totalWaitTime amount of time to wait, in seconds; if * negative, wait indefinitely * @param fromNative true if this select is being called * from native code */ public static void ioWaitSelect(int[] readFds, int[] writeFds, int[] exceptFds, double totalWaitTime, boolean fromNative) { // Create wait data to represent the event that the thread is // waiting for long maxWaitNano = getMaxWaitNano(totalWaitTime); VM_ThreadIOWaitData waitData = new VM_ThreadIOWaitData(maxWaitNano); waitData.readFds = readFds; waitData.writeFds = writeFds; waitData.exceptFds = exceptFds; if (fromNative) { waitData.setNative(); } // Put the thread on the ioQueue if (noIoWait) { waitData.markAllAsReady(); } else { VM_GreenThread.ioWaitImpl(waitData); } } public static VM_ThreadSubArchWaitData subArchWait(int threadId) { return subArchWait(threadId, VM_ThreadEventConstants.WAIT_INFINITE); } /** * Suspend execution of current thread until thread has migrated back from * the subarch * @param threadId the subarch thread id we are waiting for * @param totalWaitTime the number of seconds to wait; negative values * indicate an infinite wait time * @return the wait data object indicating the result of the wait */ public static VM_ThreadSubArchWaitData subArchWait(int threadId, double totalWaitTime) { // Create wait data to represent the event the thread is // waiting for long maxWaitNano = getMaxWaitNano(totalWaitTime); VM_ThreadSubArchWaitData waitData = new VM_ThreadSubArchWaitData(maxWaitNano, threadId); // Put the thread on the ioQueue VM_GreenThread.subArchWaitImpl(waitData); return waitData; } /** * Suspend execution of current thread until process whose * pid is given has finished, or the thread is interrupted. * @param process the object representing the process to wait for * @param totalWaitTime number of seconds to wait, or negative if * caller wants to wait indefinitely * @return the <code>VM_ThreadProcessWaitData</code> representing * the state of the process */ public static VM_ThreadProcessWaitData processWait(VM_Process process, double totalWaitTime) throws InterruptedException { // Create wait data to represent the event the thread is // waiting for long maxWaitNano = getMaxWaitNano(totalWaitTime); VM_ThreadProcessWaitData waitData = new VM_ThreadProcessWaitData(process.getPid(), maxWaitNano); // Put the thread on the processWaitQueue VM_GreenThread.processWaitImpl(waitData, process); return waitData; } }