aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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();
}