1 /* 2 * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved. 3 * 4 * This file is part of the Lock Contention Tracing Subsystem for the HotSpot 5 * Virtual Machine, which is developed at Christian Doppler Laboratory on 6 * Monitoring and Evolution of Very-Large-Scale Software Systems. Please 7 * contact us at <http://mevss.jku.at/> if you need additional information 8 * or have any questions. 9 * 10 * This code is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 only, as 12 * published by the Free Software Foundation. 13 * 14 * This code is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * version 2 for more details (a copy is included in the LICENSE file that 18 * accompanied this code). 19 * 20 * You should have received a copy of the GNU General Public License version 21 * 2 along with this work. If not, see <http://www.gnu.org/licenses/>. 22 * 23 */ 24 25 #ifndef SHARE_VM_EVTRACE_TRACEEVENTS_HPP 26 #define SHARE_VM_EVTRACE_TRACEEVENTS_HPP 27 28 #include "evtrace/traceManager.hpp" 29 #include "evtrace/traceMetadata.hpp" 30 31 #include "memory/allocation.hpp" 32 #include "runtime/objectMonitor.hpp" 33 #include "runtime/thread.hpp" 34 35 class TraceWriter; 36 class Klass; 37 class ClassLoaderData; 38 39 class TraceEvents: private TraceTypes // for mere convenience 40 { 41 public: 42 static void initialize(); 43 44 static void write_thread_start(); 45 static void write_thread_name_change(Thread *t); 46 static void write_thread_state_change(Thread *t); 47 static void write_thread_interrupt(Thread *t); 48 static void write_thread_exit(); 49 50 static void write_thread_park_begin(JavaThread *t, bool is_absolute, timestamp park_time); 51 static void write_thread_park_end(Thread *t, seq_num seq, seq_num unpark_seq, park_return_code return_code); 52 static void write_thread_unpark(thread_id thread, seq_num seq, seq_num chained_seq); 53 54 static void write_monitor_inflate(ObjectMonitor *m, seq_num seq); 55 static void write_monitor_deflate(ObjectMonitor *m); 56 static void write_monitor_contended_enter(ObjectMonitor *m, monitor_enter_wait wait); 57 static void write_monitor_contended_entered(ObjectMonitor *m, monitor_entered_flags flags); 58 static void write_monitor_contended_exited(ObjectMonitor *m, seq_num seq, stack_id preallocated_stack_id, bool resolve_stack); 59 static void write_monitor_dummy(ObjectMonitor *m, seq_num seq); 60 61 static void write_class_loader_unload(ClassLoaderData *cld); 62 63 static void write_safepoint_begin(safepoint_reason reason); 64 static void write_safepoint_end(u4 vmops_processed); 65 66 static void write_vm_end(); 67 68 static void write_metadata_reset(); 69 70 static void write_group(JavaThread* t, seq_num park_seq_begin_ref, oop source); 71 72 static void write_marker(const char *label); 73 74 private: 75 TraceEvents() { } 76 77 static bool can_write(); 78 79 static class_id retrieve_class_id_or_write_metadata(Klass *k); 80 static method_id retrieve_method_id_or_write_metadata(Method *m); 81 static stack_id retrieve_stack_id_or_write_metadata(JavaThread *t, stack_id preallocated_id = 0); 82 static void write_stack_metadata(stack_id id, const CompositeTraceStack &ts); 83 static void write_identical_stacks_metadata(stack_id id, stack_id known); 84 85 static timestamp time_now(); 86 static thread_id thread_id_for(Thread *t); 87 static object_id object_id_for(oop obj); 88 static objmonitor_id objmonitor_id_for(ObjectMonitor *om); 89 static object_id objmonitor_object_id_for(ObjectMonitor *om); 90 static classloader_id classloader_id_for(ClassLoaderData *cld); 91 static method_id method_id_for(Method *m); 92 }; 93 94 class TraceEventThreadParkEnd: public StackObj { 95 private: 96 No_Safepoint_Verifier _nsv; 97 bool _enabled; 98 bool _filled; 99 Thread *_thread; 100 TraceTypes::seq_num _seq; 101 TraceTypes::seq_num _unpark_seq; 102 TraceTypes::park_return_code _return_code; 103 104 void do_write(); 105 106 public: 107 TraceEventThreadParkEnd(Thread *t) 108 : _nsv(false, false), _thread(t), _filled(false) 109 { 110 assert(t != NULL, "null thread"); 111 _enabled = EnableEventTracing && EnableEventTracingParkEvents && t->park_priority() >= 0; 112 } 113 114 void fill(TraceTypes::seq_num unpark_seq, TraceTypes::park_return_code return_code) { 115 assert(!_filled, "already filled"); 116 _nsv.enable(); 117 _enabled = _enabled && TraceManager::is_initialized(); 118 if (_enabled) { 119 _seq = TraceManager::metadata()->next_global_seq(); 120 _thread->set_park_last_global_seq(_seq); 121 _unpark_seq = unpark_seq; 122 _return_code = return_code; 123 } 124 _filled = true; 125 } 126 127 ~TraceEventThreadParkEnd() { 128 assert(_filled, "must have been filled"); 129 if (_enabled) { 130 do_write(); 131 } 132 } 133 }; 134 135 class TraceEventThreadUnpark: public StackObj { 136 private: 137 No_Safepoint_Verifier _nsv; 138 bool _enabled; 139 TraceTypes::thread_id _thread_id; 140 TraceTypes::seq_num _seq; 141 TraceTypes::seq_num _chained_seq; 142 143 void do_write(); 144 145 public: 146 TraceEventThreadUnpark(Thread *t) : _nsv(true, false), _chained_seq(-1) { 147 assert(t != NULL, "null thread"); 148 _enabled = EnableEventTracing && EnableEventTracingParkEvents && TraceManager::is_initialized(); 149 if (_enabled) { 150 _thread_id = TraceManager::metadata()->thread_id(t); 151 _seq = TraceManager::metadata()->next_global_seq(); 152 } else { 153 _thread_id = 0; 154 _seq = 1; 155 } 156 } 157 158 ~TraceEventThreadUnpark() { 159 if (_enabled) { 160 do_write(); 161 } 162 } 163 164 TraceTypes::seq_num seq() { return _seq; } 165 166 void set_chained_seq(TraceTypes::seq_num chained_seq) { _chained_seq = chained_seq; } 167 }; 168 169 class TraceEventMonitorContendedExited: public StackObj { 170 private: 171 No_Safepoint_Verifier _nsv; 172 bool _enabled; 173 ObjectMonitor *_monitor; 174 TraceTypes::seq_num _seq; 175 TraceTypes::stack_id *_stack_id_at; 176 TraceTypes::stack_id _preallocated_stack_id; 177 bool _resolve_stack; 178 179 public: 180 TraceEventMonitorContendedExited(ObjectMonitor *m) 181 : _nsv(true, false), _enabled(false), _monitor(m), _seq(0), _stack_id_at(NULL), _resolve_stack(true) 182 { 183 if (EnableEventTracing && EventTracingStrictMonitorEventOrder) { 184 _seq = _monitor->next_trace_seq(); 185 } 186 } 187 188 ~TraceEventMonitorContendedExited() { 189 if (_enabled) { 190 TraceTypes::stack_id id = 0; 191 if (_stack_id_at != NULL) { 192 if (*_stack_id_at == 0 && EnableEventTracingStackTraces) { 193 *_stack_id_at = TraceManager::metadata()->next_stack_id(); 194 } 195 id = *_stack_id_at; 196 } 197 TraceEvents::write_monitor_contended_exited(_monitor, _seq, id, _resolve_stack); 198 } else if (EnableEventTracing && EventTracingStrictMonitorEventOrder && TraceManager::is_initialized()) { 199 assert(!_resolve_stack || _stack_id_at == NULL || *_stack_id_at == 0, 200 "event must be enabled if there is a stack id to resolve"); 201 202 // must consume eagerly acquired sequence number 203 TraceEvents::write_monitor_dummy(_monitor, _seq); 204 } 205 } 206 207 void set_use_or_preallocate_stack_id_at(TraceTypes::stack_id *p) { 208 assert (_stack_id_at == NULL, "set only once"); 209 _stack_id_at = p; 210 } 211 212 void set_use_stack_id(TraceTypes::stack_id id) { 213 _preallocated_stack_id = id; 214 set_use_or_preallocate_stack_id_at(&_preallocated_stack_id); 215 } 216 217 void set_resolve_stack(bool resolve) { 218 _resolve_stack = resolve; 219 } 220 221 void enable() { 222 if (EnableEventTracing && TraceManager::is_initialized()) { 223 if (!_enabled && !EventTracingStrictMonitorEventOrder) { 224 // lazily acquire sequence number, racing with other threads which try 225 // to spin-acquire the monitor and then write contended-entered events 226 _seq = _monitor->next_trace_seq(); 227 } 228 _enabled = true; 229 } 230 } 231 }; 232 233 // for convenience, so this is the only file to include for writing events 234 #include "evtrace/traceWriter.hpp" 235 #include "evtrace/traceMacros.hpp" 236 237 #endif /* SHARE_VM_EVTRACE_TRACEEVENTS_HPP */