1/*
2 * Copyright (c) 2012, 2019, 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/recorder/checkpoint/jfrCheckpointBlob.hpp"
29#include "jfr/utilities/jfrTypes.hpp"
30
31class JavaThread;
32class JfrBuffer;
33class JfrStackFrame;
34class Thread;
35
36class JfrThreadLocal {
37 private:
38 jobject _java_event_writer;
39 mutable JfrBuffer* _java_buffer;
40 mutable JfrBuffer* _native_buffer;
41 JfrBuffer* _shelved_buffer;
42 mutable JfrStackFrame* _stackframes;
43 mutable traceid _trace_id;
44 JfrCheckpointBlobHandle _thread_cp;
45 u8 _data_lost;
46 traceid _stack_trace_id;
47 jlong _user_time;
48 jlong _cpu_time;
49 jlong _wallclock_time;
50 unsigned int _stack_trace_hash;
51 mutable u4 _stackdepth;
52 volatile jint _entering_suspend_flag;
53 bool _dead;
54
55 JfrBuffer* install_native_buffer() const;
56 JfrBuffer* install_java_buffer() const;
57 JfrStackFrame* install_stackframes() const;
58
59 static void release(JfrThreadLocal* tl, Thread* t);
60
61 public:
62 JfrThreadLocal();
63
64 JfrBuffer* native_buffer() const {
65 return _native_buffer != NULL ? _native_buffer : install_native_buffer();
66 }
67
68 bool has_native_buffer() const {
69 return _native_buffer != NULL;
70 }
71
72 void set_native_buffer(JfrBuffer* buffer) {
73 _native_buffer = buffer;
74 }
75
76 JfrBuffer* java_buffer() const {
77 return _java_buffer != NULL ? _java_buffer : install_java_buffer();
78 }
79
80 bool has_java_buffer() const {
81 return _java_buffer != NULL;
82 }
83
84 void set_java_buffer(JfrBuffer* buffer) {
85 _java_buffer = buffer;
86 }
87
88 JfrBuffer* shelved_buffer() const {
89 return _shelved_buffer;
90 }
91
92 void shelve_buffer(JfrBuffer* buffer) {
93 _shelved_buffer = buffer;
94 }
95
96 bool has_java_event_writer() const {
97 return _java_event_writer != NULL;
98 }
99
100 jobject java_event_writer() {
101 return _java_event_writer;
102 }
103
104 void set_java_event_writer(jobject java_event_writer) {
105 _java_event_writer = java_event_writer;
106 }
107
108 JfrStackFrame* stackframes() const {
109 return _stackframes != NULL ? _stackframes : install_stackframes();
110 }
111
112 void set_stackframes(JfrStackFrame* frames) {
113 _stackframes = frames;
114 }
115
116 u4 stackdepth() const;
117
118 void set_stackdepth(u4 depth) {
119 _stackdepth = depth;
120 }
121
122 traceid thread_id() const {
123 return _trace_id;
124 }
125
126 void set_thread_id(traceid thread_id) {
127 _trace_id = thread_id;
128 }
129
130 void set_cached_stack_trace_id(traceid id, unsigned int hash = 0) {
131 _stack_trace_id = id;
132 _stack_trace_hash = hash;
133 }
134
135 bool has_cached_stack_trace() const {
136 return _stack_trace_id != max_julong;
137 }
138
139 void clear_cached_stack_trace() {
140 _stack_trace_id = max_julong;
141 _stack_trace_hash = 0;
142 }
143
144 traceid cached_stack_trace_id() const {
145 return _stack_trace_id;
146 }
147
148 unsigned int cached_stack_trace_hash() const {
149 return _stack_trace_hash;
150 }
151
152 void set_trace_block() {
153 _entering_suspend_flag = 1;
154 }
155
156 void clear_trace_block() {
157 _entering_suspend_flag = 0;
158 }
159
160 bool is_trace_block() const {
161 return _entering_suspend_flag != 0;
162 }
163
164 u8 data_lost() const {
165 return _data_lost;
166 }
167
168 u8 add_data_lost(u8 value);
169
170 jlong get_user_time() const {
171 return _user_time;
172 }
173
174 void set_user_time(jlong user_time) {
175 _user_time = user_time;
176 }
177
178 jlong get_cpu_time() const {
179 return _cpu_time;
180 }
181
182 void set_cpu_time(jlong cpu_time) {
183 _cpu_time = cpu_time;
184 }
185
186 jlong get_wallclock_time() const {
187 return _wallclock_time;
188 }
189
190 void set_wallclock_time(jlong wallclock_time) {
191 _wallclock_time = wallclock_time;
192 }
193
194 traceid trace_id() const {
195 return _trace_id;
196 }
197
198 traceid* const trace_id_addr() const {
199 return &_trace_id;
200 }
201
202 void set_trace_id(traceid id) const {
203 _trace_id = id;
204 }
205
206 bool is_dead() const {
207 return _dead;
208 }
209
210 bool has_thread_checkpoint() const;
211 void set_thread_checkpoint(const JfrCheckpointBlobHandle& handle);
212 const JfrCheckpointBlobHandle& thread_checkpoint() const;
213
214 static void on_start(Thread* t);
215 static void on_exit(Thread* t);
216
217 // Code generation
218 static ByteSize trace_id_offset();
219 static ByteSize java_event_writer_offset();
220};
221
222#endif // SHARE_JFR_SUPPORT_JFRTHREADLOCAL_HPP
223