< prev index next >

src/share/vm/utilities/ostream.cpp

Print this page

        

@@ -25,12 +25,14 @@
 #include "precompiled.hpp"
 #include "compiler/compileLog.hpp"
 #include "gc_implementation/shared/gcId.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
 #include "utilities/defaultStream.hpp"
+#include "utilities/globalDefinitions.hpp"
 #include "utilities/ostream.hpp"
 #include "utilities/top.hpp"
 #include "utilities/xmlstream.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "os_linux.inline.hpp"

@@ -799,10 +801,17 @@
 gcLogFileStream::gcLogFileStream(const char* file_name) {
   _cur_file_num = 0;
   _bytes_written = 0L;
   _file_name = make_log_name(file_name, NULL);
 
+  if (AsyncGCLogging) {
+    //the mutex ranks higher than Mutex::safepoint
+    _lock = new Mutex(Mutex::leaf, "GCLogRingBuffer");
+    _reader = new GCLogEvent("gcLogRingBuf0", GCLogBufferSize);
+    _writer = new GCLogEvent("gcLogRingBuf1", GCLogBufferSize);
+  }
+
   if (_file_name == NULL) {
     warning("Cannot open file %s: file name is too long.\n", file_name);
     _need_close = false;
     UseGCLogFileRotation = false;
     return;

@@ -816,25 +825,57 @@
   } else {
     _file = fopen(_file_name, "w");
   }
   if (_file != NULL) {
     _need_close = true;
+
+    // temporarily disable AsyncGCLogging, because ThreadLocalStorage::thread()
+    // hasn't been initialized yet.
+    FlagSetting saver(AsyncGCLogging, false);
     dump_loggc_header();
   } else {
     warning("Cannot open file %s due to %s\n", _file_name, strerror(errno));
     _need_close = false;
   }
 }
 
-void gcLogFileStream::write(const char* s, size_t len) {
+void gcLogFileStream::flush_log() {
+  assert(AsyncGCLogging, "flush_log can only be used when AsyncGCLogging is on!");
+
+  _reader->print_log_on(this);
+  _reader->reset();
+
+  {
+    MutexLockerEx ml(_lock, true/*no_safepoint_check*/);
+    swap(_reader, _writer);
+  }
+}
+
+void gcLogFileStream::write_blocking(const char* s, size_t len) {
+#ifndef PRODUCT
+  if (DelayInGCLogging > 0) {
+     os::naked_short_sleep((jlong)DelayInGCLogging);
+  }
+#endif
+
   if (_file != NULL) {
     size_t count = fwrite(s, 1, len, _file);
     _bytes_written += count;
   }
   update_position(s, len);
 }
 
+void gcLogFileStream::write(const char* s, size_t len) {
+  if (AsyncGCLogging) {
+    MutexLockerEx ml(_lock, true/*no_safepoint_check*/);
+    _writer->log(NULL, s, len);
+  }
+  else {
+    write_blocking(s, len);
+  }
+}
+
 // rotate_log must be called from VMThread at safepoint. In case need change parameters
 // for gc log rotation from thread other than VMThread, a sub type of VM_Operation
 // should be created and be submitted to VMThread's operation queue. DO NOT call this
 // function directly. Currently, it is safe to rotate log at safepoint through VMThread.
 // That is, no mutator threads and concurrent GC threads run parallel with VMThread to

@@ -1547,6 +1588,12 @@
 
   int result = os::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in));
   return (result >= 0);
 }
 
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+void Test_gcLogFileStream() {
+}
+#endif
 #endif
< prev index next >