aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-09-10 16:38:41 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-09-10 16:38:41 +0200
commitc63a0f8e7ed7a2d88cb24a46a6fd8e409f35756b (patch)
treea39f38114423bd6068be6812c7e8322dda834499
parent3ce0197e99ecea7be66decc2c3c6f785497ef862 (diff)
downloadkernel-c63a0f8e7ed7a2d88cb24a46a6fd8e409f35756b.tar.xz
kernel-c63a0f8e7ed7a2d88cb24a46a6fd8e409f35756b.zip
kapi/system: reduce panic buffer size
Previously, we allocated a 512-byte buffer for every call of the formatted panic function. This was heavily increasing the stack size for a number of functions. We now don't print to a statically allocated buffer, but rather use the iterator-based formatting facility and a proxy iterator with a small, self-flushing buffer. This reduces that static overhead of the formatted panic function to by almost 500 bytes, while increasing possible message fidelity, since we are not longer arbitrarily limited by the buffer.
-rw-r--r--kapi/kapi/system.hpp102
-rw-r--r--kernel/kapi/system.cpp90
2 files changed, 163 insertions, 29 deletions
diff --git a/kapi/kapi/system.hpp b/kapi/kapi/system.hpp
index 80233507..d8a306d3 100644
--- a/kapi/kapi/system.hpp
+++ b/kapi/kapi/system.hpp
@@ -6,8 +6,8 @@
#include <array>
#include <cstddef>
+#include <iterator>
#include <source_location>
-#include <span>
#include <string_view>
#include <type_traits>
@@ -17,25 +17,76 @@ namespace kapi::system
//! @addtogroup kapi-system-kernel-defined
//! @{
- template<typename... FormatArguments>
- struct panic_format_string
+ namespace detail
{
- kstd::format_string<FormatArguments...> format;
- std::source_location location;
-
- template<std::size_t Size>
- consteval panic_format_string(char const (&format)[Size], // NOLINT
- std::source_location location = std::source_location::current())
- : format{format}
- , location{location}
- {}
-
- consteval panic_format_string(std::string_view format,
- std::source_location location = std::source_location::current())
- : format{format}
- , location{location}
- {}
- };
+ template<typename... FormatArguments>
+ struct panic_format_string
+ {
+ kstd::format_string<FormatArguments...> format;
+ std::source_location location;
+
+ template<std::size_t Size>
+ consteval panic_format_string(char const (&format)[Size], // NOLINT
+ std::source_location location = std::source_location::current())
+ : format{format}
+ , location{location}
+ {}
+
+ consteval panic_format_string(std::string_view format,
+ std::source_location location = std::source_location::current())
+ : format{format}
+ , location{location}
+ {}
+ };
+
+ struct panic_buffer
+ {
+ ~panic_buffer();
+
+ void append(char character);
+ void flush();
+
+ private:
+ std::array<char, 16> m_buffer{};
+ std::size_t m_written{};
+ };
+
+ struct panic_iterator
+ {
+ using iterator_category = std::output_iterator_tag;
+ using iterator_concept = std::output_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+ using value_type = void;
+ using pointer = void;
+ using reference = void;
+
+ explicit panic_iterator(panic_buffer & buffer);
+
+ auto operator*() noexcept -> panic_iterator &;
+ auto operator=(char character) -> panic_iterator &;
+ auto operator++() -> panic_iterator &;
+ auto operator++(int) -> panic_iterator;
+
+ private:
+ panic_buffer * m_buffer;
+ };
+
+ } // namespace detail
+
+ //! Initiate panic processing.
+ //!
+ //! @param location The location where the panic occurred.
+ auto panic_start(std::source_location location) -> void;
+
+ //! Write panic output.
+ //!
+ //! @param message The message to write.
+ auto panic_write(std::string_view message) -> void;
+
+ //! Finish panic processing
+ //!
+ //! @param location The location where the panic occurred.
+ [[noreturn]] auto panic_finish(std::source_location location) -> void;
//! Terminate kernel execution with the given error message.
//!
@@ -61,14 +112,17 @@ namespace kapi::system
auto memory_initialized() -> void;
//! @} // end group platform-defined
- //
+
template<typename... FormatArguments>
- [[noreturn]] auto panic(panic_format_string<std::type_identity_t<FormatArguments>...> format,
+ [[noreturn]] auto panic(detail::panic_format_string<std::type_identity_t<FormatArguments>...> format,
FormatArguments &&... arguments)
{
- auto buffer = std::array<char, 512uz>{};
- auto [_, length] = kstd::format_to(std::span{buffer}, format.format, std::forward<FormatArguments>(arguments)...);
- panic(std::string_view{buffer.data(), length}, format.location);
+ panic_start(format.location);
+ {
+ auto buffer = detail::panic_buffer{};
+ kstd::format_to(detail::panic_iterator{buffer}, format.format, std::forward<FormatArguments>(arguments)...);
+ }
+ panic_finish(format.location);
}
} // namespace kapi::system
diff --git a/kernel/kapi/system.cpp b/kernel/kapi/system.cpp
index 629e5990..34601b9d 100644
--- a/kernel/kapi/system.cpp
+++ b/kernel/kapi/system.cpp
@@ -11,19 +11,99 @@
namespace kapi::system
{
+ namespace
+ {
+
+ auto panic_write(kstd::error_code error) -> void
+ {
+ kstd::print(kstd::print_sink::stderr, " ({}) ", error);
+ }
+
+ } // namespace
+
+ namespace detail
+ {
+
+ panic_buffer::~panic_buffer()
+ {
+ flush();
+ }
+
+ void panic_buffer::append(char character)
+ {
+ m_buffer[m_written++] = character;
+ if (m_written == m_buffer.size())
+ {
+ flush();
+ }
+ }
+
+ void panic_buffer::flush()
+ {
+ if (m_written > 0)
+ {
+ panic_write(std::string_view{m_buffer.data(), m_written});
+ m_written = 0;
+ }
+ }
+
+ panic_iterator::panic_iterator(panic_buffer & buffer)
+ : m_buffer(&buffer)
+ {}
+
+ auto panic_iterator::operator*() noexcept -> panic_iterator &
+ {
+ return *this;
+ }
+
+ auto panic_iterator::operator=(char character) -> panic_iterator &
+ {
+ m_buffer->append(character);
+ return *this;
+ }
+
+ auto panic_iterator::operator++() -> panic_iterator &
+ {
+ return *this;
+ }
+
+ auto panic_iterator::operator++(int) -> panic_iterator
+ {
+ return *this;
+ }
+
+ } // namespace detail
+
[[gnu::weak]]
auto panic(std::string_view message, std::source_location location) -> void
{
- kstd::println(kstd::print_sink::stderr, "[PANIC] in {} : {} @ {}:{}", location.function_name(), message,
- location.file_name(), location.line());
- cpu::halt();
+ panic_start(location);
+ panic_write(message);
+ panic_finish(location);
}
[[gnu::weak]]
auto panic(std::string_view message, kstd::error_code error, std::source_location location) -> void
{
- kstd::println(kstd::print_sink::stderr, "[PANIC] in {} : {} ({}) @ {}:{}", location.function_name(), message, error,
- location.file_name(), location.line());
+ panic_start(location);
+ panic_write(message);
+ panic_write(error);
+ panic_finish(location);
+ }
+
+ auto panic_start(std::source_location location) -> void
+ {
+ kstd::print(kstd::print_sink::stderr, "[PANIC] in '{}': ", location.function_name());
+ }
+
+ auto panic_write(std::string_view message) -> void
+ {
+ kstd::print(kstd::print_sink::stderr, "{}", message);
+ }
+
+ auto panic_finish(std::source_location location) -> void
+ {
+ kstd::println(kstd::print_sink::stderr, " @ {}:{}", location.file_name(), location.line());
cpu::halt();
}