< 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  *

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

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

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

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







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

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

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

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

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