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