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 */
013package org.jikesrvm.adaptive;
014
015import org.jikesrvm.adaptive.controller.Controller;
016import org.jikesrvm.runtime.Magic;
017import org.jikesrvm.scheduler.RVMThread;
018import org.jikesrvm.scheduler.SystemThread;
019import org.vmmagic.pragma.Uninterruptible;
020import org.vmmagic.pragma.NonMoving;
021
022/**
023 * Organizer thread collects OSR requests and inserted in controller queue
024 * The producers are application threads, and the consumer thread is the
025 * organizer. The buffer is RVMThread.threads array. The producer set
026 * it is own flag "requesting_osr" and notify the consumer. The consumer
027 * scans the threads array and collect requests.
028 */
029@NonMoving
030public final class OSROrganizerThread extends SystemThread {
031  /** Constructor */
032  public OSROrganizerThread() {
033    super("OSR_Organizer");
034  }
035
036  public boolean osr_flag = false;
037
038  @Override
039  public void run() {
040    while (true) {
041      rvmThread.monitor().lockNoHandshake();
042      if (!this.osr_flag) {
043        rvmThread.monitor().waitWithHandshake();
044      }
045      this.osr_flag = false; /* if we get another activation after here
046                              then we should rescan the threads array */
047      rvmThread.monitor().unlock();
048
049      processOsrRequest();
050    }
051  }
052
053  /**
054   * Activates organizer thread if it is waiting.
055   */
056  @Uninterruptible
057  public void activate() {
058    rvmThread.monitor().lockNoHandshake();
059    osr_flag = true;
060    rvmThread.monitor().broadcast();
061    rvmThread.monitor().unlock();
062  }
063
064  private void processOsrRequest() {
065    // scan RVMThread.threads (scan down so we don't miss anything)
066    for (int i = RVMThread.numThreads - 1; i >= 0; i--) {
067      Magic.sync();
068      RVMThread t = RVMThread.threads[i];
069      if (t != null) {
070        boolean go = false;
071        t.monitor().lockNoHandshake();
072        // NOTE: if threads are being removed, we may see a thread twice
073        if (t.requesting_osr) {
074          t.requesting_osr = false;
075          go = true;
076        }
077        t.monitor().unlock();
078        if (go) {
079          Controller.controllerInputQueue.insert(5.0, t.onStackReplacementEvent);
080        }
081      }
082    }
083  }
084}