summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-07-02 08:34:08 -0600
committerAndreas Kling <kling@serenityos.org>2020-07-03 19:32:34 +0200
commit038dd9f30edbb53e99088050708faddad88881ca (patch)
tree57c40f3202d2a0b9c066dc3a330b92429d0e6275 /AK
parent57b61b2dde7f07f830679983c3dac94b71d2a1f8 (diff)
downloadserenity-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.h1
-rw-r--r--AK/LogStream.cpp14
-rw-r--r--AK/LogStream.h70
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