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/jfrTraceTime.hpp" 31 #include "jfr/writers/jfrNativeEventWriter.hpp" 32 #include "runtime/thread.hpp" 33 #include "trace/traceEvent.hpp" 34 #include "utilities/ticks.hpp" 35 #ifdef ASSERT 36 #include "utilities/bitMap.hpp" 37 #endif 38 39 #ifdef ASSERT 40 class JfrTraceEventVerifier { 41 template <typename> 42 friend class JfrTraceEvent; 43 private: 44 // verification of event fields 45 BitMap::bm_word_t _verification_storage[1]; 46 BitMapView _verification_bit_map; 47 48 JfrTraceEventVerifier(); 49 void check(BitMap::idx_t field_idx) const; 50 void set_field_bit(size_t field_idx); 51 bool verify_field_bit(size_t field_idx) const; 52 }; 53 54 #endif // ASSERT 55 56 template <typename T> 57 class JfrTraceEvent : public TraceEvent<T> { 58 protected: 59 JfrTraceEvent(EventStartTime timing=TIMED) : TraceEvent<T>(timing) 60 #ifdef ASSERT 61 , _verifier() 62 #endif 63 { } 64 65 public: 66 void set_starttime(const JfrTraceTime& time) { 67 this->_startTime = time.value(); 68 } 69 70 void set_endtime(const JfrTraceTime& time) { 71 this->_endTime = time.value(); 72 } 73 74 void set_starttime(const Ticks& time) { 75 this->_startTime = JfrTraceTime::is_ft_enabled() ? time.ft_value() : time.value(); 76 } 77 78 void set_endtime(const Ticks& time) { 79 this->_endTime = JfrTraceTime::is_ft_enabled() ? time.ft_value() : time.value(); 80 } 81 82 private: 83 bool should_write() { 84 if (T::isInstant || T::isRequestable || T::hasCutoff) { 85 return true; 86 } 87 return (this->_endTime - this->_startTime) >= JfrEventSetting::threshold(T::eventId); 88 } 89 90 void writeEvent() { 91 DEBUG_ONLY(assert_precondition();) 92 Thread* const event_thread = Thread::current(); 93 JfrThreadData* const trace_data = event_thread->trace_data(); 94 JfrBuffer* const buffer = trace_data->native_buffer(); 95 if (buffer == NULL) { 96 // most likely a pending OOM 97 return; 98 } 99 JfrNativeEventWriter writer(buffer, event_thread); 100 writer.write<u8>(T::eventId); 101 assert(this->_startTime != 0, "invariant"); 102 writer.write(this->_startTime); 103 if (!(T::isInstant || T::isRequestable) || T::hasCutoff) { 104 assert(this->_endTime != 0, "invariant"); 105 writer.write(this->_endTime - this->_startTime); 106 } 107 if (T::hasThread) { 108 writer.write(trace_data->thread_id()); 109 } 110 if (T::hasStackTrace) { 111 if (JfrEventSetting::has_stacktrace(T::eventId)) { 112 if (trace_data->has_cached_stack_trace()) { 113 writer.write(trace_data->cached_stack_trace_id()); 114 } else { 115 writer.write(JfrStackTraceRepository::record(event_thread)); 116 } 117 } else { 118 writer.write<traceid>(0); 119 } 120 } 121 // payload 122 static_cast<T*>(this)->writeData(writer); 123 } 124 125 #ifdef ASSERT 126 private: 127 // verification of event fields 128 JfrTraceEventVerifier _verifier; 129 130 void assert_precondition() { 131 assert(T::eventId >= (TraceEventId)NUM_RESERVED_EVENTS, "event id underflow invariant"); 132 assert(T::eventId < MaxTraceEventId, "event id overflow invariant"); 133 DEBUG_ONLY(static_cast<T*>(this)->verify()); 134 } 135 136 protected: 137 void set_field_bit(size_t field_idx) { 138 _verifier.set_field_bit(field_idx); 139 // it is ok to reuse an already committed event 140 // granted you provide new informational content 141 this->_committed = false; 142 } 143 bool verify_field_bit(size_t field_idx) const { 144 return _verifier.verify_field_bit(field_idx); 145 } 146 #endif // ASSERT 147 148 template <typename> 149 friend class TraceEvent; 150 }; 151 152 #endif // SHARE_VM_JFR_RECORDER_SERVICE_JFREVENT_HPP