|
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 #include "precompiled.hpp" |
|
26 #include "gc/shared/concurrentGCPhaseManager.hpp" |
|
27 #include "runtime/mutexLocker.hpp" |
|
28 #include "runtime/thread.hpp" |
|
29 |
|
30 #define assert_ConcurrentGC_thread() \ |
|
31 assert(Thread::current()->is_ConcurrentGC_thread(), "precondition") |
|
32 |
|
33 #define assert_not_enter_unconstrained(phase) \ |
|
34 assert((phase) != UNCONSTRAINED_PHASE, "Cannot enter \"unconstrained\" phase") |
|
35 |
|
36 #define assert_manager_is_tos(manager, stack, kind) \ |
|
37 assert((manager) == (stack)->_top, kind " manager is not top of stack") |
|
38 |
|
39 ConcurrentGCPhaseManager::Stack::Stack() : |
|
40 _requested_phase(UNCONSTRAINED_PHASE), |
|
41 _top(NULL) |
|
42 { } |
|
43 |
|
44 ConcurrentGCPhaseManager::ConcurrentGCPhaseManager(int phase, Stack* stack) : |
|
45 _phase(phase), |
|
46 _active(true), |
|
47 _prev(NULL), |
|
48 _stack(stack) |
|
49 { |
|
50 assert_ConcurrentGC_thread(); |
|
51 assert_not_enter_unconstrained(phase); |
|
52 assert(stack != NULL, "precondition"); |
|
53 MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag); |
|
54 if (stack->_top != NULL) { |
|
55 assert(stack->_top->_active, "precondition"); |
|
56 _prev = stack->_top; |
|
57 } |
|
58 stack->_top = this; |
|
59 ml.notify_all(); |
|
60 } |
|
61 |
|
62 ConcurrentGCPhaseManager::~ConcurrentGCPhaseManager() { |
|
63 assert_ConcurrentGC_thread(); |
|
64 MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag); |
|
65 assert_manager_is_tos(this, _stack, "This"); |
|
66 wait_when_requested_impl(); |
|
67 _stack->_top = _prev; |
|
68 ml.notify_all(); |
|
69 } |
|
70 |
|
71 bool ConcurrentGCPhaseManager::is_requested() const { |
|
72 assert_ConcurrentGC_thread(); |
|
73 MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag); |
|
74 assert_manager_is_tos(this, _stack, "This"); |
|
75 return _active && (_stack->_requested_phase == _phase); |
|
76 } |
|
77 |
|
78 bool ConcurrentGCPhaseManager::wait_when_requested_impl() const { |
|
79 assert_ConcurrentGC_thread(); |
|
80 assert_lock_strong(CGCPhaseManager_lock); |
|
81 bool waited = false; |
|
82 while (_active && (_stack->_requested_phase == _phase)) { |
|
83 waited = true; |
|
84 CGCPhaseManager_lock->wait(Mutex::_no_safepoint_check_flag); |
|
85 } |
|
86 return waited; |
|
87 } |
|
88 |
|
89 bool ConcurrentGCPhaseManager::wait_when_requested() const { |
|
90 assert_ConcurrentGC_thread(); |
|
91 MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag); |
|
92 assert_manager_is_tos(this, _stack, "This"); |
|
93 return wait_when_requested_impl(); |
|
94 } |
|
95 |
|
96 void ConcurrentGCPhaseManager::set_phase(int phase, bool force) { |
|
97 assert_ConcurrentGC_thread(); |
|
98 assert_not_enter_unconstrained(phase); |
|
99 MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag); |
|
100 assert_manager_is_tos(this, _stack, "This"); |
|
101 if (!force) wait_when_requested_impl(); |
|
102 _phase = phase; |
|
103 ml.notify_all(); |
|
104 } |
|
105 |
|
106 void ConcurrentGCPhaseManager::deactivate() { |
|
107 assert_ConcurrentGC_thread(); |
|
108 MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag); |
|
109 assert_manager_is_tos(this, _stack, "This"); |
|
110 _active = false; |
|
111 ml.notify_all(); |
|
112 } |
|
113 |
|
114 bool ConcurrentGCPhaseManager::wait_for_phase(int phase, Stack* stack) { |
|
115 assert(Thread::current()->is_Java_thread(), "precondition"); |
|
116 assert(stack != NULL, "precondition"); |
|
117 MonitorLockerEx ml(CGCPhaseManager_lock); |
|
118 // Update request and notify service of change. |
|
119 if (stack->_requested_phase != phase) { |
|
120 stack->_requested_phase = phase; |
|
121 ml.notify_all(); |
|
122 } |
|
123 |
|
124 if (phase == UNCONSTRAINED_PHASE) { |
|
125 return true; |
|
126 } |
|
127 |
|
128 // Wait until phase or IDLE is active. |
|
129 while (true) { |
|
130 bool idle = false; |
|
131 for (ConcurrentGCPhaseManager* manager = stack->_top; |
|
132 manager != NULL; |
|
133 manager = manager->_prev) { |
|
134 if (manager->_phase == phase) { |
|
135 return true; // phase is active. |
|
136 } else if (manager->_phase == IDLE_PHASE) { |
|
137 idle = true; // Note idle active, continue search for phase. |
|
138 } |
|
139 } |
|
140 if (idle) { |
|
141 return false; // idle is active and phase is not. |
|
142 } else { |
|
143 ml.wait(); // Wait for phase change. |
|
144 } |
|
145 } |
|
146 } |