< prev index next >

src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp

Print this page

 22  *
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "classfile/javaClasses.inline.hpp"
 27 #include "jfr/jni/jfrJavaSupport.hpp"
 28 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
 29 #include "jfr/leakprofiler/leakProfiler.hpp"
 30 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
 31 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
 32 #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp"
 33 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
 34 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
 35 #include "jfr/recorder/jfrRecorder.hpp"
 36 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 37 #include "jfr/recorder/service/jfrOptionSet.hpp"
 38 #include "jfr/recorder/storage/jfrEpochStorage.inline.hpp"
 39 #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
 40 #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
 41 #include "jfr/support/jfrKlassUnloading.hpp"

 42 #include "jfr/utilities/jfrBigEndian.hpp"
 43 #include "jfr/utilities/jfrIterator.hpp"
 44 #include "jfr/utilities/jfrLinkedList.inline.hpp"
 45 #include "jfr/utilities/jfrSignal.hpp"
 46 #include "jfr/utilities/jfrThreadIterator.hpp"
 47 #include "jfr/utilities/jfrTypes.hpp"
 48 #include "jfr/writers/jfrJavaEventWriter.hpp"
 49 #include "logging/log.hpp"
 50 #include "memory/iterator.hpp"
 51 #include "memory/resourceArea.hpp"
 52 #include "runtime/atomic.hpp"
 53 #include "runtime/handles.inline.hpp"
 54 #include "runtime/interfaceSupport.inline.hpp"
 55 #include "runtime/mutex.hpp"
 56 #include "runtime/safepoint.hpp"
 57 
 58 typedef JfrCheckpointManager::BufferPtr BufferPtr;
 59 
 60 static JfrSignal _new_checkpoint;
 61 static JfrCheckpointManager* _instance = NULL;
 62 
 63 JfrCheckpointManager& JfrCheckpointManager::instance() {
 64   return *_instance;
 65 }
 66 
 67 JfrCheckpointManager* JfrCheckpointManager::create(JfrChunkWriter& cw) {
 68   assert(_instance == NULL, "invariant");
 69   _instance = new JfrCheckpointManager(cw);
 70   return _instance;
 71 }
 72 
 73 void JfrCheckpointManager::destroy() {
 74   assert(_instance != NULL, "invariant");
 75   delete _instance;
 76   _instance = NULL;
 77 }
 78 
 79 JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) :
 80   _global_mspace(NULL),
 81   _thread_local_mspace(NULL),
 82   _chunkwriter(cw) {}
 83 
 84 JfrCheckpointManager::~JfrCheckpointManager() {
 85   JfrTraceIdLoadBarrier::destroy();
 86   JfrTypeManager::destroy();
 87   delete _global_mspace;
 88   delete _thread_local_mspace;
 89 }
 90 
 91 static const size_t global_buffer_prealloc_count = 2;
 92 static const size_t global_buffer_size = 512 * K;
 93 
 94 static const size_t thread_local_buffer_prealloc_count = 16;
 95 static const size_t thread_local_buffer_size = 128;
 96 
 97 bool JfrCheckpointManager::initialize() {
 98   assert(_global_mspace == NULL, "invariant");
 99   _global_mspace =  create_mspace<JfrCheckpointMspace, JfrCheckpointManager>(global_buffer_size, 0, 0, false, this); // post-pone preallocation
100   if (_global_mspace == NULL) {
101     return false;
102   }
103   // preallocate buffer count to each of the epoch live lists
104   for (size_t i = 0; i < global_buffer_prealloc_count * 2; ++i) {
105     Buffer* const buffer = mspace_allocate(global_buffer_size, _global_mspace);
106     _global_mspace->add_to_live_list(buffer, i % 2 == 0);
107   }
108   assert(_global_mspace->free_list_is_empty(), "invariant");
109 
110   assert(_thread_local_mspace == NULL, "invariant");
111   _thread_local_mspace = new JfrThreadLocalCheckpointMspace();
112   if (_thread_local_mspace == NULL || !_thread_local_mspace->initialize(thread_local_buffer_size,
113                                                                         JFR_MSPACE_UNLIMITED_CACHE_SIZE,
114                                                                         thread_local_buffer_prealloc_count)) {
115     return false;
116   }
117   return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize();
118 }
119 
120 #ifdef ASSERT
121 static void assert_lease(const BufferPtr buffer) {
122   assert(buffer != NULL, "invariant");
123   assert(buffer->acquired_by_self(), "invariant");
124   assert(buffer->lease(), "invariant");
125 }
126 
127 static void assert_release(const BufferPtr buffer) {
128   assert(buffer != NULL, "invariant");
129   assert(buffer->lease(), "invariant");
130   assert(buffer->acquired_by_self(), "invariant");
131 }
132 
133 static void assert_retired(const BufferPtr buffer, Thread* thread) {
134   assert(buffer != NULL, "invariant");

145 BufferPtr JfrCheckpointManager::lease(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) {
146   JfrCheckpointMspace* const mspace = instance()._global_mspace;
147   assert(mspace != NULL, "invariant");
148   static const size_t max_elem_size = mspace->min_element_size(); // min is max
149   BufferPtr buffer;
150   if (size <= max_elem_size) {
151     buffer = mspace_acquire_live(size, mspace, thread, previous_epoch);
152     if (buffer != NULL) {
153       buffer->set_lease();
154       DEBUG_ONLY(assert_lease(buffer);)
155       return buffer;
156     }
157   }
158   buffer = mspace_allocate_transient_lease_to_live_list(size, mspace, thread, previous_epoch);
159   DEBUG_ONLY(assert_lease(buffer);)
160   return buffer;
161 }
162 
163 const u1 thread_local_context = 1;
164 
165 static bool is_thread_local(JfrBuffer* buffer) {
166   assert(buffer != NULL, "invariant");
167   return buffer->context() == thread_local_context;
168 }
169 
170 static void retire(JfrBuffer* buffer) {
171   DEBUG_ONLY(assert_release(buffer);)
172   buffer->clear_lease();
173   buffer->set_retired();
174 }
175 
176 /*
177  * The buffer is effectively invalidated for the thread post-return,
178  * and the caller should take means to ensure that it is not referenced.
179  */
180 static void release(JfrBuffer* buffer) {
181   DEBUG_ONLY(assert_release(buffer);)
182   if (is_thread_local(buffer)) {
183     retire(buffer);
184   } else {
185     buffer->clear_lease();
186     buffer->release();
187   }
188 }


















189 BufferPtr JfrCheckpointManager::acquire_thread_local(size_t size, Thread* thread) {
190   assert(thread != NULL, "invariant");
191   JfrBuffer* const buffer = instance()._thread_local_mspace->acquire(size, thread);

192   assert(buffer != NULL, "invariant");
193   assert(buffer->free_size() >= size, "invariant");
194   buffer->set_context(thread_local_context);
195   assert(is_thread_local(buffer), "invariant");
196   buffer->set_lease();

197   return buffer;
198 }
199 
200 BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size /* 0 */) {
201   JfrBuffer* const buffer = acquire_thread_local(size, thread);






202   DEBUG_ONLY(assert_lease(buffer);)


203   return buffer;
204 }
205 
206 BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size) {
207   assert(old != NULL, "invariant");
208   return is_thread_local(old) ? acquire_thread_local(size, thread) :
209                                 lease(thread, instance()._global_mspace->in_previous_epoch_list(old), size);
210 }
211 
212 BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t requested, Thread* thread) {
213   assert(old != NULL, "invariant");
214   assert(old->lease(), "invariant");
215   if (0 == requested) {
216     // indicates a lease is being returned
217     release(old);
218     // signal completion of a new checkpoint
219     _new_checkpoint.signal();
220     return NULL;
221   }
222   BufferPtr new_buffer = lease(old, thread, used + requested);

322 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
323 typedef ReleaseWithExcisionOp<JfrCheckpointMspace, JfrCheckpointMspace::LiveList> ReleaseOperation;
324 typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> WriteReleaseOperation;
325 
326 void JfrCheckpointManager::begin_epoch_shift() {
327   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
328   JfrTraceIdEpoch::begin_epoch_shift();
329 }
330 
331 void JfrCheckpointManager::end_epoch_shift() {
332   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
333   debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
334   JfrTraceIdEpoch::end_epoch_shift();
335   assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
336 }
337 
338 size_t JfrCheckpointManager::write() {
339   DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
340   WriteOperation wo(_chunkwriter);
341   MutexedWriteOperation mwo(wo);
342   _thread_local_mspace->iterate(mwo, true); // previous epoch list
343   assert(_global_mspace->free_list_is_empty(), "invariant");
344   ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
345   WriteReleaseOperation wro(&mwo, &ro);
346   process_live_list(wro, _global_mspace, true); // previous epoch list
347   return wo.processed();
348 }
349 
350 typedef DiscardOp<DefaultDiscarder<JfrCheckpointManager::Buffer> > DiscardOperation;
351 typedef CompositeOperation<DiscardOperation, ReleaseOperation> DiscardReleaseOperation;
352 
353 size_t JfrCheckpointManager::clear() {
354   JfrTraceIdLoadBarrier::clear();
355   clear_type_set();
356   DiscardOperation discard_operation(mutexed); // mutexed discard mode
357   _thread_local_mspace->iterate(discard_operation, true); // previous epoch list
358   ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
359   DiscardReleaseOperation discard_op(&discard_operation, &ro);
360   assert(_global_mspace->free_list_is_empty(), "invariant");
361   process_live_list(discard_op, _global_mspace, true); // previous epoch list
362   return discard_operation.elements();
363 }
364 
365 size_t JfrCheckpointManager::write_static_type_set(Thread* thread) {
366   assert(thread != NULL, "invariant");
367   JfrCheckpointWriter writer(true, thread, STATICS);
368   JfrTypeManager::write_static_types(writer);
369   return writer.used_size();
370 }
371 
372 size_t JfrCheckpointManager::write_threads(JavaThread* thread) {
373   assert(thread != NULL, "invariant");
374   // can safepoint here
375   ThreadInVMfromNative transition(thread);
376   ResourceMark rm(thread);
377   HandleMark hm(thread);

441   MutexLocker cld_lock(thread, ClassLoaderDataGraph_lock);
442   MutexLocker module_lock(thread, Module_lock);
443   return JfrTypeSet::serialize(&writer, NULL, false, true);
444 }
445 
446 size_t JfrCheckpointManager::flush_type_set() {
447   size_t elements = 0;
448   if (JfrTraceIdEpoch::has_changed_tag_state()) {
449     Thread* const thread = Thread::current();
450     if (thread->is_Java_thread()) {
451       // can safepoint here
452       ThreadInVMfromNative transition(JavaThread::cast(thread));
453       elements = ::flush_type_set(thread);
454     } else {
455       elements = ::flush_type_set(thread);
456     }
457   }
458   if (_new_checkpoint.is_signaled_with_reset()) {
459     WriteOperation wo(_chunkwriter);
460     MutexedWriteOperation mwo(wo);
461     _thread_local_mspace->iterate(mwo); // current epoch list
462     assert(_global_mspace->live_list_is_nonempty(), "invariant");
463     process_live_list(mwo, _global_mspace); // current epoch list
464   }
465   return elements;
466 }
467 
468 void JfrCheckpointManager::create_thread_blob(Thread* thread) {
469   JfrTypeManager::create_thread_blob(thread);



470 }
471 
472 void JfrCheckpointManager::write_thread_checkpoint(Thread* thread) {
473   JfrTypeManager::write_thread_checkpoint(thread);
474 }
475 
476 class JfrNotifyClosure : public ThreadClosure {
477  public:
478   void do_thread(Thread* thread) {
479     assert(thread != NULL, "invariant");
480     assert_locked_or_safepoint(Threads_lock);
481     JfrJavaEventWriter::notify(JavaThread::cast(thread));
482   }
483 };
484 
485 void JfrCheckpointManager::notify_threads() {
486   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
487   JfrNotifyClosure tc;
488   JfrJavaThreadIterator iter;
489   while (iter.has_next()) {
490     tc.do_thread(iter.next());
491   }
492 }

 22  *
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "classfile/javaClasses.inline.hpp"
 27 #include "jfr/jni/jfrJavaSupport.hpp"
 28 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
 29 #include "jfr/leakprofiler/leakProfiler.hpp"
 30 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
 31 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
 32 #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp"
 33 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
 34 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
 35 #include "jfr/recorder/jfrRecorder.hpp"
 36 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 37 #include "jfr/recorder/service/jfrOptionSet.hpp"
 38 #include "jfr/recorder/storage/jfrEpochStorage.inline.hpp"
 39 #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
 40 #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
 41 #include "jfr/support/jfrKlassUnloading.hpp"
 42 #include "jfr/support/jfrThreadLocal.hpp"
 43 #include "jfr/utilities/jfrBigEndian.hpp"
 44 #include "jfr/utilities/jfrIterator.hpp"
 45 #include "jfr/utilities/jfrLinkedList.inline.hpp"
 46 #include "jfr/utilities/jfrSignal.hpp"
 47 #include "jfr/utilities/jfrThreadIterator.hpp"

 48 #include "jfr/writers/jfrJavaEventWriter.hpp"
 49 #include "logging/log.hpp"
 50 #include "memory/iterator.hpp"
 51 #include "memory/resourceArea.hpp"
 52 #include "runtime/atomic.hpp"
 53 #include "runtime/handles.inline.hpp"
 54 #include "runtime/interfaceSupport.inline.hpp"
 55 #include "runtime/mutex.hpp"
 56 #include "runtime/safepoint.hpp"
 57 
 58 typedef JfrCheckpointManager::BufferPtr BufferPtr;
 59 
 60 static JfrSignal _new_checkpoint;
 61 static JfrCheckpointManager* _instance = NULL;
 62 
 63 JfrCheckpointManager& JfrCheckpointManager::instance() {
 64   return *_instance;
 65 }
 66 
 67 JfrCheckpointManager* JfrCheckpointManager::create(JfrChunkWriter& cw) {
 68   assert(_instance == NULL, "invariant");
 69   _instance = new JfrCheckpointManager(cw);
 70   return _instance;
 71 }
 72 
 73 void JfrCheckpointManager::destroy() {
 74   assert(_instance != NULL, "invariant");
 75   delete _instance;
 76   _instance = NULL;
 77 }
 78 
 79 JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) :
 80   _global_mspace(NULL),
 81   _java_thread_local_mspace(NULL),
 82   _chunkwriter(cw) {}
 83 
 84 JfrCheckpointManager::~JfrCheckpointManager() {
 85   JfrTraceIdLoadBarrier::destroy();
 86   JfrTypeManager::destroy();
 87   delete _global_mspace;
 88   delete _java_thread_local_mspace;
 89 }
 90 
 91 static const size_t global_buffer_prealloc_count = 2;
 92 static const size_t global_buffer_size = 512 * K;
 93 
 94 static const size_t thread_local_buffer_prealloc_count = 32;
 95 static const size_t thread_local_buffer_size = 2 * K;
 96 
 97 bool JfrCheckpointManager::initialize() {
 98   assert(_global_mspace == NULL, "invariant");
 99   _global_mspace =  create_mspace<JfrCheckpointMspace, JfrCheckpointManager>(global_buffer_size, 0, 0, false, this); // post-pone preallocation
100   if (_global_mspace == NULL) {
101     return false;
102   }
103   // preallocate buffer count to each of the epoch live lists
104   for (size_t i = 0; i < global_buffer_prealloc_count * 2; ++i) {
105     Buffer* const buffer = mspace_allocate(global_buffer_size, _global_mspace);
106     _global_mspace->add_to_live_list(buffer, i % 2 == 0);
107   }
108   assert(_global_mspace->free_list_is_empty(), "invariant");
109 
110   assert(_java_thread_local_mspace == NULL, "invariant");
111   _java_thread_local_mspace = new JfrThreadLocalCheckpointMspace();
112   if (_java_thread_local_mspace == NULL || !_java_thread_local_mspace->initialize(thread_local_buffer_size,
113                                                                                   JFR_MSPACE_UNLIMITED_CACHE_SIZE,
114                                                                                   thread_local_buffer_prealloc_count)) {
115     return false;
116   }
117   return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize();
118 }
119 
120 #ifdef ASSERT
121 static void assert_lease(const BufferPtr buffer) {
122   assert(buffer != NULL, "invariant");
123   assert(buffer->acquired_by_self(), "invariant");
124   assert(buffer->lease(), "invariant");
125 }
126 
127 static void assert_release(const BufferPtr buffer) {
128   assert(buffer != NULL, "invariant");
129   assert(buffer->lease(), "invariant");
130   assert(buffer->acquired_by_self(), "invariant");
131 }
132 
133 static void assert_retired(const BufferPtr buffer, Thread* thread) {
134   assert(buffer != NULL, "invariant");

145 BufferPtr JfrCheckpointManager::lease(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) {
146   JfrCheckpointMspace* const mspace = instance()._global_mspace;
147   assert(mspace != NULL, "invariant");
148   static const size_t max_elem_size = mspace->min_element_size(); // min is max
149   BufferPtr buffer;
150   if (size <= max_elem_size) {
151     buffer = mspace_acquire_live(size, mspace, thread, previous_epoch);
152     if (buffer != NULL) {
153       buffer->set_lease();
154       DEBUG_ONLY(assert_lease(buffer);)
155       return buffer;
156     }
157   }
158   buffer = mspace_allocate_transient_lease_to_live_list(size, mspace, thread, previous_epoch);
159   DEBUG_ONLY(assert_lease(buffer);)
160   return buffer;
161 }
162 
163 const u1 thread_local_context = 1;
164 
165 static bool is_thread_local(const JfrBuffer* buffer) {
166   assert(buffer != NULL, "invariant");
167   return buffer->context() == thread_local_context;
168 }
169 
170 static void retire(JfrBuffer* buffer) {
171   DEBUG_ONLY(assert_release(buffer);)
172   buffer->clear_lease();
173   buffer->set_retired();
174 }
175 
176 /*
177  * The buffer is effectively invalidated for the thread post-return,
178  * and the caller should take means to ensure that it is not referenced.
179  */
180 static void release(JfrBuffer* buffer) {
181   DEBUG_ONLY(assert_release(buffer);)
182   if (!is_thread_local(buffer)) {


183     buffer->clear_lease();
184     buffer->release();
185   }
186 }
187 
188 BufferPtr JfrCheckpointManager::get_thread_local(Thread* thread) {
189   assert(thread != NULL, "invariant");
190   assert(thread->is_Java_thread(), "invariant");
191   return JfrTraceIdEpoch::epoch() ? thread->jfr_thread_local()->_checkpoint_buffer_epoch_1 :
192                                     thread->jfr_thread_local()->_checkpoint_buffer_epoch_0;
193 }
194 
195 void JfrCheckpointManager::set_thread_local(Thread* thread, BufferPtr buffer) {
196   assert(thread != NULL, "invariant");
197   assert(thread->is_Java_thread(), "invariant");
198   if (JfrTraceIdEpoch::epoch()) {
199     thread->jfr_thread_local()->_checkpoint_buffer_epoch_1 = buffer;
200   } else {
201     thread->jfr_thread_local()->_checkpoint_buffer_epoch_0 = buffer;
202   }
203 }
204 
205 BufferPtr JfrCheckpointManager::acquire_thread_local(size_t size, Thread* thread) {
206   assert(thread != NULL, "invariant");
207   assert(thread->is_Java_thread(), "invariant");
208   JfrBuffer* const buffer = instance()._java_thread_local_mspace->acquire(size, thread);
209   assert(buffer != NULL, "invariant");
210   assert(buffer->free_size() >= size, "invariant");
211   buffer->set_context(thread_local_context);
212   assert(is_thread_local(buffer), "invariant");
213   buffer->set_lease();
214   set_thread_local(thread, buffer);
215   return buffer;
216 }
217 
218 BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size /* 0 */) {
219   JfrBuffer* buffer = get_thread_local(thread);
220   if (buffer == NULL) {
221     buffer = acquire_thread_local(size, thread);
222   } else if (buffer->free_size() < size) {
223     retire(buffer);
224     buffer = acquire_thread_local(size, thread);
225   }
226   DEBUG_ONLY(assert_lease(buffer);)
227   assert(buffer->free_size() >= size, "invariant");
228   assert(get_thread_local(thread) == buffer, "invariant");
229   return buffer;
230 }
231 
232 BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size) {
233   assert(old != NULL, "invariant");
234   return is_thread_local(old) ? acquire_thread_local(size, thread) :
235                                 lease(thread, instance()._global_mspace->in_previous_epoch_list(old), size);
236 }
237 
238 BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t requested, Thread* thread) {
239   assert(old != NULL, "invariant");
240   assert(old->lease(), "invariant");
241   if (0 == requested) {
242     // indicates a lease is being returned
243     release(old);
244     // signal completion of a new checkpoint
245     _new_checkpoint.signal();
246     return NULL;
247   }
248   BufferPtr new_buffer = lease(old, thread, used + requested);

348 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
349 typedef ReleaseWithExcisionOp<JfrCheckpointMspace, JfrCheckpointMspace::LiveList> ReleaseOperation;
350 typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> WriteReleaseOperation;
351 
352 void JfrCheckpointManager::begin_epoch_shift() {
353   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
354   JfrTraceIdEpoch::begin_epoch_shift();
355 }
356 
357 void JfrCheckpointManager::end_epoch_shift() {
358   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
359   debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
360   JfrTraceIdEpoch::end_epoch_shift();
361   assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
362 }
363 
364 size_t JfrCheckpointManager::write() {
365   DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
366   WriteOperation wo(_chunkwriter);
367   MutexedWriteOperation mwo(wo);
368   _java_thread_local_mspace->iterate(mwo, true); // previous epoch list
369   assert(_global_mspace->free_list_is_empty(), "invariant");
370   ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
371   WriteReleaseOperation wro(&mwo, &ro);
372   process_live_list(wro, _global_mspace, true); // previous epoch list
373   return wo.processed();
374 }
375 
376 typedef DiscardOp<DefaultDiscarder<JfrCheckpointManager::Buffer> > DiscardOperation;
377 typedef CompositeOperation<DiscardOperation, ReleaseOperation> DiscardReleaseOperation;
378 
379 size_t JfrCheckpointManager::clear() {
380   JfrTraceIdLoadBarrier::clear();
381   clear_type_set();
382   DiscardOperation discard_operation(mutexed); // mutexed discard mode
383   _java_thread_local_mspace->iterate(discard_operation, true); // previous epoch list
384   ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
385   DiscardReleaseOperation discard_op(&discard_operation, &ro);
386   assert(_global_mspace->free_list_is_empty(), "invariant");
387   process_live_list(discard_op, _global_mspace, true); // previous epoch list
388   return discard_operation.elements();
389 }
390 
391 size_t JfrCheckpointManager::write_static_type_set(Thread* thread) {
392   assert(thread != NULL, "invariant");
393   JfrCheckpointWriter writer(true, thread, STATICS);
394   JfrTypeManager::write_static_types(writer);
395   return writer.used_size();
396 }
397 
398 size_t JfrCheckpointManager::write_threads(JavaThread* thread) {
399   assert(thread != NULL, "invariant");
400   // can safepoint here
401   ThreadInVMfromNative transition(thread);
402   ResourceMark rm(thread);
403   HandleMark hm(thread);

467   MutexLocker cld_lock(thread, ClassLoaderDataGraph_lock);
468   MutexLocker module_lock(thread, Module_lock);
469   return JfrTypeSet::serialize(&writer, NULL, false, true);
470 }
471 
472 size_t JfrCheckpointManager::flush_type_set() {
473   size_t elements = 0;
474   if (JfrTraceIdEpoch::has_changed_tag_state()) {
475     Thread* const thread = Thread::current();
476     if (thread->is_Java_thread()) {
477       // can safepoint here
478       ThreadInVMfromNative transition(JavaThread::cast(thread));
479       elements = ::flush_type_set(thread);
480     } else {
481       elements = ::flush_type_set(thread);
482     }
483   }
484   if (_new_checkpoint.is_signaled_with_reset()) {
485     WriteOperation wo(_chunkwriter);
486     MutexedWriteOperation mwo(wo);
487     _java_thread_local_mspace->iterate(mwo); // current epoch list
488     assert(_global_mspace->live_list_is_nonempty(), "invariant");
489     process_live_list(mwo, _global_mspace); // current epoch list
490   }
491   return elements;
492 }
493 
494 JfrBlobHandle JfrCheckpointManager::create_thread_blob(JavaThread* jt, traceid tid, oop vthread) {
495   assert(jt != NULL, "invariant");
496   assert(Thread::current() == jt, "invariant");
497   DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
498   return JfrTypeManager::create_thread_blob(jt, tid, vthread);
499 }
500 
501 void JfrCheckpointManager::write_checkpoint(Thread* thread, traceid tid, oop vthread) {
502   JfrTypeManager::write_checkpoint(thread, tid, vthread);
503 }
504 
505 class JfrNotifyClosure : public ThreadClosure {
506  public:
507   void do_thread(Thread* thread) {
508     assert(thread != NULL, "invariant");
509     assert_locked_or_safepoint(Threads_lock);
510     JfrJavaEventWriter::notify(JavaThread::cast(thread));
511   }
512 };
513 
514 void JfrCheckpointManager::notify_threads() {
515   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
516   JfrNotifyClosure tc;
517   JfrJavaThreadIterator iter;
518   while (iter.has_next()) {
519     tc.do_thread(iter.next());
520   }
521 }
< prev index next >