src/share/vm/utilities/ostream.cpp

changeset 9904
4698900b8221
parent 9478
f3108e56b502
child 9906
0df63a32f7bb
     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();

mercurial