diff options
author | Tom <tomut@yahoo.com> | 2020-07-02 08:34:08 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-03 19:32:34 +0200 |
commit | 038dd9f30edbb53e99088050708faddad88881ca (patch) | |
tree | 57c40f3202d2a0b9c066dc3a330b92429d0e6275 /AK | |
parent | 57b61b2dde7f07f830679983c3dac94b71d2a1f8 (diff) | |
download | serenity-038dd9f30edbb53e99088050708faddad88881ca.zip |
AK: Serialize entire log statements
Prior to this, we wrote to the log every time the << operator
was used, which meant that only these parts of the log statement
were serialized. If the thread was preempted, or especially with
multiple CPUs the debug output was hard to decipher. Instead, we
buffer up the log statements. To avoid allocations we'll attempt
to use stack space, which covers most log statements.
Diffstat (limited to 'AK')
-rw-r--r-- | AK/ByteBuffer.h | 1 | ||||
-rw-r--r-- | AK/LogStream.cpp | 14 | ||||
-rw-r--r-- | AK/LogStream.h | 70 |
3 files changed, 67 insertions, 18 deletions
diff --git a/AK/ByteBuffer.h b/AK/ByteBuffer.h index 945461eee3..9772e2091f 100644 --- a/AK/ByteBuffer.h +++ b/AK/ByteBuffer.h @@ -26,7 +26,6 @@ #pragma once -#include <AK/LogStream.h> #include <AK/NonnullRefPtr.h> #include <AK/RefCounted.h> #include <AK/RefPtr.h> diff --git a/AK/LogStream.cpp b/AK/LogStream.cpp index 8a637bf5a2..52185d1530 100644 --- a/AK/LogStream.cpp +++ b/AK/LogStream.cpp @@ -153,15 +153,21 @@ DebugLogStream klog() #ifdef KERNEL KernelLogStream::~KernelLogStream() { - char newline = '\n'; - write(&newline, 1); + if (!empty()) { + char newline = '\n'; + write(&newline, 1); + kernelputstr(reinterpret_cast<char*>(data()), size()); + } } #endif DebugLogStream::~DebugLogStream() { - char newline = '\n'; - write(&newline, 1); + if (!empty()) { + char newline = '\n'; + write(&newline, 1); + dbgputstr(reinterpret_cast<char*>(data()), size()); + } } #ifndef KERNEL diff --git a/AK/LogStream.h b/AK/LogStream.h index e51556d351..1a1a937ad0 100644 --- a/AK/LogStream.h +++ b/AK/LogStream.h @@ -28,6 +28,7 @@ #include <AK/Forward.h> #include <AK/Types.h> +#include <AK/kmalloc.h> #include <AK/kstdio.h> #if !defined(KERNEL) @@ -47,7 +48,7 @@ public: #endif { } - virtual ~LogStream() {} + virtual ~LogStream() { } virtual void write(const char*, int) const = 0; @@ -57,15 +58,63 @@ private: #endif }; -class DebugLogStream final : public LogStream { +class BufferedLogStream : public LogStream { + mutable size_t m_size { 0 }; + mutable size_t m_capacity { 128 }; + union { + mutable u8* m_buffer { nullptr }; + mutable u8 m_local_buffer[128]; + } u; + + void grow(size_t bytes_needed) const + { + size_t new_capacity = (m_size + bytes_needed + 0x7F) & ~0x7F; + u8* new_data = static_cast<u8*>(kmalloc(new_capacity)); + if (m_capacity <= sizeof(u.m_local_buffer)) { + __builtin_memcpy(new_data, u.m_local_buffer, m_size); + } else if (u.m_buffer) { + __builtin_memcpy(new_data, u.m_buffer, m_size); + kfree(u.m_buffer); + } + u.m_buffer = new_data; + m_capacity = new_capacity; + } + +protected: + u8* data() const + { + if (m_capacity <= sizeof(u.m_local_buffer)) + return u.m_local_buffer; + return u.m_buffer; + } + + size_t size() const { return m_size; } + + bool empty() const { return m_size == 0; } + public: - DebugLogStream() {} - virtual ~DebugLogStream() override; + BufferedLogStream() { } - virtual void write(const char* characters, int length) const override + virtual ~BufferedLogStream() override { - dbgputstr(characters, length); + if (m_capacity > sizeof(u.m_local_buffer)) + kfree(u.m_buffer); } + + virtual void write(const char* str, int len) const override + { + size_t new_size = m_size + len; + if (new_size > m_capacity) + grow(len); + __builtin_memcpy(data() + m_size, str, len); + m_size = new_size; + } +}; + +class DebugLogStream final : public BufferedLogStream { +public: + DebugLogStream() { } + virtual ~DebugLogStream() override; }; #if !defined(KERNEL) @@ -87,15 +136,10 @@ inline StdLogStream warn() { return StdLogStream(STDERR_FILENO); } #endif #ifdef KERNEL -class KernelLogStream final : public LogStream { +class KernelLogStream final : public BufferedLogStream { public: - KernelLogStream() {} + KernelLogStream() { } virtual ~KernelLogStream() override; - - virtual void write(const char* characters, int length) const override - { - kernelputstr(characters, length); - } }; #endif |