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.jikesrvm.scheduler.SystemThread;
019    import org.vmmagic.pragma.Uninterruptible;
020    import 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
030    public 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    }