1/*
2 * Copyright (c) 2017, 2019, 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_GC_SHARED_CONCURRENTGCPHASEMANAGER_HPP
26#define SHARE_GC_SHARED_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.
33class ConcurrentGCPhaseManager : public StackObj {
34public:
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 {
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 CollectedHeap::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
124private:
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 // SHARE_GC_SHARED_CONCURRENTGCPHASEMANAGER_HPP
138