1 /*
  2  * Copyright (c) 2012, 2020, 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_JFR_SUPPORT_JFRTHREADLOCAL_HPP
 26 #define SHARE_JFR_SUPPORT_JFRTHREADLOCAL_HPP
 27 
 28 #include "jfr/utilities/jfrBlob.hpp"
 29 #include "jfr/utilities/jfrTypes.hpp"
 30 
 31 class JavaThread;
 32 class JfrBuffer;
 33 class JfrStackFrame;
 34 class Thread;
 35 
 36 class JfrThreadLocal {
 37  private:
 38   jobject _java_event_writer;
 39   mutable JfrBuffer* _java_buffer;
 40   mutable JfrBuffer* _native_buffer;
 41   JfrBuffer* _shelved_buffer;
 42   JfrBuffer* _load_barrier_buffer_epoch_0;
 43   JfrBuffer* _load_barrier_buffer_epoch_1;
 44   JfrBuffer* _checkpoint_buffer_epoch_0;
 45   JfrBuffer* _checkpoint_buffer_epoch_1;
 46   mutable JfrStackFrame* _stackframes;
 47   JfrBlobHandle _thread;
 48   mutable traceid _thread_id;
 49   mutable traceid _thread_id_alias;
 50   u8 _data_lost;
 51   traceid _stack_trace_id;
 52   jlong _user_time;
 53   jlong _cpu_time;
 54   jlong _wallclock_time;
 55   unsigned int _stack_trace_hash;
 56   mutable u4 _stackdepth;
 57   volatile jint _entering_suspend_flag;
 58   mutable volatile int _critical_section;
 59   bool _excluded;
 60   bool _dead;
 61   traceid _parent_trace_id;
 62 
 63   JfrBuffer* install_native_buffer() const;
 64   JfrBuffer* install_java_buffer() const;
 65   JfrStackFrame* install_stackframes() const;
 66   void release(Thread* t);
 67   static void release(JfrThreadLocal* tl, Thread* t);
 68   static traceid assign_thread_id(const Thread* t);
 69 
 70  public:
 71   JfrThreadLocal();
 72 
 73   JfrBuffer* native_buffer() const {
 74     return _native_buffer != NULL ? _native_buffer : install_native_buffer();
 75   }
 76 
 77   bool has_native_buffer() const {
 78     return _native_buffer != NULL;
 79   }
 80 
 81   void set_native_buffer(JfrBuffer* buffer) {
 82     _native_buffer = buffer;
 83   }
 84 
 85   JfrBuffer* java_buffer() const {
 86     return _java_buffer != NULL ? _java_buffer : install_java_buffer();
 87   }
 88 
 89   bool has_java_buffer() const {
 90     return _java_buffer != NULL;
 91   }
 92 
 93   void set_java_buffer(JfrBuffer* buffer) {
 94     _java_buffer = buffer;
 95   }
 96 
 97   JfrBuffer* shelved_buffer() const {
 98     return _shelved_buffer;
 99   }
100 
101   void shelve_buffer(JfrBuffer* buffer) {
102     _shelved_buffer = buffer;
103   }
104 
105   bool has_java_event_writer() const {
106     return _java_event_writer != NULL;
107   }
108 
109   jobject java_event_writer() {
110     return _java_event_writer;
111   }
112 
113   void set_java_event_writer(jobject java_event_writer) {
114     _java_event_writer = java_event_writer;
115   }
116 
117   JfrStackFrame* stackframes() const {
118     return _stackframes != NULL ? _stackframes : install_stackframes();
119   }
120 
121   void set_stackframes(JfrStackFrame* frames) {
122     _stackframes = frames;
123   }
124 
125   u4 stackdepth() const;
126 
127   void set_stackdepth(u4 depth) {
128     _stackdepth = depth;
129   }
130 
131   // jfr contextual thread id
132   static traceid thread_id(const Thread* t, bool* is_virtual = NULL);
133   static traceid virtual_thread_id(const Thread* t, oop vthread);
134   // jfr hardware thread id
135   static traceid vm_thread_id(const Thread* t);
136 
137   static void impersonate(const Thread* t, traceid other_thread_id);
138   static void stop_impersonating(const Thread* t);
139   static bool is_impersonating(const Thread* t);
140 
141   traceid parent_thread_id() const {
142     return _parent_trace_id;
143   }
144 
145   void set_cached_stack_trace_id(traceid id, unsigned int hash = 0) {
146     _stack_trace_id = id;
147     _stack_trace_hash = hash;
148   }
149 
150   bool has_cached_stack_trace() const {
151     return _stack_trace_id != max_julong;
152   }
153 
154   void clear_cached_stack_trace() {
155     _stack_trace_id = max_julong;
156     _stack_trace_hash = 0;
157   }
158 
159   traceid cached_stack_trace_id() const {
160     return _stack_trace_id;
161   }
162 
163   unsigned int cached_stack_trace_hash() const {
164     return _stack_trace_hash;
165   }
166 
167   void set_trace_block() {
168     _entering_suspend_flag = 1;
169   }
170 
171   void clear_trace_block() {
172     _entering_suspend_flag = 0;
173   }
174 
175   bool is_trace_block() const {
176     return _entering_suspend_flag != 0;
177   }
178 
179   u8 data_lost() const {
180     return _data_lost;
181   }
182 
183   u8 add_data_lost(u8 value);
184 
185   jlong get_user_time() const {
186     return _user_time;
187   }
188 
189   void set_user_time(jlong user_time) {
190     _user_time = user_time;
191   }
192 
193   jlong get_cpu_time() const {
194     return _cpu_time;
195   }
196 
197   void set_cpu_time(jlong cpu_time) {
198     _cpu_time = cpu_time;
199   }
200 
201   jlong get_wallclock_time() const {
202     return _wallclock_time;
203   }
204 
205   void set_wallclock_time(jlong wallclock_time) {
206     _wallclock_time = wallclock_time;
207   }
208 
209   traceid trace_id() const {
210     return _thread_id;
211   }
212 
213   traceid* const trace_id_addr() const {
214     return &_thread_id;
215   }
216 
217   void set_trace_id(traceid id) const {
218     _thread_id = id;
219   }
220 
221   bool is_excluded() const {
222     return _excluded;
223   }
224 
225   bool is_dead() const {
226     return _dead;
227   }
228 
229   bool has_thread_blob() const;
230   void set_thread_blob(const JfrBlobHandle& handle);
231   const JfrBlobHandle& thread_blob() const;
232 
233   static void exclude(Thread* t);
234   static void include(Thread* t);
235 
236   static void on_start(Thread* t);
237   static void on_vthread_start(JavaThread* jt, jobject vthread);
238   static void on_exit(Thread* t);
239   static void on_vthread_exit(JavaThread* jt, jobject vthread);
240 
241   // Code generation
242   static ByteSize trace_id_offset();
243   static ByteSize java_event_writer_offset();
244 
245   friend class JfrJavaThread;
246   friend class JfrCheckpointManager;
247   template <typename>
248   friend class JfrEpochQueueKlassPolicy;
249 };
250 
251 #endif // SHARE_JFR_SUPPORT_JFRTHREADLOCAL_HPP