1.1 --- a/src/share/vm/utilities/ostream.cpp Mon Nov 18 23:41:06 2019 -0500 1.2 +++ b/src/share/vm/utilities/ostream.cpp Thu Apr 09 13:07:11 2020 +0000 1.3 @@ -27,6 +27,7 @@ 1.4 #include "gc_implementation/shared/gcId.hpp" 1.5 #include "oops/oop.inline.hpp" 1.6 #include "runtime/arguments.hpp" 1.7 +#include "runtime/mutexLocker.hpp" 1.8 #include "runtime/os.hpp" 1.9 #include "utilities/defaultStream.hpp" 1.10 #include "utilities/ostream.hpp" 1.11 @@ -794,9 +795,11 @@ 1.12 FREE_C_HEAP_ARRAY(char, _file_name, mtInternal); 1.13 _file_name = NULL; 1.14 } 1.15 + 1.16 + delete _file_lock; 1.17 } 1.18 1.19 -gcLogFileStream::gcLogFileStream(const char* file_name) { 1.20 +gcLogFileStream::gcLogFileStream(const char* file_name) : _file_lock(NULL) { 1.21 _cur_file_num = 0; 1.22 _bytes_written = 0L; 1.23 _file_name = make_log_name(file_name, NULL); 1.24 @@ -819,6 +822,10 @@ 1.25 if (_file != NULL) { 1.26 _need_close = true; 1.27 dump_loggc_header(); 1.28 + 1.29 + if (UseGCLogFileRotation) { 1.30 + _file_lock = new Mutex(Mutex::leaf, "GCLogFile"); 1.31 + } 1.32 } else { 1.33 warning("Cannot open file %s due to %s\n", _file_name, strerror(errno)); 1.34 _need_close = false; 1.35 @@ -827,21 +834,54 @@ 1.36 1.37 void gcLogFileStream::write(const char* s, size_t len) { 1.38 if (_file != NULL) { 1.39 - size_t count = fwrite(s, 1, len, _file); 1.40 - _bytes_written += count; 1.41 + // we can't use Thread::current() here because thread may be NULL 1.42 + // in early stage(ostream_init_log) 1.43 + Thread* thread = ThreadLocalStorage::thread(); 1.44 + 1.45 + // avoid the mutex in the following cases 1.46 + // 1) ThreadLocalStorage::thread() hasn't been initialized 1.47 + // 2) _file_lock is not in use. 1.48 + // 3) current() is VMThread and its reentry flag is set 1.49 + if (!thread || !_file_lock || (thread->is_VM_thread() 1.50 + && ((VMThread* )thread)->is_gclog_reentry())) { 1.51 + size_t count = fwrite(s, 1, len, _file); 1.52 + _bytes_written += count; 1.53 + } 1.54 + else { 1.55 + MutexLockerEx ml(_file_lock, Mutex::_no_safepoint_check_flag); 1.56 + size_t count = fwrite(s, 1, len, _file); 1.57 + _bytes_written += count; 1.58 + } 1.59 } 1.60 update_position(s, len); 1.61 } 1.62 1.63 -// rotate_log must be called from VMThread at safepoint. In case need change parameters 1.64 +// rotate_log must be called from VMThread at a safepoint. In case need change parameters 1.65 // for gc log rotation from thread other than VMThread, a sub type of VM_Operation 1.66 // should be created and be submitted to VMThread's operation queue. DO NOT call this 1.67 -// function directly. Currently, it is safe to rotate log at safepoint through VMThread. 1.68 -// That is, no mutator threads and concurrent GC threads run parallel with VMThread to 1.69 -// write to gc log file at safepoint. If in future, changes made for mutator threads or 1.70 -// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log 1.71 -// must be synchronized. 1.72 +// function directly. It is safe to rotate log through VMThread because 1.73 +// no mutator threads run concurrently with the VMThread, and GC threads that run 1.74 +// concurrently with the VMThread are synchronized in write and rotate_log via _file_lock. 1.75 +// rotate_log can write log entries, so write supports reentry for it. 1.76 void gcLogFileStream::rotate_log(bool force, outputStream* out) { 1.77 + #ifdef ASSERT 1.78 + Thread *thread = Thread::current(); 1.79 + assert(thread == NULL || 1.80 + (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()), 1.81 + "Must be VMThread at safepoint"); 1.82 + #endif 1.83 + 1.84 + VMThread* vmthread = VMThread::vm_thread(); 1.85 + { 1.86 + // nop if _file_lock is NULL. 1.87 + MutexLockerEx ml(_file_lock, Mutex::_no_safepoint_check_flag); 1.88 + vmthread->set_gclog_reentry(true); 1.89 + rotate_log_impl(force, out); 1.90 + vmthread->set_gclog_reentry(false); 1.91 + } 1.92 +} 1.93 + 1.94 +void gcLogFileStream::rotate_log_impl(bool force, outputStream* out) { 1.95 char time_msg[O_BUFLEN]; 1.96 char time_str[EXTRACHARLEN]; 1.97 char current_file_name[JVM_MAXPATHLEN]; 1.98 @@ -851,12 +891,6 @@ 1.99 return; 1.100 } 1.101 1.102 -#ifdef ASSERT 1.103 - Thread *thread = Thread::current(); 1.104 - assert(thread == NULL || 1.105 - (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()), 1.106 - "Must be VMThread at safepoint"); 1.107 -#endif 1.108 if (NumberOfGCLogFiles == 1) { 1.109 // rotate in same file 1.110 rewind();