1 /*
   2  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
  26 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
  27 
  28 #ifndef SERIALGC
  29 #include "runtime/thread.hpp"
  30 #endif
  31 
  32 class VoidClosure;
  33 
  34 // A SuspendibleThreadSet is (obviously) a set of threads that can be
  35 // suspended.  A thread can join and later leave the set, and periodically
  36 // yield.  If some thread (not in the set) requests, via suspend_all, that
  37 // the threads be suspended, then the requesting thread is blocked until
  38 // all the threads in the set have yielded or left the set.  (Threads may
  39 // not enter the set when an attempted suspension is in progress.)  The
  40 // suspending thread later calls resume_all, allowing the suspended threads
  41 // to continue.
  42 
  43 class SuspendibleThreadSet {
  44   Monitor* _m;
  45   int      _async;
  46   bool     _async_stop;
  47   int      _async_stopped;
  48   bool     _initialized;
  49   double   _suspend_all_start;
  50 
  51   void initialize_work();
  52 
  53  public:
  54   SuspendibleThreadSet() : _initialized(false) {}
  55 
  56   // Add the current thread to the set.  May block if a suspension
  57   // is in progress.
  58   void join();
  59   // Removes the current thread from the set.
  60   void leave();
  61   // Returns "true" iff an suspension is in progress.
  62   bool should_yield() { return _async_stop; }
  63   // Suspends the current thread if a suspension is in progress (for
  64   // the duration of the suspension.)
  65   void yield(const char* id);
  66   // Return when all threads in the set are suspended.
  67   void suspend_all();
  68   // Allow suspended threads to resume.
  69   void resume_all();
  70   // Redundant initializations okay.
  71   void initialize() {
  72     // Double-check dirty read idiom.
  73     if (!_initialized) initialize_work();
  74   }
  75 };
  76 
  77 
  78 class ConcurrentGCThread: public NamedThread {
  79   friend class VMStructs;
  80 
  81 protected:
  82   bool _should_terminate;
  83   bool _has_terminated;
  84 
  85   enum CGC_flag_type {
  86     CGC_nil           = 0x0,
  87     CGC_dont_suspend  = 0x1,
  88     CGC_CGC_safepoint = 0x2,
  89     CGC_VM_safepoint  = 0x4
  90   };
  91 
  92   static int _CGC_flag;
  93 
  94   static bool CGC_flag_is_set(int b)       { return (_CGC_flag & b) != 0; }
  95   static int set_CGC_flag(int b)           { return _CGC_flag |= b; }
  96   static int reset_CGC_flag(int b)         { return _CGC_flag &= ~b; }
  97 
  98   void stopWorldAndDo(VoidClosure* op);
  99 
 100   // All instances share this one set.
 101   static SuspendibleThreadSet _sts;
 102 
 103   // Create and start the thread (setting it's priority high.)
 104   void create_and_start();
 105 
 106   // Do initialization steps in the thread: record stack base and size,
 107   // init thread local storage, set JNI handle block.
 108   void initialize_in_thread();
 109 
 110   // Wait until Universe::is_fully_initialized();
 111   void wait_for_universe_init();
 112 
 113   // Record that the current thread is terminating, and will do more
 114   // concurrent work.
 115   void terminate();
 116 
 117 public:
 118   // Constructor
 119 
 120   ConcurrentGCThread();
 121   ~ConcurrentGCThread() {} // Exists to call NamedThread destructor.
 122 
 123   // Tester
 124   bool is_ConcurrentGC_thread() const          { return true;       }
 125 
 126   static void safepoint_synchronize();
 127   static void safepoint_desynchronize();
 128 
 129   // All overridings should probably do _sts::yield, but we allow
 130   // overriding for distinguished debugging messages.  Default is to do
 131   // nothing.
 132   virtual void yield() {}
 133 
 134   bool should_yield() { return _sts.should_yield(); }
 135 
 136   // they are prefixed by sts since there are already yield() and
 137   // should_yield() (non-static) methods in this class and it was an
 138   // easy way to differentiate them.
 139   static void stsYield(const char* id);
 140   static bool stsShouldYield();
 141   static void stsJoin();
 142   static void stsLeave();
 143 
 144 };
 145 
 146 // The SurrogateLockerThread is used by concurrent GC threads for
 147 // manipulating Java monitors, in particular, currently for
 148 // manipulating the pending_list_lock. XXX
 149 class SurrogateLockerThread: public JavaThread {
 150   friend class VMStructs;
 151  public:
 152   enum SLT_msg_type {
 153     empty = 0,           // no message
 154     acquirePLL,          // acquire pending list lock
 155     releaseAndNotifyPLL  // notify and release pending list lock
 156   };
 157  private:
 158   // the following are shared with the CMSThread
 159   SLT_msg_type  _buffer;  // communication buffer
 160   Monitor       _monitor; // monitor controlling buffer
 161   BasicLock     _basicLock; // used for PLL locking
 162 
 163  public:
 164   static SurrogateLockerThread* make(TRAPS);
 165 
 166   SurrogateLockerThread();
 167 
 168   bool is_hidden_from_external_view() const     { return true; }
 169 
 170   void loop(); // main method
 171 
 172   void manipulatePLL(SLT_msg_type msg);
 173 
 174 };
 175 
 176 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP