diff --git a/src/include/j6/signals.h b/src/include/j6/signals.h index 8eff049..bb625a7 100644 --- a/src/include/j6/signals.h +++ b/src/include/j6/signals.h @@ -8,9 +8,42 @@ // Signals 16-47 are defined per-object-type -// Process signals +// Event signals +#define j7_signal_event00 (1ull << 16) +#define j7_signal_event01 (1ull << 17) +#define j7_signal_event02 (1ull << 18) +#define j7_signal_event03 (1ull << 19) +#define j7_signal_event04 (1ull << 20) +#define j7_signal_event05 (1ull << 21) +#define j7_signal_event06 (1ull << 22) +#define j7_signal_event07 (1ull << 23) +#define j7_signal_event08 (1ull << 24) +#define j7_signal_event09 (1ull << 25) +#define j7_signal_event10 (1ull << 26) +#define j7_signal_event11 (1ull << 27) +#define j7_signal_event12 (1ull << 28) +#define j7_signal_event13 (1ull << 29) +#define j7_signal_event14 (1ull << 30) +#define j7_signal_event15 (1ull << 31) +#define j7_signal_event16 (1ull << 32) +#define j7_signal_event17 (1ull << 33) +#define j7_signal_event18 (1ull << 34) +#define j7_signal_event19 (1ull << 35) +#define j7_signal_event20 (1ull << 36) +#define j7_signal_event21 (1ull << 37) +#define j7_signal_event22 (1ull << 38) +#define j7_signal_event23 (1ull << 39) +#define j7_signal_event24 (1ull << 40) +#define j7_signal_event25 (1ull << 41) +#define j7_signal_event26 (1ull << 42) +#define j7_signal_event27 (1ull << 43) +#define j7_signal_event28 (1ull << 44) +#define j7_signal_event29 (1ull << 45) +#define j7_signal_event30 (1ull << 46) +#define j7_signal_event31 (1ull << 47) -// Thread signals +// System signals +#define j6_signal_system_has_log (1ull << 16) // Channel signals #define j6_signal_channel_can_send (1ull << 16) diff --git a/src/kernel/log.cpp b/src/kernel/log.cpp index dc9e68b..09191b6 100644 --- a/src/kernel/log.cpp +++ b/src/kernel/log.cpp @@ -1,8 +1,10 @@ +#include "j6/signals.h" #include "kutil/memory.h" #include "kutil/no_construct.h" #include "console.h" #include "log.h" -#include "scheduler.h" +#include "objects/system.h" +#include "objects/thread.h" static uint8_t log_buffer[0x10000]; @@ -26,29 +28,54 @@ output_log(log::area_t area, log::level severity, const char *message) cons->set_color(); } +static void +log_flush() +{ + system &sys = system::get(); + sys.assert_signal(j6_signal_system_has_log); +} + void logger_task() { - uint8_t buffer[257]; - auto *ent = reinterpret_cast(buffer); auto *cons = console::get(); log::info(logs::task, "Starting kernel logger task"); g_logger.set_immediate(nullptr); + g_logger.set_flush(log_flush); - scheduler &s = scheduler::get(); + thread &self = thread::current(); + system &sys = system::get(); + + size_t buffer_size = 1; + uint8_t *buffer = nullptr; while (true) { - if(g_logger.get_entry(buffer, sizeof(buffer))) { + size_t size = g_logger.get_entry(buffer, buffer_size); + if (size > buffer_size) { + while (size > buffer_size) buffer_size *= 2; + kutil::kfree(buffer); + buffer = reinterpret_cast(kutil::kalloc(buffer_size)); + kassert(buffer, "Could not allocate logger task buffer"); + continue; + } + + if(size) { + auto *ent = reinterpret_cast(buffer); buffer[ent->bytes] = 0; + cons->set_color(level_colors[static_cast(ent->severity)]); cons->printf("%7s %5s: %s\n", g_logger.area_name(ent->area), g_logger.level_name(ent->severity), ent->message); cons->set_color(); - } else { - s.schedule(); + } + + if (!g_logger.has_log()) { + sys.deassert_signal(j6_signal_system_has_log); + sys.add_blocked_thread(&self); + self.wait_on_signals(&sys, j6_signal_system_has_log); } } } diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index e872f1d..e59b90a 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -200,7 +200,7 @@ kernel_main(args::header *header) } if (!has_video) - sched->create_kernel_task(logger_task, scheduler::max_priority-1, true); + sched->create_kernel_task(logger_task, scheduler::max_priority/2, true); sched->create_kernel_task(stdout_task, scheduler::max_priority-1, true); const char stdout_message[] = "Hello on the fake stdout channel\n"; diff --git a/src/kernel/objects/system.h b/src/kernel/objects/system.h index 1491776..0367d17 100644 --- a/src/kernel/objects/system.h +++ b/src/kernel/objects/system.h @@ -10,7 +10,7 @@ class system : public: static constexpr kobject::type type = kobject::type::event; - inline static system * get() { return &s_instance; } + inline static system & get() { return s_instance; } private: static system s_instance; diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 6ce2183..9b6ca39 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -112,7 +112,7 @@ load_process_image(uintptr_t phys, uintptr_t virt, size_t bytes, TCB *tcb) j6_init_value *initv = push(tcb->rsp3); initv->type = j6_init_handle_system; - initv->value = static_cast(proc.add_handle(system::get())); + initv->value = static_cast(proc.add_handle(&system::get())); initv = push(tcb->rsp3); initv->type = j6_init_handle_process; diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index fa13a96..8a5acb0 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -5,6 +5,7 @@ #include "log.h" #include "objects/endpoint.h" #include "objects/thread.h" +#include "objects/system.h" #include "syscalls/helpers.h" extern log::logger &g_logger; @@ -33,8 +34,15 @@ system_noop() j6_status_t system_get_log(j6_handle_t sys, char *buffer, size_t *size) { + if (!size || (*size && !buffer)) + return j6_err_invalid_arg; + + size_t orig_size = *size; *size = g_logger.get_entry(buffer, *size); - return j6_status_ok; + if (!g_logger.has_log()) + system::get().deassert_signal(j6_signal_system_has_log); + + return (*size > orig_size) ? j6_err_insufficient : j6_status_ok; } j6_status_t diff --git a/src/libraries/kutil/include/kutil/logger.h b/src/libraries/kutil/include/kutil/logger.h index 15aeb9a..a4ca516 100644 --- a/src/libraries/kutil/include/kutil/logger.h +++ b/src/libraries/kutil/include/kutil/logger.h @@ -19,17 +19,20 @@ class logger { public: /// Callback type for immediate-mode logging - typedef void (*immediate)(area_t, level, const char *); + typedef void (*immediate_cb)(area_t, level, const char *); + + /// Callback type for log flushing + typedef void (*flush_cb)(); /// Default constructor. Creates a logger without a backing store. /// \arg output Immediate-mode logging output function - logger(immediate output = nullptr); + logger(immediate_cb output = nullptr); /// Constructor. Logs are written to the given buffer. /// \arg buffer Buffer to which logs are written /// \arg size Size of `buffer`, in bytes /// \arg output Immediate-mode logging output function - logger(uint8_t *buffer, size_t size, immediate output = nullptr); + logger(uint8_t *buffer, size_t size, immediate_cb output = nullptr); /// Register a log area for future use. /// \arg area The key for the new area @@ -38,7 +41,10 @@ public: void register_area(area_t area, const char *name, level verbosity); /// Register an immediate-mode log callback - inline void set_immediate(immediate cb) { m_immediate = cb; } + inline void set_immediate(immediate_cb cb) { m_immediate = cb; } + + /// Register a flush callback + inline void set_flush(flush_cb cb) { m_flush = cb; } /// Get the default logger. inline logger & get() { return *s_log; } @@ -77,9 +83,13 @@ public: /// Get the next log entry from the buffer /// \arg buffer The buffer to copy the log message into /// \arg size Size of the passed-in buffer, in bytes - /// \returns Number of bytes copied into the buffer + /// \returns The size of the log entry (if larger than the + /// buffer, then no data was copied) size_t get_entry(void *buffer, size_t size); + /// Get whether there is currently data in the log buffer + inline bool has_log() const { return m_buffer.size(); } + private: friend void debug(area_t area, const char *fmt, ...); friend void info (area_t area, const char *fmt, ...); @@ -95,7 +105,8 @@ private: static const unsigned num_areas = 1 << (sizeof(area_t) * 8); uint8_t m_levels[num_areas / 2]; const char *m_names[num_areas]; - immediate m_immediate; + immediate_cb m_immediate; + flush_cb m_flush; uint8_t m_sequence; diff --git a/src/libraries/kutil/logger.cpp b/src/libraries/kutil/logger.cpp index ade8782..4f7f284 100644 --- a/src/libraries/kutil/logger.cpp +++ b/src/libraries/kutil/logger.cpp @@ -21,9 +21,10 @@ using kutil::memcpy; logger *logger::s_log = nullptr; const char *logger::s_level_names[] = {"", "debug", "info", "warn", "error", "fatal"}; -logger::logger(logger::immediate output) : +logger::logger(logger::immediate_cb output) : m_buffer(nullptr, 0), m_immediate(output), + m_flush(nullptr), m_sequence(0) { memset(&m_levels, 0, sizeof(m_levels)); @@ -31,9 +32,10 @@ logger::logger(logger::immediate output) : s_log = this; } -logger::logger(uint8_t *buffer, size_t size, logger::immediate output) : +logger::logger(uint8_t *buffer, size_t size, logger::immediate_cb output) : m_buffer(buffer, size), m_immediate(output), + m_flush(nullptr), m_sequence(0) { memset(&m_levels, 0, sizeof(m_levels)); @@ -107,6 +109,9 @@ logger::output(level severity, area_t area, const char *fmt, va_list args) memcpy(out, buffer, n); m_buffer.commit(n); + + if (m_flush) + m_flush(); } size_t @@ -114,7 +119,6 @@ logger::get_entry(void *buffer, size_t size) { void *out; size_t out_size = m_buffer.get_block(&out); - entry *ent = reinterpret_cast(out); if (out_size == 0 || out == 0) return 0; @@ -122,13 +126,13 @@ logger::get_entry(void *buffer, size_t size) if (out_size < sizeof(entry)) return 0; - kassert(size >= ent->bytes, "Didn't pass a big enough buffer"); - if (size < ent->bytes) - return 0; + entry *ent = reinterpret_cast(out); + if (size >= out_size) { + memcpy(buffer, out, ent->bytes); + m_buffer.consume(ent->bytes); + } - memcpy(buffer, out, ent->bytes); - m_buffer.consume(ent->bytes); - return ent->bytes; + return out_size; } #define LOG_LEVEL_FUNCTION(name) \