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