1 /* 2 * Copyright (c) 2012, 2018, 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 #ifndef SHARE_VM_JFR_RECORDER_SERVICE_JFREVENT_HPP 26 #define SHARE_VM_JFR_RECORDER_SERVICE_JFREVENT_HPP 27 28 #include "jfr/recorder/jfrEventSetting.inline.hpp" 29 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" 30 #include "jfr/utilities/jfrTime.hpp" 31 #include "jfr/utilities/jfrTypes.hpp" 32 #include "jfr/writers/jfrNativeEventWriter.hpp" 33 #include "runtime/thread.hpp" 34 #include "utilities/exceptions.hpp" 35 #include "utilities/ticks.hpp" 36 #ifdef ASSERT 37 #include "utilities/bitMap.hpp" 38 #endif 39 40 #ifdef ASSERT 41 class JfrEventVerifier { 42 template <typename> 43 friend class JfrEvent; 44 private: 45 // verification of event fields 46 BitMap::bm_word_t _verification_storage[1]; 47 BitMap _verification_bit_map; 48 bool _committed; 49 50 JfrEventVerifier(); 51 void check(BitMap::idx_t field_idx) const; 52 void set_field_bit(size_t field_idx); 53 bool verify_field_bit(size_t field_idx) const; 54 void set_committed(); 55 void clear_committed(); 56 bool committed() const; 57 }; 58 #endif // ASSERT 59 60 template <typename T> 61 class JfrEvent { 62 private: 63 jlong _start_time; 64 jlong _end_time; 65 bool _started; 66 67 protected: 68 JfrEvent(EventStartTime timing=TIMED) : _start_time(0), _end_time(0), _started(false) 69 #ifdef ASSERT 70 , _verifier() 71 #endif 72 { 73 if (T::is_enabled()) { 74 _started = true; 75 if (TIMED == timing && !T::isInstant) { 76 set_starttime(JfrTicks::now()); 77 } 78 } 79 } 80 81 void commit() { 82 if (!should_commit()) { 83 return; 84 } 85 assert(!_verifier.committed(), "event already committed"); 86 if (_start_time == 0) { 87 set_starttime(JfrTicks::now()); 88 } else if (_end_time == 0) { 89 set_endtime(JfrTicks::now()); 90 } 91 if (should_write()) { 92 write_event(); 93 DEBUG_ONLY(_verifier.set_committed();) 94 } 95 } 96 97 public: 98 void set_starttime(const JfrTicks& time) { 99 _start_time = time.value(); 100 } 101 102 void set_endtime(const JfrTicks& time) { 103 _end_time = time.value(); 104 } 105 106 void set_starttime(const Ticks& time) { 107 _start_time = JfrTime::is_ft_enabled() ? time.ft_value() : time.value(); 108 } 109 110 void set_endtime(const Ticks& time) { 111 _end_time = JfrTime::is_ft_enabled() ? time.ft_value() : time.value(); 112 } 113 114 static bool is_enabled() { 115 return JfrEventSetting::is_enabled(T::eventId); 116 } 117 118 static bool is_stacktrace_enabled() { 119 return JfrEventSetting::has_stacktrace(T::eventId); 120 } 121 122 static JfrEventId id() { 123 return T::eventId; 124 } 125 126 static bool is_instant() { 127 return T::isInstant; 128 } 129 130 static bool is_requestable() { 131 return T::isRequestable; 132 } 133 134 static bool has_thread() { 135 return T::hasThread; 136 } 137 138 static bool has_stacktrace() { 139 return T::hasStackTrace; 140 } 141 142 bool should_commit() { 143 return _started; 144 } 145 146 private: 147 bool should_write() { 148 if (T::isInstant || T::isRequestable || T::hasCutoff) { 149 return true; 150 } 151 return (_end_time - _start_time) >= JfrEventSetting::threshold(T::eventId); 152 } 153 154 void write_event() { 155 DEBUG_ONLY(assert_precondition();) 156 Thread* const event_thread = Thread::current(); 157 JfrThreadLocal* const tl = event_thread->jfr_thread_local(); 158 JfrBuffer* const buffer = tl->native_buffer(); 159 if (buffer == NULL) { 160 // most likely a pending OOM 161 return; 162 } 163 JfrNativeEventWriter writer(buffer, event_thread); 164 writer.write<u8>(T::eventId); 165 assert(_start_time != 0, "invariant"); 166 writer.write(_start_time); 167 if (!(T::isInstant || T::isRequestable) || T::hasCutoff) { 168 assert(_end_time != 0, "invariant"); 169 writer.write(_end_time - _start_time); 170 } 171 if (T::hasThread) { 172 writer.write(tl->thread_id()); 173 } 174 if (T::hasStackTrace) { 175 if (is_stacktrace_enabled()) { 176 if (tl->has_cached_stack_trace()) { 177 writer.write(tl->cached_stack_trace_id()); 178 } else { 179 writer.write(JfrStackTraceRepository::record(event_thread)); 180 } 181 } else { 182 writer.write<traceid>(0); 183 } 184 } 185 // payload 186 static_cast<T*>(this)->writeData(writer); 187 } 188 189 #ifdef ASSERT 190 private: 191 // verification of event fields 192 JfrEventVerifier _verifier; 193 194 void assert_precondition() { 195 assert(T::eventId >= (JfrEventId)NUM_RESERVED_EVENTS, "event id underflow invariant"); 196 assert(T::eventId < MaxJfrEventId, "event id overflow invariant"); 197 DEBUG_ONLY(static_cast<T*>(this)->verify()); 198 } 199 200 protected: 201 void set_field_bit(size_t field_idx) { 202 _verifier.set_field_bit(field_idx); 203 // it is ok to reuse an already committed event 204 // granted you provide new informational content 205 _verifier.clear_committed(); 206 } 207 208 bool verify_field_bit(size_t field_idx) const { 209 return _verifier.verify_field_bit(field_idx); 210 } 211 #endif // ASSERT 212 }; 213 214 #endif // SHARE_VM_JFR_RECORDER_SERVICE_JFREVENT_HPP