23 */
24
25 #include "precompiled.hpp"
26 #include "compiler/compileBroker.hpp"
27 #include "gc_interface/collectedHeap.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "oops/method.hpp"
30 #include "oops/oop.inline.hpp"
31 #include "runtime/interfaceSupport.hpp"
32 #include "runtime/mutexLocker.hpp"
33 #include "runtime/os.hpp"
34 #include "runtime/thread.inline.hpp"
35 #include "runtime/vmThread.hpp"
36 #include "runtime/vm_operations.hpp"
37 #include "services/runtimeService.hpp"
38 #include "trace/tracing.hpp"
39 #include "utilities/dtrace.hpp"
40 #include "utilities/events.hpp"
41 #include "utilities/xmlstream.hpp"
42
43 #ifndef USDT2
44 HS_DTRACE_PROBE_DECL3(hotspot, vmops__request, char *, uintptr_t, int);
45 HS_DTRACE_PROBE_DECL3(hotspot, vmops__begin, char *, uintptr_t, int);
46 HS_DTRACE_PROBE_DECL3(hotspot, vmops__end, char *, uintptr_t, int);
47 #endif /* !USDT2 */
48
49 // Dummy VM operation to act as first element in our circular double-linked list
50 class VM_Dummy: public VM_Operation {
51 VMOp_Type type() const { return VMOp_Dummy; }
52 void doit() {};
53 };
54
55 VMOperationQueue::VMOperationQueue() {
56 // The queue is a circular doubled-linked list, which always contains
57 // one element (i.e., one element means empty).
58 for(int i = 0; i < nof_priorities; i++) {
59 _queue_length[i] = 0;
60 _queue_counter = 0;
61 _queue[i] = new VM_Dummy();
62 _queue[i]->set_next(_queue[i]);
63 _queue[i]->set_prev(_queue[i]);
64 }
65 _drain_list = NULL;
66 }
67
68
137 VM_Operation* cur = _queue[queue];
138 cur = cur->next();
139 while (cur != _queue[queue]) {
140 cur->oops_do(f);
141 cur = cur->next();
142 }
143 }
144
145 void VMOperationQueue::drain_list_oops_do(OopClosure* f) {
146 VM_Operation* cur = _drain_list;
147 while (cur != NULL) {
148 cur->oops_do(f);
149 cur = cur->next();
150 }
151 }
152
153 //-----------------------------------------------------------------
154 // High-level interface
155 bool VMOperationQueue::add(VM_Operation *op) {
156
157 #ifndef USDT2
158 HS_DTRACE_PROBE3(hotspot, vmops__request, op->name(), strlen(op->name()),
159 op->evaluation_mode());
160 #else /* USDT2 */
161 HOTSPOT_VMOPS_REQUEST(
162 (char *) op->name(), strlen(op->name()),
163 op->evaluation_mode());
164 #endif /* USDT2 */
165
166 // Encapsulates VM queue policy. Currently, that
167 // only involves putting them on the right list
168 if (op->evaluate_at_safepoint()) {
169 queue_add_back(SafepointPriority, op);
170 return true;
171 }
172
173 queue_add_back(MediumPriority, op);
174 return true;
175 }
176
177 VM_Operation* VMOperationQueue::remove_next() {
178 // Assuming VMOperation queue is two-level priority queue. If there are
179 // more than two priorities, we need a different scheduling algorithm.
180 assert(SafepointPriority == 0 && MediumPriority == 1 && nof_priorities == 2,
181 "current algorithm does not work");
182
183 // simple counter based scheduling to prevent starvation of lower priority
184 // queue. -- see 4390175
341 // at a very delicate time (VM shutdown) and we are operating in non- VM
342 // thread at Safepoint. It's safer to not share lock with other threads.
343 { MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
344 while(!VMThread::is_terminated()) {
345 _terminate_lock->wait(Mutex::_no_safepoint_check_flag);
346 }
347 }
348 }
349
350 void VMThread::print_on(outputStream* st) const {
351 st->print("\"%s\" ", name());
352 Thread::print_on(st);
353 st->cr();
354 }
355
356 void VMThread::evaluate_operation(VM_Operation* op) {
357 ResourceMark rm;
358
359 {
360 PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time());
361 #ifndef USDT2
362 HS_DTRACE_PROBE3(hotspot, vmops__begin, op->name(), strlen(op->name()),
363 op->evaluation_mode());
364 #else /* USDT2 */
365 HOTSPOT_VMOPS_BEGIN(
366 (char *) op->name(), strlen(op->name()),
367 op->evaluation_mode());
368 #endif /* USDT2 */
369
370 EventExecuteVMOperation event;
371
372 op->evaluate();
373
374 if (event.should_commit()) {
375 bool is_concurrent = op->evaluate_concurrently();
376 event.set_operation(op->type());
377 event.set_safepoint(op->evaluate_at_safepoint());
378 event.set_blocking(!is_concurrent);
379 // Only write caller thread information for non-concurrent vm operations.
380 // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown.
381 // This is because the caller thread could have exited already.
382 event.set_caller(is_concurrent ? 0 : op->calling_thread()->osthread()->thread_id());
383 event.commit();
384 }
385
386 #ifndef USDT2
387 HS_DTRACE_PROBE3(hotspot, vmops__end, op->name(), strlen(op->name()),
388 op->evaluation_mode());
389 #else /* USDT2 */
390 HOTSPOT_VMOPS_END(
391 (char *) op->name(), strlen(op->name()),
392 op->evaluation_mode());
393 #endif /* USDT2 */
394 }
395
396 // Last access of info in _cur_vm_operation!
397 bool c_heap_allocated = op->is_cheap_allocated();
398
399 // Mark as completed
400 if (!op->evaluate_concurrently()) {
401 op->calling_thread()->increment_vm_operation_completed_count();
402 }
403 // It is unsafe to access the _cur_vm_operation after the 'increment_vm_operation_completed_count' call,
404 // since if it is stack allocated the calling thread might have deallocated
405 if (c_heap_allocated) {
406 delete _cur_vm_operation;
407 }
408 }
409
410
411 void VMThread::loop() {
412 assert(_cur_vm_operation == NULL, "no current one should be executing");
413
|
23 */
24
25 #include "precompiled.hpp"
26 #include "compiler/compileBroker.hpp"
27 #include "gc_interface/collectedHeap.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "oops/method.hpp"
30 #include "oops/oop.inline.hpp"
31 #include "runtime/interfaceSupport.hpp"
32 #include "runtime/mutexLocker.hpp"
33 #include "runtime/os.hpp"
34 #include "runtime/thread.inline.hpp"
35 #include "runtime/vmThread.hpp"
36 #include "runtime/vm_operations.hpp"
37 #include "services/runtimeService.hpp"
38 #include "trace/tracing.hpp"
39 #include "utilities/dtrace.hpp"
40 #include "utilities/events.hpp"
41 #include "utilities/xmlstream.hpp"
42
43 // Dummy VM operation to act as first element in our circular double-linked list
44 class VM_Dummy: public VM_Operation {
45 VMOp_Type type() const { return VMOp_Dummy; }
46 void doit() {};
47 };
48
49 VMOperationQueue::VMOperationQueue() {
50 // The queue is a circular doubled-linked list, which always contains
51 // one element (i.e., one element means empty).
52 for(int i = 0; i < nof_priorities; i++) {
53 _queue_length[i] = 0;
54 _queue_counter = 0;
55 _queue[i] = new VM_Dummy();
56 _queue[i]->set_next(_queue[i]);
57 _queue[i]->set_prev(_queue[i]);
58 }
59 _drain_list = NULL;
60 }
61
62
131 VM_Operation* cur = _queue[queue];
132 cur = cur->next();
133 while (cur != _queue[queue]) {
134 cur->oops_do(f);
135 cur = cur->next();
136 }
137 }
138
139 void VMOperationQueue::drain_list_oops_do(OopClosure* f) {
140 VM_Operation* cur = _drain_list;
141 while (cur != NULL) {
142 cur->oops_do(f);
143 cur = cur->next();
144 }
145 }
146
147 //-----------------------------------------------------------------
148 // High-level interface
149 bool VMOperationQueue::add(VM_Operation *op) {
150
151 HOTSPOT_VMOPS_REQUEST(
152 (char *) op->name(), strlen(op->name()),
153 op->evaluation_mode());
154
155 // Encapsulates VM queue policy. Currently, that
156 // only involves putting them on the right list
157 if (op->evaluate_at_safepoint()) {
158 queue_add_back(SafepointPriority, op);
159 return true;
160 }
161
162 queue_add_back(MediumPriority, op);
163 return true;
164 }
165
166 VM_Operation* VMOperationQueue::remove_next() {
167 // Assuming VMOperation queue is two-level priority queue. If there are
168 // more than two priorities, we need a different scheduling algorithm.
169 assert(SafepointPriority == 0 && MediumPriority == 1 && nof_priorities == 2,
170 "current algorithm does not work");
171
172 // simple counter based scheduling to prevent starvation of lower priority
173 // queue. -- see 4390175
330 // at a very delicate time (VM shutdown) and we are operating in non- VM
331 // thread at Safepoint. It's safer to not share lock with other threads.
332 { MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
333 while(!VMThread::is_terminated()) {
334 _terminate_lock->wait(Mutex::_no_safepoint_check_flag);
335 }
336 }
337 }
338
339 void VMThread::print_on(outputStream* st) const {
340 st->print("\"%s\" ", name());
341 Thread::print_on(st);
342 st->cr();
343 }
344
345 void VMThread::evaluate_operation(VM_Operation* op) {
346 ResourceMark rm;
347
348 {
349 PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time());
350 HOTSPOT_VMOPS_BEGIN(
351 (char *) op->name(), strlen(op->name()),
352 op->evaluation_mode());
353
354 EventExecuteVMOperation event;
355
356 op->evaluate();
357
358 if (event.should_commit()) {
359 bool is_concurrent = op->evaluate_concurrently();
360 event.set_operation(op->type());
361 event.set_safepoint(op->evaluate_at_safepoint());
362 event.set_blocking(!is_concurrent);
363 // Only write caller thread information for non-concurrent vm operations.
364 // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown.
365 // This is because the caller thread could have exited already.
366 event.set_caller(is_concurrent ? 0 : op->calling_thread()->osthread()->thread_id());
367 event.commit();
368 }
369
370 HOTSPOT_VMOPS_END(
371 (char *) op->name(), strlen(op->name()),
372 op->evaluation_mode());
373 }
374
375 // Last access of info in _cur_vm_operation!
376 bool c_heap_allocated = op->is_cheap_allocated();
377
378 // Mark as completed
379 if (!op->evaluate_concurrently()) {
380 op->calling_thread()->increment_vm_operation_completed_count();
381 }
382 // It is unsafe to access the _cur_vm_operation after the 'increment_vm_operation_completed_count' call,
383 // since if it is stack allocated the calling thread might have deallocated
384 if (c_heap_allocated) {
385 delete _cur_vm_operation;
386 }
387 }
388
389
390 void VMThread::loop() {
391 assert(_cur_vm_operation == NULL, "no current one should be executing");
392
|