8269865: Async UL needs to handle ERANGE on exceeding SEM_VALUE_MAX

Reviewed-by: dholmes, pchilanomate
This commit is contained in:
Xin Liu 2021-07-14 01:43:53 +00:00
parent 0f5470715e
commit 67273ae63c
2 changed files with 20 additions and 14 deletions

View File

@ -27,16 +27,17 @@
#include "logging/logFileOutput.hpp" #include "logging/logFileOutput.hpp"
#include "logging/logHandle.hpp" #include "logging/logHandle.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "runtime/os.inline.hpp"
class AsyncLogWriter::AsyncLogLocker : public StackObj { class AsyncLogWriter::AsyncLogLocker : public StackObj {
public: public:
AsyncLogLocker() { AsyncLogLocker() {
assert(_instance != nullptr, "AsyncLogWriter::_lock is unavailable"); assert(_instance != nullptr, "AsyncLogWriter::_lock is unavailable");
_instance->_lock.wait(); _instance->_lock.lock();
} }
~AsyncLogLocker() { ~AsyncLogLocker() {
_instance->_lock.signal(); _instance->_lock.unlock();
} }
}; };
@ -51,7 +52,8 @@ void AsyncLogWriter::enqueue_locked(const AsyncLogMessage& msg) {
} }
_buffer.push_back(msg); _buffer.push_back(msg);
_sem.signal(); _data_available = true;
_lock.notify();
} }
void AsyncLogWriter::enqueue(LogFileOutput& output, const LogDecorations& decorations, const char* msg) { void AsyncLogWriter::enqueue(LogFileOutput& output, const LogDecorations& decorations, const char* msg) {
@ -75,7 +77,7 @@ void AsyncLogWriter::enqueue(LogFileOutput& output, LogMessageBuffer::Iterator m
} }
AsyncLogWriter::AsyncLogWriter() AsyncLogWriter::AsyncLogWriter()
: _lock(1), _sem(0), _flush_sem(0), : _flush_sem(0), _lock(), _data_available(false),
_initialized(false), _initialized(false),
_stats(17 /*table_size*/) { _stats(17 /*table_size*/) {
if (os::create_thread(this, os::asynclog_thread)) { if (os::create_thread(this, os::asynclog_thread)) {
@ -125,6 +127,7 @@ void AsyncLogWriter::write() {
// append meta-messages of dropped counters // append meta-messages of dropped counters
AsyncLogMapIterator dropped_counters_iter(logs); AsyncLogMapIterator dropped_counters_iter(logs);
_stats.iterate(&dropped_counters_iter); _stats.iterate(&dropped_counters_iter);
_data_available = false;
} }
LinkedListIterator<AsyncLogMessage> it(logs.head()); LinkedListIterator<AsyncLogMessage> it(logs.head());
@ -152,9 +155,14 @@ void AsyncLogWriter::write() {
void AsyncLogWriter::run() { void AsyncLogWriter::run() {
while (true) { 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. AsyncLogLocker locker;
_sem.wait();
while (!_data_available) {
_lock.wait(0/* no timeout */);
}
}
write(); write();
} }
} }
@ -198,7 +206,8 @@ void AsyncLogWriter::flush() {
// Push directly in-case we are at logical max capacity, as this must not get dropped. // Push directly in-case we are at logical max capacity, as this must not get dropped.
_instance->_buffer.push_back(token); _instance->_buffer.push_back(token);
_instance->_sem.signal(); _instance->_data_available = true;
_instance->_lock.notify();
} }
_instance->_flush_sem.wait(); _instance->_flush_sem.wait();

View File

@ -135,13 +135,10 @@ class AsyncLogWriter : public NonJavaThread {
class AsyncLogLocker; class AsyncLogLocker;
static AsyncLogWriter* _instance; 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;
Semaphore _flush_sem; Semaphore _flush_sem;
// Can't use a Monitor here as we need a low-level API that can be used without Thread::current().
os::PlatformMonitor _lock;
bool _data_available;
volatile bool _initialized; volatile bool _initialized;
AsyncLogMap _stats; // statistics for dropped messages AsyncLogMap _stats; // statistics for dropped messages
AsyncLogBuffer _buffer; AsyncLogBuffer _buffer;