< prev index next >

src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp

Print this page

  1 /*
  2  * Copyright (c) 2016, 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  *

165   jweak thread_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(thread_group_handle) : NULL;
166 
167   JfrThreadGroupPointers* thread_group_pointers = new JfrThreadGroupPointers(thread_group_handle, thread_group_weak_ref);
168   _thread_group_hierarchy->append(thread_group_pointers);
169   // immediate parent thread group
170   oop parent_thread_group_obj = java_lang_ThreadGroup::parent(thread_group_handle());
171   Handle parent_thread_group_handle(current, parent_thread_group_obj);
172 
173   // and check parents parents...
174   while (parent_thread_group_handle != nullptr) {
175     const jweak parent_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(parent_thread_group_handle) : NULL;
176     thread_group_pointers = new JfrThreadGroupPointers(parent_thread_group_handle, parent_group_weak_ref);
177     _thread_group_hierarchy->append(thread_group_pointers);
178     parent_thread_group_obj = java_lang_ThreadGroup::parent(parent_thread_group_handle());
179     parent_thread_group_handle = Handle(current, parent_thread_group_obj);
180   }
181   return _thread_group_hierarchy->length();
182 }
183 
184 static traceid next_id() {
185   static traceid _current_threadgroup_id = 0;
186   return ++_current_threadgroup_id;
187 }
188 
189 class JfrThreadGroup::JfrThreadGroupEntry : public JfrCHeapObj {
190   friend class JfrThreadGroup;
191  private:
192   traceid _thread_group_id;
193   traceid _parent_group_id;
194   char* _thread_group_name; // utf8 format
195   // If an entry is created during a safepoint, the
196   // _thread_group_oop contains a direct oop to
197   // the java.lang.ThreadGroup object.
198   // If an entry is created on javathread exit time (not at safepoint),
199   // _thread_group_weak_ref contains a JNI weak global handle
200   // indirection to the java.lang.ThreadGroup object.
201   // Note: we cannot use a union here since CHECK_UNHANDLED_OOPS makes oop have
202   //       a ctor which isn't allowed in a union by the SunStudio compiler
203   oop _thread_group_oop;
204   jweak _thread_group_weak_ref;
205 

267 
268 JfrThreadGroup::~JfrThreadGroup() {
269   if (_list != NULL) {
270     for (int i = 0; i < _list->length(); i++) {
271       JfrThreadGroupEntry* e = _list->at(i);
272       delete e;
273     }
274     delete _list;
275   }
276 }
277 
278 JfrThreadGroup* JfrThreadGroup::instance() {
279   return _instance;
280 }
281 
282 void JfrThreadGroup::set_instance(JfrThreadGroup* new_instance) {
283   _instance = new_instance;
284 }
285 
286 traceid JfrThreadGroup::thread_group_id(const JavaThread* jt, Thread* current) {

287   JfrThreadGroupsHelper helper(jt, current);
288   return helper.is_valid() ? thread_group_id_internal(helper) : 0;
289 }
290 
291 traceid JfrThreadGroup::thread_group_id(JavaThread* const jt) {
292   return thread_group_id(jt, jt);
293 }
294 
295 traceid JfrThreadGroup::thread_group_id_internal(JfrThreadGroupsHelper& helper) {
296   ThreadGroupExclusiveAccess lock;
297   JfrThreadGroup* tg_instance = instance();
298   if (tg_instance == NULL) {
299     tg_instance = new JfrThreadGroup();
300     if (tg_instance == NULL) {
301       return 0;
302     }
303     set_instance(tg_instance);
304   }
305 
306   JfrThreadGroupEntry* tge = NULL;

336 
337 // Assumes you already searched for the existence
338 // of a corresponding entry in find_entry().
339 JfrThreadGroup::JfrThreadGroupEntry*
340 JfrThreadGroup::new_entry(JfrThreadGroupPointers& ptrs) {
341   JfrThreadGroupEntry* const tge = new JfrThreadGroupEntry(java_lang_ThreadGroup::name(ptrs.thread_group_oop()), ptrs);
342   add_entry(tge);
343   return tge;
344 }
345 
346 int JfrThreadGroup::add_entry(JfrThreadGroupEntry* tge) {
347   assert(tge != NULL, "attempting to add a null entry!");
348   assert(0 == tge->thread_group_id(), "id must be unassigned!");
349   tge->set_thread_group_id(next_id());
350   return _list->append(tge);
351 }
352 
353 void JfrThreadGroup::write_thread_group_entries(JfrCheckpointWriter& writer) const {
354   assert(_list != NULL && !_list->is_empty(), "should not need be here!");
355   const int number_of_tg_entries = _list->length();
356   writer.write_count(number_of_tg_entries);







357   for (int index = 0; index < number_of_tg_entries; ++index) {
358     const JfrThreadGroupEntry* const curtge = _list->at(index);
359     writer.write_key(curtge->thread_group_id());
360     writer.write(curtge->parent_group_id());
361     writer.write(curtge->thread_group_name());
362   }
363 }
364 
365 void JfrThreadGroup::write_selective_thread_group(JfrCheckpointWriter* writer, traceid thread_group_id) const {
366   assert(writer != NULL, "invariant");
367   assert(_list != NULL && !_list->is_empty(), "should not need be here!");

368   const int number_of_tg_entries = _list->length();
369 
370   // save context
371   const JfrCheckpointContext ctx = writer->context();
372   writer->write_type(TYPE_THREADGROUP);
373   const jlong count_offset = writer->reserve(sizeof(u4)); // Don't know how many yet
374   int number_of_entries_written = 0;
375   for (int index = number_of_tg_entries - 1; index >= 0; --index) {
376     const JfrThreadGroupEntry* const curtge = _list->at(index);
377     if (thread_group_id == curtge->thread_group_id()) {
378       writer->write_key(curtge->thread_group_id());
379       writer->write(curtge->parent_group_id());
380       writer->write(curtge->thread_group_name());
381       ++number_of_entries_written;
382       thread_group_id = curtge->parent_group_id();
383     }
384   }
385   if (number_of_entries_written == 0) {
386     // nothing to write, restore context
387     writer->set_context(ctx);

  1 /*
  2  * Copyright (c) 2016, 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  *

165   jweak thread_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(thread_group_handle) : NULL;
166 
167   JfrThreadGroupPointers* thread_group_pointers = new JfrThreadGroupPointers(thread_group_handle, thread_group_weak_ref);
168   _thread_group_hierarchy->append(thread_group_pointers);
169   // immediate parent thread group
170   oop parent_thread_group_obj = java_lang_ThreadGroup::parent(thread_group_handle());
171   Handle parent_thread_group_handle(current, parent_thread_group_obj);
172 
173   // and check parents parents...
174   while (parent_thread_group_handle != nullptr) {
175     const jweak parent_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(parent_thread_group_handle) : NULL;
176     thread_group_pointers = new JfrThreadGroupPointers(parent_thread_group_handle, parent_group_weak_ref);
177     _thread_group_hierarchy->append(thread_group_pointers);
178     parent_thread_group_obj = java_lang_ThreadGroup::parent(parent_thread_group_handle());
179     parent_thread_group_handle = Handle(current, parent_thread_group_obj);
180   }
181   return _thread_group_hierarchy->length();
182 }
183 
184 static traceid next_id() {
185   static traceid _current_threadgroup_id = 1; // 1 is reserved for thread group "VirtualThreads"
186   return ++_current_threadgroup_id;
187 }
188 
189 class JfrThreadGroup::JfrThreadGroupEntry : public JfrCHeapObj {
190   friend class JfrThreadGroup;
191  private:
192   traceid _thread_group_id;
193   traceid _parent_group_id;
194   char* _thread_group_name; // utf8 format
195   // If an entry is created during a safepoint, the
196   // _thread_group_oop contains a direct oop to
197   // the java.lang.ThreadGroup object.
198   // If an entry is created on javathread exit time (not at safepoint),
199   // _thread_group_weak_ref contains a JNI weak global handle
200   // indirection to the java.lang.ThreadGroup object.
201   // Note: we cannot use a union here since CHECK_UNHANDLED_OOPS makes oop have
202   //       a ctor which isn't allowed in a union by the SunStudio compiler
203   oop _thread_group_oop;
204   jweak _thread_group_weak_ref;
205 

267 
268 JfrThreadGroup::~JfrThreadGroup() {
269   if (_list != NULL) {
270     for (int i = 0; i < _list->length(); i++) {
271       JfrThreadGroupEntry* e = _list->at(i);
272       delete e;
273     }
274     delete _list;
275   }
276 }
277 
278 JfrThreadGroup* JfrThreadGroup::instance() {
279   return _instance;
280 }
281 
282 void JfrThreadGroup::set_instance(JfrThreadGroup* new_instance) {
283   _instance = new_instance;
284 }
285 
286 traceid JfrThreadGroup::thread_group_id(const JavaThread* jt, Thread* current) {
287   HandleMark hm(current);
288   JfrThreadGroupsHelper helper(jt, current);
289   return helper.is_valid() ? thread_group_id_internal(helper) : 0;
290 }
291 
292 traceid JfrThreadGroup::thread_group_id(JavaThread* const jt) {
293   return thread_group_id(jt, jt);
294 }
295 
296 traceid JfrThreadGroup::thread_group_id_internal(JfrThreadGroupsHelper& helper) {
297   ThreadGroupExclusiveAccess lock;
298   JfrThreadGroup* tg_instance = instance();
299   if (tg_instance == NULL) {
300     tg_instance = new JfrThreadGroup();
301     if (tg_instance == NULL) {
302       return 0;
303     }
304     set_instance(tg_instance);
305   }
306 
307   JfrThreadGroupEntry* tge = NULL;

337 
338 // Assumes you already searched for the existence
339 // of a corresponding entry in find_entry().
340 JfrThreadGroup::JfrThreadGroupEntry*
341 JfrThreadGroup::new_entry(JfrThreadGroupPointers& ptrs) {
342   JfrThreadGroupEntry* const tge = new JfrThreadGroupEntry(java_lang_ThreadGroup::name(ptrs.thread_group_oop()), ptrs);
343   add_entry(tge);
344   return tge;
345 }
346 
347 int JfrThreadGroup::add_entry(JfrThreadGroupEntry* tge) {
348   assert(tge != NULL, "attempting to add a null entry!");
349   assert(0 == tge->thread_group_id(), "id must be unassigned!");
350   tge->set_thread_group_id(next_id());
351   return _list->append(tge);
352 }
353 
354 void JfrThreadGroup::write_thread_group_entries(JfrCheckpointWriter& writer) const {
355   assert(_list != NULL && !_list->is_empty(), "should not need be here!");
356   const int number_of_tg_entries = _list->length();
357   writer.write_count(number_of_tg_entries + 1); // + VirtualThread group
358   writer.write_key(1);      // 1 is reserved for VirtualThread group
359   writer.write<traceid>(0); // parent
360   const oop vgroup = java_lang_Thread_VirtualThreads::get_THREAD_GROUP();
361   assert(vgroup != (oop)NULL, "invariant");
362   const char* const vgroup_name = java_lang_ThreadGroup::name(vgroup);
363   assert(vgroup_name != NULL, "invariant");
364   writer.write(vgroup_name);
365   for (int index = 0; index < number_of_tg_entries; ++index) {
366     const JfrThreadGroupEntry* const curtge = _list->at(index);
367     writer.write_key(curtge->thread_group_id());
368     writer.write(curtge->parent_group_id());
369     writer.write(curtge->thread_group_name());
370   }
371 }
372 
373 void JfrThreadGroup::write_selective_thread_group(JfrCheckpointWriter* writer, traceid thread_group_id) const {
374   assert(writer != NULL, "invariant");
375   assert(_list != NULL && !_list->is_empty(), "should not need be here!");
376   assert(thread_group_id != 1, "should not need be here!");
377   const int number_of_tg_entries = _list->length();
378 
379   // save context
380   const JfrCheckpointContext ctx = writer->context();
381   writer->write_type(TYPE_THREADGROUP);
382   const jlong count_offset = writer->reserve(sizeof(u4)); // Don't know how many yet
383   int number_of_entries_written = 0;
384   for (int index = number_of_tg_entries - 1; index >= 0; --index) {
385     const JfrThreadGroupEntry* const curtge = _list->at(index);
386     if (thread_group_id == curtge->thread_group_id()) {
387       writer->write_key(curtge->thread_group_id());
388       writer->write(curtge->parent_group_id());
389       writer->write(curtge->thread_group_name());
390       ++number_of_entries_written;
391       thread_group_id = curtge->parent_group_id();
392     }
393   }
394   if (number_of_entries_written == 0) {
395     // nothing to write, restore context
396     writer->set_context(ctx);
< prev index next >