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   int _phase;
  35   bool _active;
  36   int* _request;
  37   ConcurrentGCPhaseManager* _link;
  38   ConcurrentGCPhaseManager** _stack;
  39 
  40 public:
  41 
  42   // Special phase ids used by all GC's that use this facility.
  43   static const int UNCONSTRAINED_PHASE = 0; // Unconstrained or no request.
  44   static const int IDLE_PHASE = 1;          // Concurrent processing is idle.
  45 
  46   // Initialize stack with this object as the base, activating phase.
  47   // Notifies callers in wait_for_phase of the phase change.
  48   //
  49   // Preconditions:
  50   // - Calling thread must be a ConcurrentGC thread
  51   // - phase != UNCONSTRAINED_PHASE
  52   // - stack != NULL && *stack == NULL
  53   // - request != NULL
  54   ConcurrentGCPhaseManager(int phase,
  55                            ConcurrentGCPhaseManager** stack,
  56                            int* request);
  57 
  58   // Push this manager on the stack topped by prev, activating phase.
  59   // Notifies callers in wait_for_phase of the phase change.
  60   //
  61   // Preconditions:
  62   // - Calling thread must be a ConcurrentGC thread
  63   // - phase != UNCONSTRAINED_PHASE
  64   // - prev must be the current top of manager stack
  65   // - prev must not have been deactivated
  66   ConcurrentGCPhaseManager(int phase, ConcurrentGCPhaseManager* prev);
  67 
  68   // Pop this manager off the stack, deactivating phase.  Before
  69   // changing phases, if is_requested() is true, wait until the
  70   // request is changed.  After changing phases, notifies callers of
  71   // wait_for_phase of the phase change.
  72   //
  73   // Preconditions:
  74   // - Calling thread must be a ConcurrentGC thread
  75   // - this must be the current top of the manager stack
  76   ~ConcurrentGCPhaseManager();
  77 
  78   // Returns true if this phase is active and is currently requested.
  79   //
  80   // Preconditions:
  81   // - Calling thread must be a ConcurrentGC thread
  82   // - this must be the current top of manager stack
  83   bool is_requested() const;
  84 
  85   // Wait until is_requested() is false.  Returns true if waited.
  86   //
  87   // Preconditions:
  88   // - Calling thread must be a ConcurrentGC thread
  89   // - this must be the current top of manager stack
  90   bool wait_when_requested() const;
  91 
  92   // Directly step from one phase to another, without needing to pop a
  93   // manager from the stack and allocate a new one.  Before changing
  94   // phases, if is_requested() is true and force is false, wait until
  95   // the request is changed.  After changing phases, notifies callers
  96   // of wait_for_phase of the phase change.
  97   //
  98   // Preconditions:
  99   // - Calling thread must be a ConcurrentGC thread
 100   // - phase != UNCONSTRAINED_PHASE
 101   // - this must be the current top of manager stack
 102   void set_phase(int phase, bool force);
 103 
 104   // Deactivate the manager.  An inactive manager no longer blocks
 105   // transitions out of the associated phase when that phase has been
 106   // requested.
 107   //
 108   // Preconditions:
 109   // - Calling thread must be a ConcurrentGC thread
 110   // - this must be the current top of manager stack
 111   void deactivate();
 112 
 113   // Used to implement CollectorPolicy::request_concurrent_phase().
 114   // Updates request to the new phase, and notifies threads blocked on
 115   // the old request of the change.  Returns true if the phase is
 116   // UNCONSTRAINED_PHASE.  Otherwise, waits until an active phase is
 117   // the requested phase (returning true) or IDLE_PHASE (returning
 118   // false if not also the requested phase).
 119   //
 120   // Preconditions:
 121   // - Calling thread must be a Java thread
 122   static bool wait_for_phase(int phase,
 123                              ConcurrentGCPhaseManager** stack,
 124                              int* request);
 125 
 126 private:
 127   // Non-copyable - never defined.
 128   ConcurrentGCPhaseManager(const ConcurrentGCPhaseManager&);
 129   ConcurrentGCPhaseManager& operator=(const ConcurrentGCPhaseManager&);
 130 
 131   bool wait_when_requested_impl() const;
 132 };
 133 
 134 #endif // include guard