annotate src/share/vm/runtime/vmThread.cpp @ 94:0834225a7916

6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction Summary: The option CMSInitiatingPermOccupancyFraction now controls perm triggering threshold. Even though the actual value of the threshold has not yet been changed, so there is no change in policy, we now have the infrastructure in place for dynamically deciding when to collect the perm gen, an issue that will be addressed in the near future. Reviewed-by: jmasa
author ysr
date Sun, 16 Mar 2008 21:57:25 -0700
parents a61af66fc99e
children 821269eca479
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_vmThread.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 // Dummy VM operation to act as first element in our circular double-linked list
a61af66fc99e Initial load
duke
parents:
diff changeset
29 class VM_Dummy: public VM_Operation {
a61af66fc99e Initial load
duke
parents:
diff changeset
30 VMOp_Type type() const { return VMOp_Dummy; }
a61af66fc99e Initial load
duke
parents:
diff changeset
31 void doit() {};
a61af66fc99e Initial load
duke
parents:
diff changeset
32 };
a61af66fc99e Initial load
duke
parents:
diff changeset
33
a61af66fc99e Initial load
duke
parents:
diff changeset
34 VMOperationQueue::VMOperationQueue() {
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // The queue is a circular doubled-linked list, which always contains
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // one element (i.e., one element means empty).
a61af66fc99e Initial load
duke
parents:
diff changeset
37 for(int i = 0; i < nof_priorities; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
38 _queue_length[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
39 _queue_counter = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
40 _queue[i] = new VM_Dummy();
a61af66fc99e Initial load
duke
parents:
diff changeset
41 _queue[i]->set_next(_queue[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
42 _queue[i]->set_prev(_queue[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
43 }
a61af66fc99e Initial load
duke
parents:
diff changeset
44 _drain_list = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
45 }
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 bool VMOperationQueue::queue_empty(int prio) {
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // It is empty if there is exactly one element
a61af66fc99e Initial load
duke
parents:
diff changeset
50 bool empty = (_queue[prio] == _queue[prio]->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
51 assert( (_queue_length[prio] == 0 && empty) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
52 (_queue_length[prio] > 0 && !empty), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
53 return _queue_length[prio] == 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
54 }
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // Inserts an element to the right of the q element
a61af66fc99e Initial load
duke
parents:
diff changeset
57 void VMOperationQueue::insert(VM_Operation* q, VM_Operation* n) {
a61af66fc99e Initial load
duke
parents:
diff changeset
58 assert(q->next()->prev() == q && q->prev()->next() == q, "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
59 n->set_prev(q);
a61af66fc99e Initial load
duke
parents:
diff changeset
60 n->set_next(q->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
61 q->next()->set_prev(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
62 q->set_next(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
63 }
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 void VMOperationQueue::queue_add_front(int prio, VM_Operation *op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 _queue_length[prio]++;
a61af66fc99e Initial load
duke
parents:
diff changeset
67 insert(_queue[prio]->next(), op);
a61af66fc99e Initial load
duke
parents:
diff changeset
68 }
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 void VMOperationQueue::queue_add_back(int prio, VM_Operation *op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
71 _queue_length[prio]++;
a61af66fc99e Initial load
duke
parents:
diff changeset
72 insert(_queue[prio]->prev(), op);
a61af66fc99e Initial load
duke
parents:
diff changeset
73 }
a61af66fc99e Initial load
duke
parents:
diff changeset
74
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 void VMOperationQueue::unlink(VM_Operation* q) {
a61af66fc99e Initial load
duke
parents:
diff changeset
77 assert(q->next()->prev() == q && q->prev()->next() == q, "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
78 q->prev()->set_next(q->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
79 q->next()->set_prev(q->prev());
a61af66fc99e Initial load
duke
parents:
diff changeset
80 }
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 VM_Operation* VMOperationQueue::queue_remove_front(int prio) {
a61af66fc99e Initial load
duke
parents:
diff changeset
83 if (queue_empty(prio)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
84 assert(_queue_length[prio] >= 0, "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
85 _queue_length[prio]--;
a61af66fc99e Initial load
duke
parents:
diff changeset
86 VM_Operation* r = _queue[prio]->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
87 assert(r != _queue[prio], "cannot remove base element");
a61af66fc99e Initial load
duke
parents:
diff changeset
88 unlink(r);
a61af66fc99e Initial load
duke
parents:
diff changeset
89 return r;
a61af66fc99e Initial load
duke
parents:
diff changeset
90 }
a61af66fc99e Initial load
duke
parents:
diff changeset
91
a61af66fc99e Initial load
duke
parents:
diff changeset
92 VM_Operation* VMOperationQueue::queue_drain(int prio) {
a61af66fc99e Initial load
duke
parents:
diff changeset
93 if (queue_empty(prio)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 DEBUG_ONLY(int length = _queue_length[prio];);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 assert(length >= 0, "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
96 _queue_length[prio] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
97 VM_Operation* r = _queue[prio]->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
98 assert(r != _queue[prio], "cannot remove base element");
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // remove links to base element from head and tail
a61af66fc99e Initial load
duke
parents:
diff changeset
100 r->set_prev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
101 _queue[prio]->prev()->set_next(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // restore queue to empty state
a61af66fc99e Initial load
duke
parents:
diff changeset
103 _queue[prio]->set_next(_queue[prio]);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 _queue[prio]->set_prev(_queue[prio]);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 assert(queue_empty(prio), "drain corrupted queue")
a61af66fc99e Initial load
duke
parents:
diff changeset
106 #ifdef DEBUG
a61af66fc99e Initial load
duke
parents:
diff changeset
107 int len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
108 VM_Operation* cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
109 for(cur = r; cur != NULL; cur=cur->next()) len++;
a61af66fc99e Initial load
duke
parents:
diff changeset
110 assert(len == length, "drain lost some ops");
a61af66fc99e Initial load
duke
parents:
diff changeset
111 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
112 return r;
a61af66fc99e Initial load
duke
parents:
diff changeset
113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
114
a61af66fc99e Initial load
duke
parents:
diff changeset
115 void VMOperationQueue::queue_oops_do(int queue, OopClosure* f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
116 VM_Operation* cur = _queue[queue];
a61af66fc99e Initial load
duke
parents:
diff changeset
117 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
118 while (cur != _queue[queue]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
119 cur->oops_do(f);
a61af66fc99e Initial load
duke
parents:
diff changeset
120 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 void VMOperationQueue::drain_list_oops_do(OopClosure* f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 VM_Operation* cur = _drain_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
126 while (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
127 cur->oops_do(f);
a61af66fc99e Initial load
duke
parents:
diff changeset
128 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131
a61af66fc99e Initial load
duke
parents:
diff changeset
132 //-----------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // High-level interface
a61af66fc99e Initial load
duke
parents:
diff changeset
134 bool VMOperationQueue::add(VM_Operation *op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // Encapsulates VM queue policy. Currently, that
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // only involves putting them on the right list
a61af66fc99e Initial load
duke
parents:
diff changeset
137 if (op->evaluate_at_safepoint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 queue_add_back(SafepointPriority, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
139 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 queue_add_back(MediumPriority, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
143 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
144 }
a61af66fc99e Initial load
duke
parents:
diff changeset
145
a61af66fc99e Initial load
duke
parents:
diff changeset
146 VM_Operation* VMOperationQueue::remove_next() {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // Assuming VMOperation queue is two-level priority queue. If there are
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // more than two priorities, we need a different scheduling algorithm.
a61af66fc99e Initial load
duke
parents:
diff changeset
149 assert(SafepointPriority == 0 && MediumPriority == 1 && nof_priorities == 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
150 "current algorithm does not work");
a61af66fc99e Initial load
duke
parents:
diff changeset
151
a61af66fc99e Initial load
duke
parents:
diff changeset
152 // simple counter based scheduling to prevent starvation of lower priority
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // queue. -- see 4390175
a61af66fc99e Initial load
duke
parents:
diff changeset
154 int high_prio, low_prio;
a61af66fc99e Initial load
duke
parents:
diff changeset
155 if (_queue_counter++ < 10) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 high_prio = SafepointPriority;
a61af66fc99e Initial load
duke
parents:
diff changeset
157 low_prio = MediumPriority;
a61af66fc99e Initial load
duke
parents:
diff changeset
158 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 _queue_counter = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
160 high_prio = MediumPriority;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 low_prio = SafepointPriority;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
163
a61af66fc99e Initial load
duke
parents:
diff changeset
164 return queue_remove_front(queue_empty(high_prio) ? low_prio : high_prio);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 void VMOperationQueue::oops_do(OopClosure* f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 for(int i = 0; i < nof_priorities; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 queue_oops_do(i, f);
a61af66fc99e Initial load
duke
parents:
diff changeset
170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
171 drain_list_oops_do(f);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
173
a61af66fc99e Initial load
duke
parents:
diff changeset
174
a61af66fc99e Initial load
duke
parents:
diff changeset
175 //------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // Implementation of VMThread stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
177
a61af66fc99e Initial load
duke
parents:
diff changeset
178 bool VMThread::_should_terminate = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 bool VMThread::_terminated = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
180 Monitor* VMThread::_terminate_lock = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
181 VMThread* VMThread::_vm_thread = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 VM_Operation* VMThread::_cur_vm_operation = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 VMOperationQueue* VMThread::_vm_queue = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
184 PerfCounter* VMThread::_perf_accumulated_vm_operation_time = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
185
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 void VMThread::create() {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 assert(vm_thread() == NULL, "we can only allocate one VMThread");
a61af66fc99e Initial load
duke
parents:
diff changeset
189 _vm_thread = new VMThread();
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 // Create VM operation queue
a61af66fc99e Initial load
duke
parents:
diff changeset
192 _vm_queue = new VMOperationQueue();
a61af66fc99e Initial load
duke
parents:
diff changeset
193 guarantee(_vm_queue != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 _terminate_lock = new Monitor(Mutex::safepoint, "VMThread::_terminate_lock", true);
a61af66fc99e Initial load
duke
parents:
diff changeset
196
a61af66fc99e Initial load
duke
parents:
diff changeset
197 if (UsePerfData) {
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // jvmstat performance counters
a61af66fc99e Initial load
duke
parents:
diff changeset
199 Thread* THREAD = Thread::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
200 _perf_accumulated_vm_operation_time =
a61af66fc99e Initial load
duke
parents:
diff changeset
201 PerfDataManager::create_counter(SUN_THREADS, "vmOperationTime",
a61af66fc99e Initial load
duke
parents:
diff changeset
202 PerfData::U_Ticks, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
205
a61af66fc99e Initial load
duke
parents:
diff changeset
206
a61af66fc99e Initial load
duke
parents:
diff changeset
207 VMThread::VMThread() : Thread() {
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
210
a61af66fc99e Initial load
duke
parents:
diff changeset
211 void VMThread::destroy() {
a61af66fc99e Initial load
duke
parents:
diff changeset
212 if (_vm_thread != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
213 delete _vm_thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 _vm_thread = NULL; // VM thread is gone
a61af66fc99e Initial load
duke
parents:
diff changeset
215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
217
a61af66fc99e Initial load
duke
parents:
diff changeset
218 void VMThread::run() {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 assert(this == vm_thread(), "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221 this->initialize_thread_local_storage();
a61af66fc99e Initial load
duke
parents:
diff changeset
222 this->record_stack_base_and_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // Notify_lock wait checks on active_handles() to rewait in
a61af66fc99e Initial load
duke
parents:
diff changeset
224 // case of spurious wakeup, it should wait on the last
a61af66fc99e Initial load
duke
parents:
diff changeset
225 // value set prior to the notify
a61af66fc99e Initial load
duke
parents:
diff changeset
226 this->set_active_handles(JNIHandleBlock::allocate_block());
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 {
a61af66fc99e Initial load
duke
parents:
diff changeset
229 MutexLocker ml(Notify_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
230 Notify_lock->notify();
a61af66fc99e Initial load
duke
parents:
diff changeset
231 }
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // Notify_lock is destroyed by Threads::create_vm()
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 int prio = (VMThreadPriority == -1)
a61af66fc99e Initial load
duke
parents:
diff changeset
235 ? os::java_to_os_priority[NearMaxPriority]
a61af66fc99e Initial load
duke
parents:
diff changeset
236 : VMThreadPriority;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // Note that I cannot call os::set_priority because it expects Java
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // priorities and I am *explicitly* using OS priorities so that it's
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // possible to set the VM thread priority higher than any Java thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
240 os::set_native_priority( this, prio );
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // Wait for VM_Operations until termination
a61af66fc99e Initial load
duke
parents:
diff changeset
243 this->loop();
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // Note the intention to exit before safepointing.
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // 6295565 This has the effect of waiting for any large tty
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // outputs to finish.
a61af66fc99e Initial load
duke
parents:
diff changeset
248 if (xtty != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
249 ttyLocker ttyl;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 xtty->begin_elem("destroy_vm");
a61af66fc99e Initial load
duke
parents:
diff changeset
251 xtty->stamp();
a61af66fc99e Initial load
duke
parents:
diff changeset
252 xtty->end_elem();
a61af66fc99e Initial load
duke
parents:
diff changeset
253 assert(should_terminate(), "termination flag must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
255
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // 4526887 let VM thread exit at Safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
257 SafepointSynchronize::begin();
a61af66fc99e Initial load
duke
parents:
diff changeset
258
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if (VerifyBeforeExit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 HandleMark hm(VMThread::vm_thread());
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // Among other things, this ensures that Eden top is correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
262 Universe::heap()->prepare_for_verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
263 os::check_heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
264 Universe::verify(true, true); // Silent verification to not polute normal output
a61af66fc99e Initial load
duke
parents:
diff changeset
265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
266
a61af66fc99e Initial load
duke
parents:
diff changeset
267 CompileBroker::set_should_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
268
a61af66fc99e Initial load
duke
parents:
diff changeset
269 // wait for threads (compiler threads or daemon threads) in the
a61af66fc99e Initial load
duke
parents:
diff changeset
270 // _thread_in_native state to block.
a61af66fc99e Initial load
duke
parents:
diff changeset
271 VM_Exit::wait_for_threads_in_native_to_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
272
a61af66fc99e Initial load
duke
parents:
diff changeset
273 // signal other threads that VM process is gone
a61af66fc99e Initial load
duke
parents:
diff changeset
274 {
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // Note: we must have the _no_safepoint_check_flag. Mutex::lock() allows
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // VM thread to enter any lock at Safepoint as long as its _owner is NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // If that happens after _terminate_lock->wait() has unset _owner
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // but before it actually drops the lock and waits, the notification below
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // may get lost and we will have a hang. To avoid this, we need to use
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // Mutex::lock_without_safepoint_check().
a61af66fc99e Initial load
duke
parents:
diff changeset
281 MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
282 _terminated = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
283 _terminate_lock->notify();
a61af66fc99e Initial load
duke
parents:
diff changeset
284 }
a61af66fc99e Initial load
duke
parents:
diff changeset
285
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // Deletion must be done synchronously by the JNI DestroyJavaVM thread
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // so that the VMThread deletion completes before the main thread frees
a61af66fc99e Initial load
duke
parents:
diff changeset
288 // up the CodeHeap.
a61af66fc99e Initial load
duke
parents:
diff changeset
289
a61af66fc99e Initial load
duke
parents:
diff changeset
290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // Notify the VMThread that the last non-daemon JavaThread has terminated,
a61af66fc99e Initial load
duke
parents:
diff changeset
294 // and wait until operation is performed.
a61af66fc99e Initial load
duke
parents:
diff changeset
295 void VMThread::wait_for_vm_thread_exit() {
a61af66fc99e Initial load
duke
parents:
diff changeset
296 { MutexLocker mu(VMOperationQueue_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
297 _should_terminate = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
298 VMOperationQueue_lock->notify();
a61af66fc99e Initial load
duke
parents:
diff changeset
299 }
a61af66fc99e Initial load
duke
parents:
diff changeset
300
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // Note: VM thread leaves at Safepoint. We are not stopped by Safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // because this thread has been removed from the threads list. But anything
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // that could get blocked by Safepoint should not be used after this point,
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // otherwise we will hang, since there is no one can end the safepoint.
a61af66fc99e Initial load
duke
parents:
diff changeset
305
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // Wait until VM thread is terminated
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // Note: it should be OK to use Terminator_lock here. But this is called
a61af66fc99e Initial load
duke
parents:
diff changeset
308 // at a very delicate time (VM shutdown) and we are operating in non- VM
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // thread at Safepoint. It's safer to not share lock with other threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
310 { MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
311 while(!VMThread::is_terminated()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
312 _terminate_lock->wait(Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
316
a61af66fc99e Initial load
duke
parents:
diff changeset
317 void VMThread::print_on(outputStream* st) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 st->print("\"%s\" ", name());
a61af66fc99e Initial load
duke
parents:
diff changeset
319 Thread::print_on(st);
a61af66fc99e Initial load
duke
parents:
diff changeset
320 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
321 }
a61af66fc99e Initial load
duke
parents:
diff changeset
322
a61af66fc99e Initial load
duke
parents:
diff changeset
323 void VMThread::evaluate_operation(VM_Operation* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
324 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
325
a61af66fc99e Initial load
duke
parents:
diff changeset
326 {
a61af66fc99e Initial load
duke
parents:
diff changeset
327 PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time());
a61af66fc99e Initial load
duke
parents:
diff changeset
328 op->evaluate();
a61af66fc99e Initial load
duke
parents:
diff changeset
329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // Last access of info in _cur_vm_operation!
a61af66fc99e Initial load
duke
parents:
diff changeset
332 bool c_heap_allocated = op->is_cheap_allocated();
a61af66fc99e Initial load
duke
parents:
diff changeset
333
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // Mark as completed
a61af66fc99e Initial load
duke
parents:
diff changeset
335 if (!op->evaluate_concurrently()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
336 op->calling_thread()->increment_vm_operation_completed_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
338 // It is unsafe to access the _cur_vm_operation after the 'increment_vm_operation_completed_count' call,
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // since if it is stack allocated the calling thread might have deallocated
a61af66fc99e Initial load
duke
parents:
diff changeset
340 if (c_heap_allocated) {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 delete _cur_vm_operation;
a61af66fc99e Initial load
duke
parents:
diff changeset
342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
344
a61af66fc99e Initial load
duke
parents:
diff changeset
345
a61af66fc99e Initial load
duke
parents:
diff changeset
346 void VMThread::loop() {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 assert(_cur_vm_operation == NULL, "no current one should be executing");
a61af66fc99e Initial load
duke
parents:
diff changeset
348
a61af66fc99e Initial load
duke
parents:
diff changeset
349 while(true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 VM_Operation* safepoint_ops = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
351 //
a61af66fc99e Initial load
duke
parents:
diff changeset
352 // Wait for VM operation
a61af66fc99e Initial load
duke
parents:
diff changeset
353 //
a61af66fc99e Initial load
duke
parents:
diff changeset
354 // use no_safepoint_check to get lock without attempting to "sneak"
a61af66fc99e Initial load
duke
parents:
diff changeset
355 { MutexLockerEx mu_queue(VMOperationQueue_lock,
a61af66fc99e Initial load
duke
parents:
diff changeset
356 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
357
a61af66fc99e Initial load
duke
parents:
diff changeset
358 // Look for new operation
a61af66fc99e Initial load
duke
parents:
diff changeset
359 assert(_cur_vm_operation == NULL, "no current one should be executing");
a61af66fc99e Initial load
duke
parents:
diff changeset
360 _cur_vm_operation = _vm_queue->remove_next();
a61af66fc99e Initial load
duke
parents:
diff changeset
361
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // Stall time tracking code
a61af66fc99e Initial load
duke
parents:
diff changeset
363 if (PrintVMQWaitTime && _cur_vm_operation != NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
364 !_cur_vm_operation->evaluate_concurrently()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
365 long stall = os::javaTimeMillis() - _cur_vm_operation->timestamp();
a61af66fc99e Initial load
duke
parents:
diff changeset
366 if (stall > 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
367 tty->print_cr("%s stall: %Ld", _cur_vm_operation->name(), stall);
a61af66fc99e Initial load
duke
parents:
diff changeset
368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
369
a61af66fc99e Initial load
duke
parents:
diff changeset
370 while (!should_terminate() && _cur_vm_operation == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
371 // wait with a timeout to guarantee safepoints at regular intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
372 bool timedout =
a61af66fc99e Initial load
duke
parents:
diff changeset
373 VMOperationQueue_lock->wait(Mutex::_no_safepoint_check_flag,
a61af66fc99e Initial load
duke
parents:
diff changeset
374 GuaranteedSafepointInterval);
a61af66fc99e Initial load
duke
parents:
diff changeset
375
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // Support for self destruction
a61af66fc99e Initial load
duke
parents:
diff changeset
377 if ((SelfDestructTimer != 0) && !is_error_reported() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
378 (os::elapsedTime() > SelfDestructTimer * 60)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
379 tty->print_cr("VM self-destructed");
a61af66fc99e Initial load
duke
parents:
diff changeset
380 exit(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382
a61af66fc99e Initial load
duke
parents:
diff changeset
383 if (timedout && (SafepointALot ||
a61af66fc99e Initial load
duke
parents:
diff changeset
384 SafepointSynchronize::is_cleanup_needed())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
385 MutexUnlockerEx mul(VMOperationQueue_lock,
a61af66fc99e Initial load
duke
parents:
diff changeset
386 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
387 // Force a safepoint since we have not had one for at least
a61af66fc99e Initial load
duke
parents:
diff changeset
388 // 'GuaranteedSafepointInterval' milliseconds. This will run all
a61af66fc99e Initial load
duke
parents:
diff changeset
389 // the clean-up processing that needs to be done regularly at a
a61af66fc99e Initial load
duke
parents:
diff changeset
390 // safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
391 SafepointSynchronize::begin();
a61af66fc99e Initial load
duke
parents:
diff changeset
392 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
393 if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
a61af66fc99e Initial load
duke
parents:
diff changeset
394 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
395 SafepointSynchronize::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
397 _cur_vm_operation = _vm_queue->remove_next();
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // If we are at a safepoint we will evaluate all the operations that
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // follow that also require a safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
401 if (_cur_vm_operation != NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
402 _cur_vm_operation->evaluate_at_safepoint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
403 safepoint_ops = _vm_queue->drain_at_safepoint_priority();
a61af66fc99e Initial load
duke
parents:
diff changeset
404 }
a61af66fc99e Initial load
duke
parents:
diff changeset
405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
406
a61af66fc99e Initial load
duke
parents:
diff changeset
407 if (should_terminate()) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
408 } // Release mu_queue_lock
a61af66fc99e Initial load
duke
parents:
diff changeset
409
a61af66fc99e Initial load
duke
parents:
diff changeset
410 //
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // Execute VM operation
a61af66fc99e Initial load
duke
parents:
diff changeset
412 //
a61af66fc99e Initial load
duke
parents:
diff changeset
413 { HandleMark hm(VMThread::vm_thread());
a61af66fc99e Initial load
duke
parents:
diff changeset
414
a61af66fc99e Initial load
duke
parents:
diff changeset
415 EventMark em("Executing VM operation: %s", vm_operation()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
416 assert(_cur_vm_operation != NULL, "we should have found an operation to execute");
a61af66fc99e Initial load
duke
parents:
diff changeset
417
a61af66fc99e Initial load
duke
parents:
diff changeset
418 // Give the VM thread an extra quantum. Jobs tend to be bursty and this
a61af66fc99e Initial load
duke
parents:
diff changeset
419 // helps the VM thread to finish up the job.
a61af66fc99e Initial load
duke
parents:
diff changeset
420 // FIXME: When this is enabled and there are many threads, this can degrade
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // performance significantly.
a61af66fc99e Initial load
duke
parents:
diff changeset
422 if( VMThreadHintNoPreempt )
a61af66fc99e Initial load
duke
parents:
diff changeset
423 os::hint_no_preempt();
a61af66fc99e Initial load
duke
parents:
diff changeset
424
a61af66fc99e Initial load
duke
parents:
diff changeset
425 // If we are at a safepoint we will evaluate all the operations that
a61af66fc99e Initial load
duke
parents:
diff changeset
426 // follow that also require a safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
427 if (_cur_vm_operation->evaluate_at_safepoint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 if (PrintGCApplicationConcurrentTime) {
a61af66fc99e Initial load
duke
parents:
diff changeset
430 gclog_or_tty->print_cr("Application time: %3.7f seconds",
a61af66fc99e Initial load
duke
parents:
diff changeset
431 RuntimeService::last_application_time_sec());
a61af66fc99e Initial load
duke
parents:
diff changeset
432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
433
a61af66fc99e Initial load
duke
parents:
diff changeset
434 _vm_queue->set_drain_list(safepoint_ops); // ensure ops can be scanned
a61af66fc99e Initial load
duke
parents:
diff changeset
435
a61af66fc99e Initial load
duke
parents:
diff changeset
436 SafepointSynchronize::begin();
a61af66fc99e Initial load
duke
parents:
diff changeset
437 evaluate_operation(_cur_vm_operation);
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // now process all queued safepoint ops, iteratively draining
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // the queue until there are none left
a61af66fc99e Initial load
duke
parents:
diff changeset
440 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
441 _cur_vm_operation = safepoint_ops;
a61af66fc99e Initial load
duke
parents:
diff changeset
442 if (_cur_vm_operation != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
443 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // evaluate_operation deletes the op object so we have
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // to grab the next op now
a61af66fc99e Initial load
duke
parents:
diff changeset
446 VM_Operation* next = _cur_vm_operation->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
447 _vm_queue->set_drain_list(next);
a61af66fc99e Initial load
duke
parents:
diff changeset
448 evaluate_operation(_cur_vm_operation);
a61af66fc99e Initial load
duke
parents:
diff changeset
449 _cur_vm_operation = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
450 if (PrintSafepointStatistics) {
a61af66fc99e Initial load
duke
parents:
diff changeset
451 SafepointSynchronize::inc_vmop_coalesced_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
453 } while (_cur_vm_operation != NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // There is a chance that a thread enqueued a safepoint op
a61af66fc99e Initial load
duke
parents:
diff changeset
456 // since we released the op-queue lock and initiated the safepoint.
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // So we drain the queue again if there is anything there, as an
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // optimization to try and reduce the number of safepoints.
a61af66fc99e Initial load
duke
parents:
diff changeset
459 // As the safepoint synchronizes us with JavaThreads we will see
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // any enqueue made by a JavaThread, but the peek will not
a61af66fc99e Initial load
duke
parents:
diff changeset
461 // necessarily detect a concurrent enqueue by a GC thread, but
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // that simply means the op will wait for the next major cycle of the
a61af66fc99e Initial load
duke
parents:
diff changeset
463 // VMThread - just as it would if the GC thread lost the race for
a61af66fc99e Initial load
duke
parents:
diff changeset
464 // the lock.
a61af66fc99e Initial load
duke
parents:
diff changeset
465 if (_vm_queue->peek_at_safepoint_priority()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
466 // must hold lock while draining queue
a61af66fc99e Initial load
duke
parents:
diff changeset
467 MutexLockerEx mu_queue(VMOperationQueue_lock,
a61af66fc99e Initial load
duke
parents:
diff changeset
468 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
469 safepoint_ops = _vm_queue->drain_at_safepoint_priority();
a61af66fc99e Initial load
duke
parents:
diff changeset
470 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
471 safepoint_ops = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
473 } while(safepoint_ops != NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
474
a61af66fc99e Initial load
duke
parents:
diff changeset
475 _vm_queue->set_drain_list(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
476
a61af66fc99e Initial load
duke
parents:
diff changeset
477 // Complete safepoint synchronization
a61af66fc99e Initial load
duke
parents:
diff changeset
478 SafepointSynchronize::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
479
a61af66fc99e Initial load
duke
parents:
diff changeset
480 if (PrintGCApplicationStoppedTime) {
a61af66fc99e Initial load
duke
parents:
diff changeset
481 gclog_or_tty->print_cr("Total time for which application threads "
a61af66fc99e Initial load
duke
parents:
diff changeset
482 "were stopped: %3.7f seconds",
a61af66fc99e Initial load
duke
parents:
diff changeset
483 RuntimeService::last_safepoint_time_sec());
a61af66fc99e Initial load
duke
parents:
diff changeset
484 }
a61af66fc99e Initial load
duke
parents:
diff changeset
485
a61af66fc99e Initial load
duke
parents:
diff changeset
486 } else { // not a safepoint operation
a61af66fc99e Initial load
duke
parents:
diff changeset
487 if (TraceLongCompiles) {
a61af66fc99e Initial load
duke
parents:
diff changeset
488 elapsedTimer t;
a61af66fc99e Initial load
duke
parents:
diff changeset
489 t.start();
a61af66fc99e Initial load
duke
parents:
diff changeset
490 evaluate_operation(_cur_vm_operation);
a61af66fc99e Initial load
duke
parents:
diff changeset
491 t.stop();
a61af66fc99e Initial load
duke
parents:
diff changeset
492 double secs = t.seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
493 if (secs * 1e3 > LongCompileThreshold) {
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // XXX - _cur_vm_operation should not be accessed after
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // the completed count has been incremented; the waiting
a61af66fc99e Initial load
duke
parents:
diff changeset
496 // thread may have already freed this memory.
a61af66fc99e Initial load
duke
parents:
diff changeset
497 tty->print_cr("vm %s: %3.7f secs]", _cur_vm_operation->name(), secs);
a61af66fc99e Initial load
duke
parents:
diff changeset
498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
499 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
500 evaluate_operation(_cur_vm_operation);
a61af66fc99e Initial load
duke
parents:
diff changeset
501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
502
a61af66fc99e Initial load
duke
parents:
diff changeset
503 _cur_vm_operation = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
504 }
a61af66fc99e Initial load
duke
parents:
diff changeset
505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
506
a61af66fc99e Initial load
duke
parents:
diff changeset
507 //
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // Notify (potential) waiting Java thread(s) - lock without safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
509 // check so that sneaking is not possible
a61af66fc99e Initial load
duke
parents:
diff changeset
510 { MutexLockerEx mu(VMOperationRequest_lock,
a61af66fc99e Initial load
duke
parents:
diff changeset
511 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
512 VMOperationRequest_lock->notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
513 }
a61af66fc99e Initial load
duke
parents:
diff changeset
514
a61af66fc99e Initial load
duke
parents:
diff changeset
515 //
a61af66fc99e Initial load
duke
parents:
diff changeset
516 // We want to make sure that we get to a safepoint regularly.
a61af66fc99e Initial load
duke
parents:
diff changeset
517 //
a61af66fc99e Initial load
duke
parents:
diff changeset
518 if (SafepointALot || SafepointSynchronize::is_cleanup_needed()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
519 long interval = SafepointSynchronize::last_non_safepoint_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
520 bool max_time_exceeded = GuaranteedSafepointInterval != 0 && (interval > GuaranteedSafepointInterval);
a61af66fc99e Initial load
duke
parents:
diff changeset
521 if (SafepointALot || max_time_exceeded) {
a61af66fc99e Initial load
duke
parents:
diff changeset
522 HandleMark hm(VMThread::vm_thread());
a61af66fc99e Initial load
duke
parents:
diff changeset
523 SafepointSynchronize::begin();
a61af66fc99e Initial load
duke
parents:
diff changeset
524 SafepointSynchronize::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
526 }
a61af66fc99e Initial load
duke
parents:
diff changeset
527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
528 }
a61af66fc99e Initial load
duke
parents:
diff changeset
529
a61af66fc99e Initial load
duke
parents:
diff changeset
530 void VMThread::execute(VM_Operation* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
531 Thread* t = Thread::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
532
a61af66fc99e Initial load
duke
parents:
diff changeset
533 if (!t->is_VM_thread()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
534 // JavaThread or WatcherThread
a61af66fc99e Initial load
duke
parents:
diff changeset
535 t->check_for_valid_safepoint_state(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
536
a61af66fc99e Initial load
duke
parents:
diff changeset
537 // New request from Java thread, evaluate prologue
a61af66fc99e Initial load
duke
parents:
diff changeset
538 if (!op->doit_prologue()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 return; // op was cancelled
a61af66fc99e Initial load
duke
parents:
diff changeset
540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
541
a61af66fc99e Initial load
duke
parents:
diff changeset
542 // Setup VM_operations for execution
a61af66fc99e Initial load
duke
parents:
diff changeset
543 op->set_calling_thread(t, Thread::get_priority(t));
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // It does not make sense to execute the epilogue, if the VM operation object is getting
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // deallocated by the VM thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
547 bool concurrent = op->evaluate_concurrently();
a61af66fc99e Initial load
duke
parents:
diff changeset
548 bool execute_epilog = !op->is_cheap_allocated();
a61af66fc99e Initial load
duke
parents:
diff changeset
549 assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated");
a61af66fc99e Initial load
duke
parents:
diff changeset
550
a61af66fc99e Initial load
duke
parents:
diff changeset
551 // Get ticket number for non-concurrent VM operations
a61af66fc99e Initial load
duke
parents:
diff changeset
552 int ticket = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
553 if (!concurrent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
554 ticket = t->vm_operation_ticket();
a61af66fc99e Initial load
duke
parents:
diff changeset
555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
556
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // Add VM operation to list of waiting threads. We are guaranteed not to block while holding the
a61af66fc99e Initial load
duke
parents:
diff changeset
558 // VMOperationQueue_lock, so we can block without a safepoint check. This allows vm operation requests
a61af66fc99e Initial load
duke
parents:
diff changeset
559 // to be queued up during a safepoint synchronization.
a61af66fc99e Initial load
duke
parents:
diff changeset
560 {
a61af66fc99e Initial load
duke
parents:
diff changeset
561 VMOperationQueue_lock->lock_without_safepoint_check();
a61af66fc99e Initial load
duke
parents:
diff changeset
562 bool ok = _vm_queue->add(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 op->set_timestamp(os::javaTimeMillis());
a61af66fc99e Initial load
duke
parents:
diff changeset
564 VMOperationQueue_lock->notify();
a61af66fc99e Initial load
duke
parents:
diff changeset
565 VMOperationQueue_lock->unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // VM_Operation got skipped
a61af66fc99e Initial load
duke
parents:
diff changeset
567 if (!ok) {
a61af66fc99e Initial load
duke
parents:
diff changeset
568 assert(concurrent, "can only skip concurrent tasks");
a61af66fc99e Initial load
duke
parents:
diff changeset
569 if (op->is_cheap_allocated()) delete op;
a61af66fc99e Initial load
duke
parents:
diff changeset
570 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
573
a61af66fc99e Initial load
duke
parents:
diff changeset
574 if (!concurrent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // Wait for completion of request (non-concurrent)
a61af66fc99e Initial load
duke
parents:
diff changeset
576 // Note: only a JavaThread triggers the safepoint check when locking
a61af66fc99e Initial load
duke
parents:
diff changeset
577 MutexLocker mu(VMOperationRequest_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
578 while(t->vm_operation_completed_count() < ticket) {
a61af66fc99e Initial load
duke
parents:
diff changeset
579 VMOperationRequest_lock->wait(!t->is_Java_thread());
a61af66fc99e Initial load
duke
parents:
diff changeset
580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
581 }
a61af66fc99e Initial load
duke
parents:
diff changeset
582
a61af66fc99e Initial load
duke
parents:
diff changeset
583 if (execute_epilog) {
a61af66fc99e Initial load
duke
parents:
diff changeset
584 op->doit_epilogue();
a61af66fc99e Initial load
duke
parents:
diff changeset
585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
586 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
587 // invoked by VM thread; usually nested VM operation
a61af66fc99e Initial load
duke
parents:
diff changeset
588 assert(t->is_VM_thread(), "must be a VM thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
589 VM_Operation* prev_vm_operation = vm_operation();
a61af66fc99e Initial load
duke
parents:
diff changeset
590 if (prev_vm_operation != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
591 // Check the VM operation allows nested VM operation. This normally not the case, e.g., the compiler
a61af66fc99e Initial load
duke
parents:
diff changeset
592 // does not allow nested scavenges or compiles.
a61af66fc99e Initial load
duke
parents:
diff changeset
593 if (!prev_vm_operation->allow_nested_vm_operations()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
594 fatal2("Nested VM operation %s requested by operation %s", op->name(), vm_operation()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
595 }
a61af66fc99e Initial load
duke
parents:
diff changeset
596 op->set_calling_thread(prev_vm_operation->calling_thread(), prev_vm_operation->priority());
a61af66fc99e Initial load
duke
parents:
diff changeset
597 }
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 EventMark em("Executing %s VM operation: %s", prev_vm_operation ? "nested" : "", op->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
600
a61af66fc99e Initial load
duke
parents:
diff changeset
601 // Release all internal handles after operation is evaluated
a61af66fc99e Initial load
duke
parents:
diff changeset
602 HandleMark hm(t);
a61af66fc99e Initial load
duke
parents:
diff changeset
603 _cur_vm_operation = op;
a61af66fc99e Initial load
duke
parents:
diff changeset
604
a61af66fc99e Initial load
duke
parents:
diff changeset
605 if (op->evaluate_at_safepoint() && !SafepointSynchronize::is_at_safepoint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
606 SafepointSynchronize::begin();
a61af66fc99e Initial load
duke
parents:
diff changeset
607 op->evaluate();
a61af66fc99e Initial load
duke
parents:
diff changeset
608 SafepointSynchronize::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
609 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
610 op->evaluate();
a61af66fc99e Initial load
duke
parents:
diff changeset
611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
612
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // Free memory if needed
a61af66fc99e Initial load
duke
parents:
diff changeset
614 if (op->is_cheap_allocated()) delete op;
a61af66fc99e Initial load
duke
parents:
diff changeset
615
a61af66fc99e Initial load
duke
parents:
diff changeset
616 _cur_vm_operation = prev_vm_operation;
a61af66fc99e Initial load
duke
parents:
diff changeset
617 }
a61af66fc99e Initial load
duke
parents:
diff changeset
618 }
a61af66fc99e Initial load
duke
parents:
diff changeset
619
a61af66fc99e Initial load
duke
parents:
diff changeset
620
a61af66fc99e Initial load
duke
parents:
diff changeset
621 void VMThread::oops_do(OopClosure* f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
622 Thread::oops_do(f);
a61af66fc99e Initial load
duke
parents:
diff changeset
623 _vm_queue->oops_do(f);
a61af66fc99e Initial load
duke
parents:
diff changeset
624 }
a61af66fc99e Initial load
duke
parents:
diff changeset
625
a61af66fc99e Initial load
duke
parents:
diff changeset
626 //------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
627 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
628
a61af66fc99e Initial load
duke
parents:
diff changeset
629 void VMOperationQueue::verify_queue(int prio) {
a61af66fc99e Initial load
duke
parents:
diff changeset
630 // Check that list is correctly linked
a61af66fc99e Initial load
duke
parents:
diff changeset
631 int length = _queue_length[prio];
a61af66fc99e Initial load
duke
parents:
diff changeset
632 VM_Operation *cur = _queue[prio];
a61af66fc99e Initial load
duke
parents:
diff changeset
633 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
634
a61af66fc99e Initial load
duke
parents:
diff changeset
635 // Check forward links
a61af66fc99e Initial load
duke
parents:
diff changeset
636 for(i = 0; i < length; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
637 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
638 assert(cur != _queue[prio], "list to short (forward)");
a61af66fc99e Initial load
duke
parents:
diff changeset
639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
640 assert(cur->next() == _queue[prio], "list to long (forward)");
a61af66fc99e Initial load
duke
parents:
diff changeset
641
a61af66fc99e Initial load
duke
parents:
diff changeset
642 // Check backwards links
a61af66fc99e Initial load
duke
parents:
diff changeset
643 cur = _queue[prio];
a61af66fc99e Initial load
duke
parents:
diff changeset
644 for(i = 0; i < length; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
645 cur = cur->prev();
a61af66fc99e Initial load
duke
parents:
diff changeset
646 assert(cur != _queue[prio], "list to short (backwards)");
a61af66fc99e Initial load
duke
parents:
diff changeset
647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
648 assert(cur->prev() == _queue[prio], "list to long (backwards)");
a61af66fc99e Initial load
duke
parents:
diff changeset
649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
650
a61af66fc99e Initial load
duke
parents:
diff changeset
651 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
652
a61af66fc99e Initial load
duke
parents:
diff changeset
653 void VMThread::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
654 oops_do(&VerifyOopClosure::verify_oop);
a61af66fc99e Initial load
duke
parents:
diff changeset
655 }