hotspot/src/share/vm/gc/shared/concurrentGCPhaseManager.hpp
changeset 46384 dacebddcdea0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCPhaseManager.hpp	Thu Apr 13 16:38:39 2017 -0400
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_CONCURRENTGCPHASEMANAGER_HPP
+#define SHARE_VM_GC_CONCURRENTGCPHASEMANAGER_HPP
+
+#include "memory/allocation.hpp"
+
+// Manage concurrent phase information, to support WhiteBox testing.
+// Managers are stack allocated.  Managers may be nested, to support
+// nested subphases.
+class ConcurrentGCPhaseManager : public StackObj {
+public:
+
+  // Special phase ids used by all GC's that use this facility.
+  static const int UNCONSTRAINED_PHASE = 0; // Unconstrained or no request.
+  static const int IDLE_PHASE = 1;          // Concurrent processing is idle.
+
+  // Stack of phase managers.
+  class Stack VALUE_OBJ_CLASS_SPEC {
+    friend class ConcurrentGCPhaseManager;
+
+  public:
+    // Create an empty stack of phase managers.
+    Stack();
+
+  private:
+    int _requested_phase;
+    ConcurrentGCPhaseManager* _top;
+
+    // Non-copyable - never defined.
+    Stack(const Stack&);
+    Stack& operator=(const Stack&);
+  };
+
+  // Construct and push a new manager on the stack, activating phase.
+  // Notifies callers in wait_for_phase of the phase change.
+  //
+  // Preconditions:
+  // - Calling thread must be a ConcurrentGC thread
+  // - phase != UNCONSTRAINED_PHASE
+  // - stack != NULL
+  // - other managers on stack must all be active.
+  ConcurrentGCPhaseManager(int phase, Stack* stack);
+
+  // Pop this manager off the stack, deactivating phase.  Before
+  // changing phases, if is_requested() is true, wait until the
+  // request is changed.  After changing phases, notifies callers of
+  // wait_for_phase of the phase change.
+  //
+  // Preconditions:
+  // - Calling thread must be a ConcurrentGC thread
+  // - this must be the current top of the manager stack
+  ~ConcurrentGCPhaseManager();
+
+  // Returns true if this phase is active and is currently requested.
+  //
+  // Preconditions:
+  // - Calling thread must be a ConcurrentGC thread
+  // - this must be the current top of manager stack
+  bool is_requested() const;
+
+  // Wait until is_requested() is false.  Returns true if waited.
+  //
+  // Preconditions:
+  // - Calling thread must be a ConcurrentGC thread
+  // - this must be the current top of manager stack
+  bool wait_when_requested() const;
+
+  // Directly step from one phase to another, without needing to pop a
+  // manager from the stack and allocate a new one.  Before changing
+  // phases, if is_requested() is true and force is false, wait until
+  // the request is changed.  After changing phases, notifies callers
+  // of wait_for_phase of the phase change.
+  //
+  // Preconditions:
+  // - Calling thread must be a ConcurrentGC thread
+  // - phase != UNCONSTRAINED_PHASE
+  // - this must be the current top of manager stack
+  void set_phase(int phase, bool force);
+
+  // Deactivate the manager.  An inactive manager no longer blocks
+  // transitions out of the associated phase when that phase has been
+  // requested.
+  //
+  // Preconditions:
+  // - Calling thread must be a ConcurrentGC thread
+  // - this must be the current top of manager stack
+  void deactivate();
+
+  // Used to implement CollectorPolicy::request_concurrent_phase().
+  // Updates request to the new phase, and notifies threads blocked on
+  // the old request of the change.  Returns true if the phase is
+  // UNCONSTRAINED_PHASE.  Otherwise, waits until an active phase is
+  // the requested phase (returning true) or IDLE_PHASE (returning
+  // false if not also the requested phase).
+  //
+  // Preconditions:
+  // - Calling thread must be a Java thread
+  // - stack must be non-NULL
+  static bool wait_for_phase(int phase, Stack* stack);
+
+private:
+  int _phase;
+  bool _active;
+  ConcurrentGCPhaseManager* _prev;
+  Stack* _stack;
+
+  // Non-copyable - never defined.
+  ConcurrentGCPhaseManager(const ConcurrentGCPhaseManager&);
+  ConcurrentGCPhaseManager& operator=(const ConcurrentGCPhaseManager&);
+
+  bool wait_when_requested_impl() const;
+};
+
+#endif // include guard