--- old/src/share/vm/utilities/ostream.cpp 2020-01-27 23:21:09.000000000 -0800 +++ new/src/share/vm/utilities/ostream.cpp 2020-01-27 23:21:09.000000000 -0800 @@ -27,8 +27,10 @@ #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" @@ -801,6 +803,13 @@ _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; @@ -818,6 +827,10 @@ } 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)); @@ -825,7 +838,25 @@ } } -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; @@ -833,6 +864,16 @@ 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 @@ -1549,4 +1590,10 @@ return (result >= 0); } +/////////////// Unit tests /////////////// + +#ifndef PRODUCT +void Test_gcLogFileStream() { +} +#endif #endif