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 */