/* * 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_Time; import org.vmmagic.pragma.Uninterruptible; /** * A queue of VM_Proxys prioritized by their thread wakeup times. * based on VM_WakeupQueue (14 October 1998 Bowen Alpern) */ @Uninterruptible public final class VM_ThreadProxyWakeupQueue extends VM_AbstractThreadQueue { /** first thread on list */ private VM_ThreadProxy head; /** * Are any proxies on the queue? */ @Override public boolean isEmpty() { return head == null; } /** * Is the head of the queue (the thread set to wake up first) ready to be * restarted? */ public boolean isReady() { VM_ThreadProxy temp = head; return ((temp != null) && (VM_Time.nanoTime() >= temp.getWakeupNano())); } /** * Put proxy for this thread on the queue. * Since a processor lock is held, the proxy cannot be created here. * Instead, it is cached in the proxy field of the thread. */ @Override public void enqueue(VM_GreenThread t) { enqueue(t.threadProxy); } /** * Add the proxy for a thread in a place determined by its wakeup time */ public void enqueue(VM_ThreadProxy p) { if (p != null) { p.mutex.lock("Enqueueing proxy"); if (p.getPatron() != null) { if(VM.VerifyAssertions) VM._assert(p.getPatron().isQueueable()); VM_ThreadProxy previous = null; VM_ThreadProxy current = head; // skip proxies with earlier wakeup timestamps while (current != null && current.getWakeupNano() <= p.getWakeupNano()) { previous = current; current = current.getWakeupNext(); } // insert p if (previous == null) { head = p; } else { previous.setWakeupNext(p); } p.setWakeupNext(current); } p.mutex.unlock(); } } /** * Remove a thread from the queue if there's one ready to wake up "now". * Returned: the thread (null --> nobody ready to wake up) */ @Override public VM_GreenThread dequeue() { long currentNano = VM_Time.nanoTime(); while (head != null) { if (currentNano < head.getWakeupNano()) return null; VM_ThreadProxy p = head; head = head.getWakeupNext(); p.setWakeupNext(null); VM_GreenThread t = p.unproxy(); if (t != null) return t; } return null; } /** * Number of items on queue (an estimate: queue is not locked during the * scan). */ @Override public int length() { if (head == null) return 0; int length = 1; for (VM_ThreadProxy p = head; p != null; p = p.getWakeupNext()) { length += 1; } return length; } // Debugging. // public boolean contains(VM_GreenThread t) { for (VM_ThreadProxy p = head; p != null; p = p.getWakeupNext()) { if (p.getPatron() == t) return true; } return false; } public void dump() { if (head != null) { VM.sysWrite(" nowNano=", VM_Time.nanoTime()); VM.sysWrite(" "); for (VM_ThreadProxy p = head; p != null; p = p.getWakeupNext()) { if (p.getPatron() != null) { p.getPatron().dump(); VM.sysWrite("(wakeupNano=", p.getWakeupNano()); VM.sysWrite(") "); } } } VM.sysWrite("\n"); } }