/* * 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.scheduler.VM_ProcessorLock; import org.jikesrvm.scheduler.VM_Thread; import org.vmmagic.pragma.Uninterruptible; /** * A queue of generic VM_Threads for use with locking */ @Uninterruptible public final class VM_ThreadQueue extends VM_AbstractThreadQueue{ /** * First thread on list. */ private VM_GreenThread head; /** * Last thread on the list. */ private VM_GreenThread tail; /** * Are any threads on the queue? */ @Override public boolean isEmpty() { return head == null; } /** * Atomic test to determine if any threads are on the queue. * Note: The test is required for native idle threads */ boolean atomicIsEmpty(VM_ProcessorLock lock) { boolean r; lock.lock("atomic is empty"); r = (head == null); lock.unlock(); return r; } /** Add a thread to head of queue. */ public void enqueueHighPriority(VM_GreenThread t) { if (VM.VerifyAssertions) VM._assert(t.getNext() == null); // not currently on any other queue t.setNext(head); head = t; if (tail == null) { tail = t; } } /** Add a thread to tail of queue. */ @Override public void enqueue(VM_GreenThread t) { if (VM.VerifyAssertions) VM._assert(t.getNext() == null); // not currently on any other queue if (head == null) { head = t; } else { tail.setNext(t); } tail = t; } /** * Remove a thread from the head of the queue. * @return the thread (null --> queue is empty) */ @Override public VM_GreenThread dequeue() { VM_GreenThread t = head; if (t == null) { return null; } head = t.getNext(); t.setNext(null); if (head == null) { tail = null; } return t; } /** * Dequeue the CollectorThread, if any, from this queue. If qlock != null * protect by lock. * @return The garbage collector thread. If no thread found, return null. */ VM_GreenThread dequeueGCThread(VM_ProcessorLock qlock) { if (qlock != null) qlock.lock("dequeueing thread mutex"); VM_GreenThread currentThread = head; if (head == null) { if (qlock != null) qlock.unlock(); return null; } VM_GreenThread nextThread = head.getNext(); if (currentThread.isGCThread()) { head = nextThread; if (head == null) { tail = null; } currentThread.setNext(null); if (qlock != null) qlock.unlock(); return currentThread; } while (nextThread != null) { if (nextThread.isGCThread()) { currentThread.setNext(nextThread.getNext()); if (nextThread == tail) { tail = currentThread; } nextThread.setNext(null); if (qlock != null) qlock.unlock(); return nextThread; } currentThread = nextThread; nextThread = nextThread.getNext(); } return null; } /** * Number of items on queue (an estimate only: we do not lock the queue during * this scan.) */ @Override public int length() { int length = 0; for (VM_GreenThread t = head; t != null; t = t.getNext()) { length++; } return length; } /** Debugging. */ public boolean contains(VM_Thread x) { for (VM_GreenThread t = head; t != null; t = t.getNext()) { if (t == x) return true; } return false; } public void dump() { // We shall space-separate them, for compactness. // I hope this is a good decision. boolean pastFirst = false; for (VM_GreenThread t = head; t != null; t = t.getNext()) { if (pastFirst) { VM.sysWrite(" "); } t.dump(); pastFirst = true; } VM.sysWrite("\n"); } }