< prev index next >

src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp

Print this page

146   }
147   virtual void call() {
148     _sampler.protected_task(_context);
149   }
150  private:
151   OSThreadSampler& _sampler;
152   const os::SuspendedThreadTaskContext& _context;
153 };
154 
155 void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) {
156 #ifndef ASSERT
157   guarantee(JfrOptionSet::sample_protection(), "Sample Protection should be on in product builds");
158 #endif
159   assert(_suspend_time.value() == 0, "already timestamped!");
160   _suspend_time = JfrTicks::now();
161 
162   if (JfrOptionSet::sample_protection()) {
163     OSThreadSamplerCallback cb(*this, context);
164     os::ThreadCrashProtection crash_protection;
165     if (!crash_protection.call(cb)) {
166       log_error(jfr)("Thread method sampler crashed");
167     }
168   } else {
169     protected_task(context);
170   }
171 }
172 
173 /*
174 * From this method and down the call tree we attempt to protect against crashes
175 * using a signal handler / __try block. Don't take locks, rely on destructors or
176 * leave memory (in case of signal / exception) in an inconsistent state. */
177 void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {
178   JavaThread* jth = JavaThread::cast(context.thread());
179   // Skip sample if we signaled a thread that moved to other state
180   if (!thread_state_in_java(jth)) {
181     return;
182   }
183   JfrGetCallTrace trace(true, jth);
184   frame topframe;
185   if (trace.get_topframe(context.ucontext(), topframe)) {
186     if (_stacktrace.record_thread(*jth, topframe)) {

187       /* If we managed to get a topframe and a stacktrace, create an event
188       * and put it into our array. We can't call Jfr::_stacktraces.add()
189       * here since it would allocate memory using malloc. Doing so while
190       * the stopped thread is inside malloc would deadlock. */
191       _success = true;
192       EventExecutionSample *ev = _closure.next_event();
193       ev->set_starttime(_suspend_time);
194       ev->set_endtime(_suspend_time); // fake to not take an end time
195       ev->set_sampledThread(JFR_THREAD_ID(jth));
196       ev->set_state(static_cast<u8>(java_lang_Thread::get_thread_status(_thread_oop)));
197     }
198   }
199 }
200 
201 void OSThreadSampler::take_sample() {
202   run();
203 }
204 
205 class JfrNativeSamplerCallback : public os::CrashProtectionCallback {
206  public:
207   JfrNativeSamplerCallback(JfrThreadSampleClosure& closure, JavaThread* jt, JfrStackFrame* frames, u4 max_frames) :
208     _closure(closure), _jt(jt), _thread_oop(jt->threadObj()), _stacktrace(frames, max_frames), _success(false) {
209   }
210   virtual void call();
211   bool success() { return _success; }
212   JfrStackTrace& stacktrace() { return _stacktrace; }
213 
214  private:
215   JfrThreadSampleClosure& _closure;
216   JavaThread* _jt;
217   oop _thread_oop;
218   JfrStackTrace _stacktrace;
219   bool _success;
220 };
221 
222 static void write_native_event(JfrThreadSampleClosure& closure, JavaThread* jt, oop thread_oop) {
223   EventNativeMethodSample *ev = closure.next_event_native();
224   ev->set_starttime(JfrTicks::now());
225   ev->set_sampledThread(JFR_THREAD_ID(jt));
226   ev->set_state(static_cast<u8>(java_lang_Thread::get_thread_status(thread_oop)));
227 }
228 
229 void JfrNativeSamplerCallback::call() {
230   // When a thread is only attach it will be native without a last java frame
231   if (!_jt->has_last_Java_frame()) {
232     return;
233   }
234 
235   frame topframe = _jt->last_frame();
236   frame first_java_frame;
237   Method* method = NULL;
238   JfrGetCallTrace gct(false, _jt);
239   if (!gct.find_top_frame(topframe, &method, first_java_frame)) {
240     return;
241   }
242   if (method == NULL) {
243     return;
244   }
245   topframe = first_java_frame;
246   _success = _stacktrace.record_thread(*_jt, topframe);

247   if (_success) {
248     write_native_event(_closure, _jt, _thread_oop);
249   }
250 }
251 
252 bool JfrThreadSampleClosure::sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) {
253   OSThreadSampler sampler(thread, *this, frames, max_frames);
254   sampler.take_sample();
255   /* We don't want to allocate any memory using malloc/etc while the thread
256   * is stopped, so everything is stored in stack allocated memory until this
257   * point where the thread has been resumed again, if the sampling was a success
258   * we need to store the stacktrace in the stacktrace repository and update
259   * the event with the id that was returned. */
260   if (!sampler.success()) {
261     return false;
262   }
263   EventExecutionSample *event = &_events[_added_java - 1];
264   traceid id = JfrStackTraceRepository::add(sampler.stacktrace());
265   assert(id != 0, "Stacktrace id should not be 0");
266   event->set_stackTrace(id);
267   return true;
268 }

146   }
147   virtual void call() {
148     _sampler.protected_task(_context);
149   }
150  private:
151   OSThreadSampler& _sampler;
152   const os::SuspendedThreadTaskContext& _context;
153 };
154 
155 void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) {
156 #ifndef ASSERT
157   guarantee(JfrOptionSet::sample_protection(), "Sample Protection should be on in product builds");
158 #endif
159   assert(_suspend_time.value() == 0, "already timestamped!");
160   _suspend_time = JfrTicks::now();
161 
162   if (JfrOptionSet::sample_protection()) {
163     OSThreadSamplerCallback cb(*this, context);
164     os::ThreadCrashProtection crash_protection;
165     if (!crash_protection.call(cb)) {
166       log_debug(jfr)("Thread method sampler crashed");
167     }
168   } else {
169     protected_task(context);
170   }
171 }
172 
173 /*
174 * From this method and down the call tree we attempt to protect against crashes
175 * using a signal handler / __try block. Don't take locks, rely on destructors or
176 * leave memory (in case of signal / exception) in an inconsistent state. */
177 void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {
178   JavaThread* const jt = JavaThread::cast(context.thread());
179   // Skip sample if we signaled a thread that moved to other state
180   if (!thread_state_in_java(jt)) {
181     return;
182   }
183   JfrGetCallTrace trace(true, jt);
184   frame topframe;
185   if (trace.get_topframe(context.ucontext(), topframe)) {
186     bool virtual_thread;
187     if (_stacktrace.record_async(jt, topframe, &virtual_thread)) {
188       /* If we managed to get a topframe and a stacktrace, create an event
189       * and put it into our array. We can't call Jfr::_stacktraces.add()
190       * here since it would allocate memory using malloc. Doing so while
191       * the stopped thread is inside malloc would deadlock. */
192       _success = true;
193       EventExecutionSample *ev = _closure.next_event();
194       ev->set_starttime(_suspend_time);
195       ev->set_endtime(_suspend_time); // fake to not take an end time
196       ev->set_sampledThread(virtual_thread ? JFR_THREAD_ID(jt) : JFR_VM_THREAD_ID(jt));
197       ev->set_state(static_cast<u8>(java_lang_Thread::get_thread_status(_thread_oop)));
198     }
199   }
200 }
201 
202 void OSThreadSampler::take_sample() {
203   run();
204 }
205 
206 class JfrNativeSamplerCallback : public os::CrashProtectionCallback {
207  public:
208   JfrNativeSamplerCallback(JfrThreadSampleClosure& closure, JavaThread* jt, JfrStackFrame* frames, u4 max_frames) :
209     _closure(closure), _jt(jt), _thread_oop(jt->threadObj()), _stacktrace(frames, max_frames), _success(false) {
210   }
211   virtual void call();
212   bool success() { return _success; }
213   JfrStackTrace& stacktrace() { return _stacktrace; }
214 
215  private:
216   JfrThreadSampleClosure& _closure;
217   JavaThread* _jt;
218   oop _thread_oop;
219   JfrStackTrace _stacktrace;
220   bool _success;
221 };
222 
223 static void write_native_event(JfrThreadSampleClosure& closure, bool virtual_thread, JavaThread* jt, oop thread_oop) {
224   EventNativeMethodSample *ev = closure.next_event_native();
225   ev->set_starttime(JfrTicks::now());
226   ev->set_sampledThread(virtual_thread ? JFR_THREAD_ID(jt) : JFR_VM_THREAD_ID(jt));
227   ev->set_state(static_cast<u8>(java_lang_Thread::get_thread_status(thread_oop)));
228 }
229 
230 void JfrNativeSamplerCallback::call() {
231   // When a thread is only attach it will be native without a last java frame
232   if (!_jt->has_last_Java_frame()) {
233     return;
234   }
235 
236   frame topframe = _jt->last_frame();
237   frame first_java_frame;
238   Method* method = NULL;
239   JfrGetCallTrace gct(false, _jt);
240   if (!gct.find_top_frame(topframe, &method, first_java_frame)) {
241     return;
242   }
243   if (method == NULL) {
244     return;
245   }
246   topframe = first_java_frame;
247   bool virtual_thread;
248   _success = _stacktrace.record_async(_jt, topframe, &virtual_thread);
249   if (_success) {
250     write_native_event(_closure, virtual_thread, _jt, _thread_oop);
251   }
252 }
253 
254 bool JfrThreadSampleClosure::sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) {
255   OSThreadSampler sampler(thread, *this, frames, max_frames);
256   sampler.take_sample();
257   /* We don't want to allocate any memory using malloc/etc while the thread
258   * is stopped, so everything is stored in stack allocated memory until this
259   * point where the thread has been resumed again, if the sampling was a success
260   * we need to store the stacktrace in the stacktrace repository and update
261   * the event with the id that was returned. */
262   if (!sampler.success()) {
263     return false;
264   }
265   EventExecutionSample *event = &_events[_added_java - 1];
266   traceid id = JfrStackTraceRepository::add(sampler.stacktrace());
267   assert(id != 0, "Stacktrace id should not be 0");
268   event->set_stackTrace(id);
269   return true;
270 }
< prev index next >