1 /*
   2  * Copyright (c) 2017, 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_CONCURRENTGCPHASEMANAGER_HPP
  26 #define SHARE_VM_GC_CONCURRENTGCPHASEMANAGER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 
  30 // Manage concurrent phase information, to support WhiteBox testing.
  31 // Managers are stack allocated.  Managers may be nested, to support
  32 // nested subphases.
  33 class ConcurrentGCPhaseManager : public StackObj {
  34 public:
  35 
  36   // Special phase ids used by all GC's that use this facility.
  37   static const int UNCONSTRAINED_PHASE = 0; // Unconstrained or no request.
  38   static const int IDLE_PHASE = 1;          // Concurrent processing is idle.
  39 
  40   // Stack of phase managers.
  41   class Stack VALUE_OBJ_CLASS_SPEC {
  42     friend class ConcurrentGCPhaseManager;
  43 
  44   public:
  45     // Create an empty stack of phase managers.
  46     Stack();
  47 
  48   private:
  49     int _requested_phase;
  50     ConcurrentGCPhaseManager* _top;
  51 
  52     // Non-copyable - never defined.
  53     Stack(const Stack&);
  54     Stack& operator=(const Stack&);
  55   };
  56 
  57   // Construct and push a new manager on the stack, activating phase.
  58   // Notifies callers in wait_for_phase of the phase change.
  59   //
  60   // Preconditions:
  61   // - Calling thread must be a ConcurrentGC thread
  62   // - phase != UNCONSTRAINED_PHASE
  63   // - stack != NULL
  64   // - other managers on stack must all be active.
  65   ConcurrentGCPhaseManager(int phase, Stack* stack);
  66 
  67   // Pop this manager off the stack, deactivating phase.  Before
  68   // changing phases, if is_requested() is true, wait until the
  69   // request is changed.  After changing phases, notifies callers of
  70   // wait_for_phase of the phase change.
  71   //
  72   // Preconditions:
  73   // - Calling thread must be a ConcurrentGC thread
  74   // - this must be the current top of the manager stack
  75   ~ConcurrentGCPhaseManager();
  76 
  77   // Returns true if this phase is active and is currently requested.
  78   //
  79   // Preconditions:
  80   // - Calling thread must be a ConcurrentGC thread
  81   // - this must be the current top of manager stack
  82   bool is_requested() const;
  83 
  84   // Wait until is_requested() is false.  Returns true if waited.
  85   //
  86   // Preconditions:
  87   // - Calling thread must be a ConcurrentGC thread
  88   // - this must be the current top of manager stack
  89   bool wait_when_requested() const;
  90 
  91   // Directly step from one phase to another, without needing to pop a
  92   // manager from the stack and allocate a new one.  Before changing
  93   // phases, if is_requested() is true and force is false, wait until
  94   // the request is changed.  After changing phases, notifies callers
  95   // of wait_for_phase of the phase change.
  96   //
  97   // Preconditions:
  98   // - Calling thread must be a ConcurrentGC thread
  99   // - phase != UNCONSTRAINED_PHASE
 100   // - this must be the current top of manager stack
 101   void set_phase(int phase, bool force);
 102 
 103   // Deactivate the manager.  An inactive manager no longer blocks
 104   // transitions out of the associated phase when that phase has been
 105   // requested.
 106   //
 107   // Preconditions:
 108   // - Calling thread must be a ConcurrentGC thread
 109   // - this must be the current top of manager stack
 110   void deactivate();
 111 
 112   // Used to implement CollectorPolicy::request_concurrent_phase().
 113   // Updates request to the new phase, and notifies threads blocked on
 114   // the old request of the change.  Returns true if the phase is
 115   // UNCONSTRAINED_PHASE.  Otherwise, waits until an active phase is
 116   // the requested phase (returning true) or IDLE_PHASE (returning
 117   // false if not also the requested phase).
 118   //
 119   // Preconditions:
 120   // - Calling thread must be a Java thread
 121   // - stack must be non-NULL
 122   static bool wait_for_phase(int phase, Stack* stack);
 123 
 124 private:
 125   int _phase;
 126   bool _active;
 127   ConcurrentGCPhaseManager* _prev;
 128   Stack* _stack;
 129 
 130   // Non-copyable - never defined.
 131   ConcurrentGCPhaseManager(const ConcurrentGCPhaseManager&);
 132   ConcurrentGCPhaseManager& operator=(const ConcurrentGCPhaseManager&);
 133 
 134   bool wait_when_requested_impl() const;
 135 };
 136 
 137 #endif // include guard