Mutual exclusions on emergency dump in relation to flush() JEP-349-branch
authormgronlun
Sun, 13 Oct 2019 16:46:15 +0200
branchJEP-349-branch
changeset 58578 7b89c53db169
parent 58577 7e0f81f63890
child 58640 496bbf554c5c
Mutual exclusions on emergency dump in relation to flush()
src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp
src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Sun Oct 13 12:36:51 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Sun Oct 13 16:46:15 2019 +0200
@@ -322,7 +322,6 @@
 void JfrEmergencyDump::on_vm_error(const char* repository_path) {
   assert(repository_path != NULL, "invariant");
   ResourceMark rm;
-
   const fio_fd emergency_fd = emergency_dump_file_descriptor();
   if (emergency_fd != invalid_fd) {
     RepositoryIterator iterator(repository_path, strlen(repository_path));
--- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp	Sun Oct 13 12:36:51 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp	Sun Oct 13 16:46:15 2019 +0200
@@ -82,7 +82,6 @@
 }
 
 void JfrRepository::on_vm_error() {
-
   if (_path == NULL) {
     // completed already
     return;
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Sun Oct 13 12:36:51 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Sun Oct 13 16:46:15 2019 +0200
@@ -508,13 +508,11 @@
 
 void JfrRecorderService::vm_error_rotation() {
   if (_chunkwriter.is_valid()) {
-    pre_safepoint_write();
-    // Do not attempt safepoint dependent operations during emergency dump.
-    // Optimistically write tagged artifacts.
-    _checkpoint_manager.shift_epoch();
-    // update time
+    Thread* const t = Thread::current();
+    _storage.flush_regular_buffer(t->jfr_thread_local()->native_buffer(), t);
+    invoke_flush(t);
     _chunkwriter.set_time_stamp();
-    post_safepoint_write();
+    _repository.close_chunk();
     assert(!_chunkwriter.is_valid(), "invariant");
     _repository.on_vm_error();
   }
@@ -619,33 +617,31 @@
   _repository.close_chunk();
 }
 
-static JfrBuffer* thread_local_buffer() {
-  return Thread::current()->jfr_thread_local()->native_buffer();
+static JfrBuffer* thread_local_buffer(Thread* t) {
+  assert(t != NULL, "invariant");
+  return t->jfr_thread_local()->native_buffer();
 }
 
-static void reset_buffer(JfrBuffer* buffer) {
+static void reset_buffer(JfrBuffer* buffer, Thread* t) {
   assert(buffer != NULL, "invariant");
-  assert(buffer == thread_local_buffer(), "invariant");
+  assert(t != NULL, "invariant");
+  assert(buffer == thread_local_buffer(t), "invariant");
   buffer->set_pos(const_cast<u1*>(buffer->top()));
-  assert(buffer->empty(), "invariant");
 }
 
-static void reset_thread_local_buffer() {
-  reset_buffer(thread_local_buffer());
+static void reset_thread_local_buffer(Thread* t) {
+  reset_buffer(thread_local_buffer(t), t);
 }
 
-static void write_thread_local_buffer(JfrChunkWriter& chunkwriter) {
-  JfrBuffer * const buffer = thread_local_buffer();
+static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) {
+  JfrBuffer * const buffer = thread_local_buffer(t);
   assert(buffer != NULL, "invariant");
   if (!buffer->empty()) {
     chunkwriter.write_unbuffered(buffer->top(), buffer->pos() - buffer->top());
-    reset_buffer(buffer);
+    reset_buffer(buffer, t);
   }
-  assert(buffer->empty(), "invariant");
 }
 
-static bool write_metadata_in_flushpoint = false;
-
 size_t JfrRecorderService::flush() {
   size_t total_elements = flush_metadata(_chunkwriter);
   const size_t storage_elements = flush_storage(_storage, _chunkwriter);
@@ -671,19 +667,29 @@
 typedef Content<EventFlush, JfrRecorderService, &JfrRecorderService::flush> FlushFunctor;
 typedef WriteContent<FlushFunctor> Flush;
 
-void JfrRecorderService::flushpoint() {
+void JfrRecorderService::invoke_flush(Thread* t) {
+  assert(t != NULL, "invariant");
   assert(_chunkwriter.is_valid(), "invariant");
-  ResourceMark rm;
-  HandleMark hm;
+  ResourceMark rm(t);
+  HandleMark hm(t);
   ++flushpoint_id;
-  reset_thread_local_buffer();
+  reset_thread_local_buffer(t);
   FlushFunctor flushpoint(*this);
   Flush fl(_chunkwriter, flushpoint);
   invoke_with_flush_event(fl);
-  write_thread_local_buffer(_chunkwriter);
+  write_thread_local_buffer(_chunkwriter, t);
   _repository.flush_chunk();
 }
 
+void JfrRecorderService::flushpoint() {
+  Thread* const t = Thread::current();
+  RotationLock rl(t);
+  if (rl.not_acquired() || !_chunkwriter.is_valid()) {
+    return;
+  }
+  invoke_flush(t);
+}
+
 void JfrRecorderService::process_full_buffers() {
   if (_chunkwriter.is_valid()) {
     _storage.write_full();
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp	Sun Oct 13 12:36:51 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp	Sun Oct 13 16:46:15 2019 +0200
@@ -33,6 +33,7 @@
 class JfrStackTraceRepository;
 class JfrStorage;
 class JfrStringPool;
+class Thread;
 
 class JfrRecorderService : public StackObj {
  private:
@@ -49,6 +50,7 @@
   void finalize_current_chunk();
   void prepare_for_vm_error_rotation();
   void vm_error_rotation();
+  void invoke_flush(Thread* t);
 
   void clear();
   void pre_safepoint_clear();