1 Star 0 Fork 80

xuyuchao/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
8229517-Support-for-optional-asynchronous-buffered-l.patch 24.01 KB
一键复制 编辑 原始数据 按行查看 历史
eapen 提交于 2023-01-11 10:00 . I69W1Y: Add feature and bug fix for 8u352
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
From 577f318d824d91e5deb8b6b82dd211583cb93cac Mon Sep 17 00:00:00 2001
From: eapen <zhangyipeng7@huawei.com>
Date: Thu, 15 Dec 2022 10:37:31 +0800
Subject: [PATCH 18/33] I68TO2: 8229517: Support for optional asynchronous/buffered
logging
---
hotspot/src/os/windows/vm/os_windows.cpp | 1 +
hotspot/src/share/vm/runtime/arguments.cpp | 10 ++
hotspot/src/share/vm/runtime/globals.hpp | 9 ++
hotspot/src/share/vm/runtime/init.cpp | 2 +
hotspot/src/share/vm/runtime/logAsyncWriter.cpp | 164 ++++++++++++++++++++++++
hotspot/src/share/vm/runtime/logAsyncWriter.hpp | 159 +++++++++++++++++++++++
hotspot/src/share/vm/runtime/os.hpp | 1 +
hotspot/src/share/vm/runtime/thread.cpp | 26 +++-
hotspot/src/share/vm/runtime/vmStructs.cpp | 2 +
hotspot/src/share/vm/utilities/linkedlist.hpp | 47 +++++--
hotspot/src/share/vm/utilities/ostream.cpp | 26 ++++
hotspot/src/share/vm/utilities/ostream.hpp | 3 +
12 files changed, 440 insertions(+), 10 deletions(-)
create mode 100644 hotspot/src/share/vm/runtime/logAsyncWriter.cpp
create mode 100644 hotspot/src/share/vm/runtime/logAsyncWriter.hpp
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 25122de..cc31126 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -562,6 +562,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
case os::pgc_thread:
case os::cgc_thread:
case os::watcher_thread:
+ case os::asynclog_thread:
if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
break;
}
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 91e2ce0..fba3d4b 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -2269,6 +2269,16 @@ bool Arguments::verify_percentage(uintx value, const char* name) {
// no gc log rotation when log file not supplied or
// NumberOfGCLogFiles is 0
void check_gclog_consistency() {
+ if (UseAsyncGCLog) {
+ if (Arguments::gc_log_filename() == NULL) {
+ jio_fprintf(defaultStream::output_stream(),
+ "To enable Async GC log, use -Xloggc:<filename> -XX:UseAsyncGCLog\n"
+ "Async GC log is turned off\n");
+ UseAsyncGCLog = false;
+
+ }
+ }
+
if (UseGCLogFileRotation) {
if ((Arguments::gc_log_filename() == NULL) || (NumberOfGCLogFiles == 0)) {
jio_fprintf(defaultStream::output_stream(),
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 41b1392..10e4e7f 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -4104,6 +4104,15 @@ class CommandLineFlags {
\
JFR_ONLY(product(bool, LogJFR, false, \
"Enable JFR logging (consider +Verbose)")) \
+ \
+ product(bool, UseAsyncGCLog, false, \
+ "Enable asynchronous GC logging") \
+ \
+ product(uintx, AsyncLogBufferSize, 2*M, \
+ "Memory budget (in bytes) for the buffer of Asynchronous") \
+ \
+ diagnostic(bool, PrintAsyncGCLog, false, \
+ "Print some information of Async GC Log") \
/*
* Macros for factoring of globals
diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp
index d2e0f22..b185409 100644
--- a/hotspot/src/share/vm/runtime/init.cpp
+++ b/hotspot/src/share/vm/runtime/init.cpp
@@ -32,6 +32,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/icache.hpp"
#include "runtime/init.hpp"
+#include "runtime/logAsyncWriter.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/sharedRuntime.hpp"
#include "services/memTracker.hpp"
@@ -106,6 +107,7 @@ jint init_globals() {
if (status != JNI_OK)
return status;
+ AsyncLogWriter::initialize();
interpreter_init(); // before any methods loaded
invocationCounter_init(); // before any methods loaded
marksweep_init();
diff --git a/hotspot/src/share/vm/runtime/logAsyncWriter.cpp b/hotspot/src/share/vm/runtime/logAsyncWriter.cpp
new file mode 100644
index 0000000..750a23f
--- /dev/null
+++ b/hotspot/src/share/vm/runtime/logAsyncWriter.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#include "precompiled.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/logAsyncWriter.hpp"
+#include "utilities/ostream.hpp"
+
+class AsyncLogWriter::AsyncLogLocker : public StackObj {
+ public:
+ AsyncLogLocker() {
+ assert(_instance != NULL, "AsyncLogWriter::_lock is unavailable");
+ _instance->_lock.wait();
+ }
+
+ ~AsyncLogLocker() {
+ _instance->_lock.signal();
+ }
+};
+
+void AsyncLogWriter::enqueue_locked(const AsyncLogMessage& msg) {
+ if (_buffer.size() >= _buffer_max_size) {
+ // drop the enqueueing message.
+ os::free(msg.message());
+ return;
+ }
+
+ assert(_buffer.size() < _buffer_max_size, "_buffer is over-sized.");
+ _buffer.push_back(msg);
+ _sem.signal();
+}
+
+void AsyncLogWriter::enqueue(const char* msg) {
+ AsyncLogMessage m(os::strdup(msg));
+
+ { // critical area
+ AsyncLogLocker locker;
+ enqueue_locked(m);
+ }
+}
+
+AsyncLogWriter::AsyncLogWriter()
+ : NamedThread(),
+ _lock(1), _sem(0), _io_sem(1),
+ _initialized(false),
+ _buffer_max_size(AsyncLogBufferSize / sizeof(AsyncLogMessage)) {
+ if (os::create_thread(this, os::asynclog_thread)) {
+ _initialized = true;
+ set_name("AsyncLog Thread");
+ } else {
+ if (PrintAsyncGCLog) {
+ tty->print_cr("AsyncLogging failed to create thread. Falling back to synchronous logging.");
+ }
+ }
+
+ if (PrintAsyncGCLog) {
+ tty->print_cr("The maximum entries of AsyncLogBuffer: " SIZE_FORMAT ", estimated memory use: " SIZE_FORMAT " bytes",
+ _buffer_max_size, AsyncLogBufferSize);
+ }
+}
+
+void AsyncLogWriter::write() {
+ // Use kind of copy-and-swap idiom here.
+ // Empty 'logs' swaps the content with _buffer.
+ // Along with logs destruction, all processed messages are deleted.
+ //
+ // The operation 'pop_all()' is done in O(1). All I/O jobs are then performed without
+ // lock protection. This guarantees I/O jobs don't block logsites.
+ AsyncLogBuffer logs;
+ bool own_io = false;
+
+ { // critical region
+ AsyncLogLocker locker;
+
+ _buffer.pop_all(&logs);
+ own_io = _io_sem.trywait();
+ }
+
+ LinkedListIterator<AsyncLogMessage> it(logs.head());
+ if (!own_io) {
+ _io_sem.wait();
+ }
+
+ bool flush = false;
+ while (!it.is_empty()) {
+ AsyncLogMessage* e = it.next();
+ char* msg = e->message();
+
+ if (msg != NULL) {
+ flush = true;
+ ((gcLogFileStream*)gclog_or_tty)->write_blocking(msg, strlen(msg));
+ os::free(msg);
+ }
+ }
+ if (flush) {
+ ((gcLogFileStream*)gclog_or_tty)->fileStream::flush();
+ }
+ _io_sem.signal();
+}
+
+void AsyncLogWriter::run() {
+ while (true) {
+ // The value of a semphore cannot be negative. Therefore, the current thread falls asleep
+ // when its value is zero. It will be waken up when new messages are enqueued.
+ _sem.wait();
+ write();
+ }
+}
+
+AsyncLogWriter* AsyncLogWriter::_instance = NULL;
+
+void AsyncLogWriter::initialize() {
+ if (!UseAsyncGCLog) return;
+
+ assert(_instance == NULL, "initialize() should only be invoked once.");
+
+ AsyncLogWriter* self = new AsyncLogWriter();
+ if (self->_initialized) {
+ OrderAccess::release_store_ptr(&AsyncLogWriter::_instance, self);
+ os::start_thread(self);
+ if (PrintAsyncGCLog) {
+ tty->print_cr("Async logging thread started.");
+ }
+ }
+}
+
+AsyncLogWriter* AsyncLogWriter::instance() {
+ return _instance;
+}
+
+// write() acquires and releases _io_sem even _buffer is empty.
+// This guarantees all logging I/O of dequeued messages are done when it returns.
+void AsyncLogWriter::flush() {
+ if (_instance != NULL) {
+ _instance->write();
+ }
+}
+
+void AsyncLogWriter::print_on(outputStream* st) const{
+ st->print("\"%s\" ", name());
+ Thread::print_on(st);
+ st->cr();
+}
diff --git a/hotspot/src/share/vm/runtime/logAsyncWriter.hpp b/hotspot/src/share/vm/runtime/logAsyncWriter.hpp
new file mode 100644
index 0000000..5242426
--- /dev/null
+++ b/hotspot/src/share/vm/runtime/logAsyncWriter.hpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#ifndef SHARE_VM_RUNTIME_LOGASYNCWRITER_HPP
+#define SHARE_VM_RUNTIME_LOGASYNCWRITER_HPP
+#include "memory/resourceArea.hpp"
+#include "runtime/semaphore.hpp"
+#include "utilities/linkedlist.hpp"
+
+template <typename E, MEMFLAGS F>
+class LinkedListDeque : private LinkedListImpl<E, ResourceObj::C_HEAP, F> {
+ private:
+ LinkedListNode<E>* _tail;
+ size_t _size;
+
+ public:
+ LinkedListDeque() : _tail(NULL), _size(0) {}
+ void push_back(const E& e) {
+ if (!_tail) {
+ _tail = this->add(e);
+ } else {
+ _tail = this->insert_after(e, _tail);
+ }
+
+ ++_size;
+ }
+
+ // pop all elements to logs.
+ void pop_all(LinkedList<E>* logs) {
+ logs->move(static_cast<LinkedList<E>* >(this));
+ _tail = NULL;
+ _size = 0;
+ }
+
+ void pop_all(LinkedListDeque<E, F>* logs) {
+ logs->_size = _size;
+ logs->_tail = _tail;
+ pop_all(static_cast<LinkedList<E>* >(logs));
+ }
+
+ void pop_front() {
+ LinkedListNode<E>* h = this->unlink_head();
+ if (h == _tail) {
+ _tail = NULL;
+ }
+
+ if (h != NULL) {
+ --_size;
+ this->delete_node(h);
+ }
+ }
+
+ size_t size() const { return _size; }
+
+ const E* front() const {
+ return this->_head == NULL ? NULL : this->_head->peek();
+ }
+
+ const E* back() const {
+ return _tail == NULL ? NULL : _tail->peek();
+ }
+
+ LinkedListNode<E>* head() const {
+ return this->_head;
+ }
+};
+
+class AsyncLogMessage {
+ char* _message;
+
+public:
+ AsyncLogMessage(char* msg)
+ : _message(msg) {}
+
+ // placeholder for LinkedListImpl.
+ bool equals(const AsyncLogMessage& o) const { return false; }
+
+ char* message() const { return _message; }
+};
+
+typedef LinkedListDeque<AsyncLogMessage, mtInternal> AsyncLogBuffer;
+
+//
+// ASYNC LOGGING SUPPORT
+//
+// Summary:
+// Async Logging is working on the basis of singleton AsyncLogWriter, which manages an intermediate buffer and a flushing thread.
+//
+// Interface:
+//
+// initialize() is called once when JVM is initialized. It creates and initializes the singleton instance of AsyncLogWriter.
+// Once async logging is established, there's no way to turn it off.
+//
+// instance() is MT-safe and returns the pointer of the singleton instance if and only if async logging is enabled and has well
+// initialized. Clients can use its return value to determine async logging is established or not.
+//
+// The basic operation of AsyncLogWriter is enqueue(). 2 overloading versions of it are provided to match LogOutput::write().
+// They are both MT-safe and non-blocking. Derived classes of LogOutput can invoke the corresponding enqueue() in write() and
+// return 0. AsyncLogWriter is responsible of copying neccessary data.
+//
+// The static member function flush() is designated to flush out all pending messages when JVM is terminating.
+// In normal JVM termination, flush() is invoked in LogConfiguration::finalize(). flush() is MT-safe and can be invoked arbitrary
+// times. It is no-op if async logging is not established.
+//
+class AsyncLogWriter : public NamedThread {
+ class AsyncLogLocker;
+
+ static AsyncLogWriter* _instance;
+ // _lock(1) denotes a critional region.
+ Semaphore _lock;
+ // _sem is a semaphore whose value denotes how many messages have been enqueued.
+ // It decreases in AsyncLogWriter::run()
+ Semaphore _sem;
+ // A lock of IO
+ Semaphore _io_sem;
+
+ volatile bool _initialized;
+ AsyncLogBuffer _buffer;
+
+ const size_t _buffer_max_size;
+
+ AsyncLogWriter();
+ void enqueue_locked(const AsyncLogMessage& msg);
+ void write();
+ void run();
+
+ public:
+ void enqueue(const char* msg);
+
+ static AsyncLogWriter* instance();
+ static void initialize();
+ static void flush();
+ // Printing
+ void print_on(outputStream* st) const;
+
+};
+
+#endif // SHARE_LOGGING_LOGASYNCWRITER_HPP
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index acc57f4..5f41e96 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -463,6 +463,7 @@ class os: AllStatic {
java_thread,
compiler_thread,
watcher_thread,
+ asynclog_thread, // dedicated to flushing logs
os_thread
};
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
index cacab59..61627e4 100644
--- a/hotspot/src/share/vm/runtime/thread.cpp
+++ b/hotspot/src/share/vm/runtime/thread.cpp
@@ -57,6 +57,7 @@
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniPeriodicChecker.hpp"
+#include "runtime/logAsyncWriter.hpp"
#include "runtime/memprofiler.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/objectMonitor.hpp"
@@ -881,7 +882,9 @@ void Thread::print_on_error(outputStream* st, char* buf, int buflen) const {
else if (is_GC_task_thread()) st->print("GCTaskThread");
else if (is_Watcher_thread()) st->print("WatcherThread");
else if (is_ConcurrentGC_thread()) st->print("ConcurrentGCThread");
- else st->print("Thread");
+ else if (this == AsyncLogWriter::instance()) {
+ st->print("%s", this->name());
+ } else st->print("Thread");
st->print(" [stack: " PTR_FORMAT "," PTR_FORMAT "]",
_stack_base - _stack_size, _stack_base);
@@ -4387,6 +4390,12 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format
st->cr();
}
CompileBroker::print_compiler_threads_on(st);
+ if (UseAsyncGCLog) {
+ AsyncLogWriter* aio_writer = AsyncLogWriter::instance();
+ if (aio_writer != NULL) {
+ aio_writer->print_on(st);
+ }
+ }
st->flush();
}
@@ -4432,6 +4441,21 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, int b
wt->print_on_error(st, buf, buflen);
st->cr();
}
+
+ if (UseAsyncGCLog) {
+ AsyncLogWriter* aio_writer = AsyncLogWriter::instance();
+ if (aio_writer != NULL) {
+ bool is_current = (current == aio_writer);
+ found_current = found_current || is_current;
+ st->print("%s", is_current ? "=>" : " ");
+
+ st->print(PTR_FORMAT, aio_writer);
+ st->print(" ");
+ aio_writer->print_on_error(st, buf, buflen);
+ st->cr();
+ }
+ }
+
if (!found_current) {
st->cr();
st->print("=>" PTR_FORMAT " (exited) ", current);
diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp
index ab20f5c..5d1cf2b 100644
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp
@@ -97,6 +97,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
+#include "runtime/logAsyncWriter.hpp"
#include "runtime/virtualspace.hpp"
#include "runtime/vmStructs.hpp"
#include "utilities/array.hpp"
@@ -1599,6 +1600,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
declare_type(Thread, ThreadShadow) \
declare_type(NamedThread, Thread) \
declare_type(WatcherThread, Thread) \
+ declare_type(AsyncLogWriter, Thread) \
declare_type(JavaThread, Thread) \
declare_type(JvmtiAgentThread, JavaThread) \
declare_type(ServiceThread, JavaThread) \
diff --git a/hotspot/src/share/vm/utilities/linkedlist.hpp b/hotspot/src/share/vm/utilities/linkedlist.hpp
index a76c15c..f4f2a9b 100644
--- a/hotspot/src/share/vm/utilities/linkedlist.hpp
+++ b/hotspot/src/share/vm/utilities/linkedlist.hpp
@@ -40,6 +40,25 @@ template <class E> class LinkedListNode : public ResourceObj {
E _data; // embedded content
LinkedListNode<E>* _next; // next entry
+ // Select member function 'bool U::equals(const U&) const' if 'U' is of class
+ // type. This works because of the "Substitution Failure Is Not An Error"
+ // (SFINAE) rule. Notice that this version of 'equal' will also be chosen for
+ // class types which don't define a corresponding 'equals()' method (and will
+ // result in a compilation error for them). It is not easily possible to
+ // specialize this 'equal()' function exclusively for class types which define
+ // the correct 'equals()' function because that function can be in a base
+ // class, a dependent base class or have a compatible but slightly different
+ // signature.
+ template <class U>
+ static bool equal(const U& a, const U& b, bool (U::*t)(const U&) const) {
+ return a.equals(b);
+ }
+
+ template <class U>
+ static bool equal(const U& a, const U& b, ...) {
+ return a == b;
+ }
+
protected:
LinkedListNode() : _next(NULL) { }
@@ -51,6 +70,10 @@ template <class E> class LinkedListNode : public ResourceObj {
E* data() { return &_data; }
const E* peek() const { return &_data; }
+
+ bool equals(const E& t) const {
+ return equal<E>(_data, t, NULL);
+ }
};
// A linked list interface. It does not specify
@@ -62,6 +85,7 @@ template <class E> class LinkedList : public ResourceObj {
public:
LinkedList() : _head(NULL) { }
+ virtual ~LinkedList() {}
inline void set_head(LinkedListNode<E>* h) { _head = h; }
inline LinkedListNode<E>* head() const { return _head; }
@@ -182,7 +206,7 @@ template <class E, ResourceObj::allocation_type T = ResourceObj::C_HEAP,
virtual LinkedListNode<E>* find_node(const E& e) {
LinkedListNode<E>* p = this->head();
- while (p != NULL && !p->peek()->equals(e)) {
+ while (p != NULL && !p->equals(e)) {
p = p->next();
}
return p;
@@ -229,7 +253,7 @@ template <class E, ResourceObj::allocation_type T = ResourceObj::C_HEAP,
LinkedListNode<E>* prev = NULL;
while (tmp != NULL) {
- if (tmp->peek()->equals(e)) {
+ if (tmp->equals(e)) {
return remove_after(prev);
}
prev = tmp;
@@ -396,16 +420,21 @@ template <class E, int (*FUNC)(const E&, const E&),
// Iterates all entries in the list
template <class E> class LinkedListIterator : public StackObj {
private:
- LinkedListNode<E>* _p;
- bool _is_empty;
+ mutable LinkedListNode<E>* _p;
+
public:
- LinkedListIterator(LinkedListNode<E>* head) : _p(head) {
- _is_empty = (head == NULL);
- }
+ LinkedListIterator(LinkedListNode<E>* head) : _p(head) { }
+
+ bool is_empty() const { return _p == NULL; }
- bool is_empty() const { return _is_empty; }
+ E* next() {
+ if (_p == NULL) return NULL;
+ E* e = _p->data();
+ _p = _p->next();
+ return e;
+ }
- const E* next() {
+ const E* next() const {
if (_p == NULL) return NULL;
const E* e = _p->peek();
_p = _p->next();
diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp
index 14d82ad..5d40559 100644
--- a/hotspot/src/share/vm/utilities/ostream.cpp
+++ b/hotspot/src/share/vm/utilities/ostream.cpp
@@ -30,6 +30,7 @@
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "runtime/vmThread.hpp"
+#include "runtime/logAsyncWriter.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/ostream.hpp"
#include "utilities/top.hpp"
@@ -876,6 +877,17 @@ gcLogFileStream::gcLogFileStream(const char* file_name) : _file_lock(NULL) {
}
void gcLogFileStream::write(const char* s, size_t len) {
+ if (UseAsyncGCLog) {
+ AsyncLogWriter* aio_writer = AsyncLogWriter::instance();
+ if (aio_writer != NULL) {
+ aio_writer->enqueue(s);
+ return;
+ }
+ }
+ write_blocking(s, len);
+}
+
+void gcLogFileStream::write_blocking(const char* s, size_t len) {
if (_file != NULL) {
// we can't use Thread::current() here because thread may be NULL
// in early stage(ostream_init_log)
@@ -1047,6 +1059,17 @@ void gcLogFileStream::rotate_log_impl(bool force, outputStream* out) {
}
}
+void gcLogFileStream::flush() {
+ if (UseAsyncGCLog) {
+ AsyncLogWriter* aio_writer = AsyncLogWriter::instance();
+ if (aio_writer != NULL) {
+ // do nothing
+ return;
+ }
+ }
+ fileStream::flush();
+}
+
defaultStream* defaultStream::instance = NULL;
int defaultStream::_output_fd = 1;
int defaultStream::_error_fd = 2;
@@ -1456,6 +1479,9 @@ void ostream_exit() {
// ostream_abort() is called by os::abort() when VM is about to die.
void ostream_abort() {
+ if (UseAsyncGCLog) {
+ AsyncLogWriter::flush();
+ }
// Here we can't delete gclog_or_tty and tty, just flush their output
if (gclog_or_tty) gclog_or_tty->flush();
if (tty) tty->flush();
diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp
index d0f9aac..85ff599 100644
--- a/hotspot/src/share/vm/utilities/ostream.hpp
+++ b/hotspot/src/share/vm/utilities/ostream.hpp
@@ -254,6 +254,7 @@ class gcLogFileStream : public fileStream {
gcLogFileStream(const char* file_name);
~gcLogFileStream();
virtual void write(const char* c, size_t len);
+ void write_blocking(const char* c, size_t len);
virtual void rotate_log(bool force, outputStream* out = NULL);
void dump_loggc_header();
@@ -263,6 +264,8 @@ class gcLogFileStream : public fileStream {
((GCLogFileSize != 0) && ((uintx)_bytes_written >= GCLogFileSize));
}
+ virtual void flush();
+
};
#ifndef PRODUCT
--
1.8.3.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xuyuchao/openjdk-1.8.0.git
git@gitee.com:xuyuchao/openjdk-1.8.0.git
xuyuchao
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891