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