From c63a0f8e7ed7a2d88cb24a46a6fd8e409f35756b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 10 Sep 2026 16:38:41 +0200 Subject: 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. --- kapi/kapi/system.hpp | 102 +++++++++++++++++++++++++++++++++++++------------ kernel/kapi/system.cpp | 90 ++++++++++++++++++++++++++++++++++++++++--- 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 #include +#include #include -#include #include #include @@ -17,25 +17,76 @@ namespace kapi::system //! @addtogroup kapi-system-kernel-defined //! @{ - template - struct panic_format_string + namespace detail { - kstd::format_string format; - std::source_location location; - - template - 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 + struct panic_format_string + { + kstd::format_string format; + std::source_location location; + + template + 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 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 - [[noreturn]] auto panic(panic_format_string...> format, + [[noreturn]] auto panic(detail::panic_format_string...> format, FormatArguments &&... arguments) { - auto buffer = std::array{}; - auto [_, length] = kstd::format_to(std::span{buffer}, format.format, std::forward(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(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(); } -- cgit v1.2.3