[kernel] Simplify kernel logger

The logger had a lot of code that was due to it being in kutil instead
of the kernel. Simplifying it a bit here in order to make the uart
logger easier and eventual paring down of the logger easier.

- Log areas are no longer hashes of their names, just an enum
- Log level settings are no longer saved in 4 bits, just a byte
- System signal updating is done in the logger now
This commit is contained in:
Justin C. Miller
2022-01-15 09:57:08 -08:00
parent 11eef8d892
commit 7bb6b21c65
4 changed files with 72 additions and 120 deletions

View File

@@ -8,7 +8,7 @@
#include "objects/system.h" #include "objects/system.h"
#include "objects/thread.h" #include "objects/thread.h"
static uint8_t log_buffer[0x10000]; static uint8_t log_buffer[128 * 1024];
// The logger is initialized _before_ global constructors are called, // The logger is initialized _before_ global constructors are called,
// so that we can start log output immediately. Keep its constructor // so that we can start log output immediately. Keep its constructor
@@ -19,7 +19,7 @@ log::logger &g_logger = __g_logger_storage.value;
static const uint8_t level_colors[] = {0x07, 0x07, 0x0f, 0x0b, 0x09}; static const uint8_t level_colors[] = {0x07, 0x07, 0x0f, 0x0b, 0x09};
static void static void
output_log(log::area_t area, log::level severity, const char *message) output_log(logs area, log::level severity, const char *message)
{ {
auto *cons = console::get(); auto *cons = console::get();
cons->set_color(level_colors[static_cast<int>(severity)]); cons->set_color(level_colors[static_cast<int>(severity)]);
@@ -33,13 +33,6 @@ output_log(log::area_t area, log::level severity, const char *message)
// For printf.c // For printf.c
extern "C" void putchar_(char c) {} extern "C" void putchar_(char c) {}
static void
log_flush()
{
system &sys = system::get();
sys.assert_signal(j6_signal_system_has_log);
}
void void
logger_task() logger_task()
{ {
@@ -47,7 +40,6 @@ logger_task()
log::info(logs::task, "Starting kernel logger task"); log::info(logs::task, "Starting kernel logger task");
g_logger.set_immediate(nullptr); g_logger.set_immediate(nullptr);
g_logger.set_flush(log_flush);
thread &self = thread::current(); thread &self = thread::current();
system &sys = system::get(); system &sys = system::get();

View File

@@ -4,80 +4,45 @@
#include "assert.h" #include "assert.h"
#include "logger.h" #include "logger.h"
#include "objects/system.h"
#include "printf/printf.h" #include "printf/printf.h"
namespace logs {
#define LOG(name, lvl) \
const log::area_t name = #name ## _h; \
const char * name ## _name = #name;
#include <j6/tables/log_areas.inc>
#undef LOG
}
namespace log { namespace log {
logger *logger::s_log = nullptr; logger *logger::s_log = nullptr;
const char *logger::s_level_names[] = {"", "debug", "info", "warn", "error", "fatal"}; const char *logger::s_level_names[] = {"", "debug", "info", "warn", "error", "fatal"};
const char *logger::s_area_names[] = {
#define LOG(name, lvl) #name ,
#include <j6/tables/log_areas.inc>
#undef LOG
nullptr
};
logger::logger(logger::immediate_cb output) : logger::logger(logger::immediate_cb output) :
m_buffer(nullptr, 0), m_buffer(nullptr, 0),
m_immediate(output), m_immediate(output),
m_flush(nullptr),
m_sequence(0) m_sequence(0)
{ {
memset(&m_levels, 0, sizeof(m_levels)); memset(&m_levels, 0, sizeof(m_levels));
memset(&m_names, 0, sizeof(m_names));
s_log = this; s_log = this;
} }
logger::logger(uint8_t *buffer, size_t size, logger::immediate_cb output) : logger::logger(uint8_t *buffer, size_t size, logger::immediate_cb output) :
m_buffer(buffer, size), m_buffer(buffer, size),
m_immediate(output), m_immediate(output),
m_flush(nullptr),
m_sequence(0) m_sequence(0)
{ {
memset(&m_levels, 0, sizeof(m_levels)); memset(&m_levels, 0, sizeof(m_levels));
memset(&m_names, 0, sizeof(m_names));
s_log = this; s_log = this;
#define LOG(name, lvl) \ #define LOG(name, lvl) \
register_area(logs::name, logs::name ## _name, log::level::lvl); set_level(logs::name, log::level::lvl);
#include <j6/tables/log_areas.inc> #include <j6/tables/log_areas.inc>
#undef LOG #undef LOG
} }
void void
logger::set_level(area_t area, level l) logger::output(level severity, logs area, const char *fmt, va_list args)
{
unsigned uarea = static_cast<unsigned>(area);
uint8_t ulevel = static_cast<uint8_t>(l) & 0x0f;
uint8_t &flags = m_levels[uarea / 2];
if (uarea & 1)
flags = (flags & 0x0f) | (ulevel << 4);
else
flags = (flags & 0xf0) | ulevel;
}
level
logger::get_level(area_t area)
{
unsigned uarea = static_cast<unsigned>(area);
uint8_t &flags = m_levels[uarea / 2];
if (uarea & 1)
return static_cast<level>((flags & 0xf0) >> 4);
else
return static_cast<level>(flags & 0x0f);
}
void
logger::register_area(area_t area, const char *name, level verbosity)
{
m_names[area] = name;
set_level(area, verbosity);
}
void
logger::output(level severity, area_t area, const char *fmt, va_list args)
{ {
uint8_t buffer[256]; uint8_t buffer[256];
entry *header = reinterpret_cast<entry *>(buffer); entry *header = reinterpret_cast<entry *>(buffer);
@@ -86,8 +51,9 @@ logger::output(level severity, area_t area, const char *fmt, va_list args)
header->severity = severity; header->severity = severity;
header->sequence = m_sequence++; header->sequence = m_sequence++;
header->bytes += size_t mlen = vsnprintf(header->message, sizeof(buffer) - sizeof(entry) - 1, fmt, args);
vsnprintf(header->message, sizeof(buffer) - sizeof(entry), fmt, args); header->message[mlen] = 0;
header->bytes += mlen + 1;
util::scoped_lock lock {m_lock}; util::scoped_lock lock {m_lock};
@@ -99,19 +65,16 @@ logger::output(level severity, area_t area, const char *fmt, va_list args)
uint8_t *out; uint8_t *out;
size_t n = m_buffer.reserve(header->bytes, reinterpret_cast<void**>(&out)); size_t n = m_buffer.reserve(header->bytes, reinterpret_cast<void**>(&out));
if (n < sizeof(entry)) { if (n < header->bytes) {
m_buffer.commit(0); // Cannot even write the header, abort m_buffer.commit(0); // Cannot write the message, give up
return; return;
} }
if (n < header->bytes)
header->bytes = n;
memcpy(out, buffer, n); memcpy(out, buffer, n);
m_buffer.commit(n); m_buffer.commit(n);
if (m_flush) system &sys = system::get();
m_flush(); sys.assert_signal(j6_signal_system_has_log);
} }
size_t size_t
@@ -138,7 +101,7 @@ logger::get_entry(void *buffer, size_t size)
} }
#define LOG_LEVEL_FUNCTION(name) \ #define LOG_LEVEL_FUNCTION(name) \
void name (area_t area, const char *fmt, ...) { \ void name (logs area, const char *fmt, ...) { \
logger *l = logger::s_log; \ logger *l = logger::s_log; \
if (!l) return; \ if (!l) return; \
level limit = l->get_level(area); \ level limit = l->get_level(area); \
@@ -154,7 +117,7 @@ LOG_LEVEL_FUNCTION(info);
LOG_LEVEL_FUNCTION(warn); LOG_LEVEL_FUNCTION(warn);
LOG_LEVEL_FUNCTION(error); LOG_LEVEL_FUNCTION(error);
void fatal(area_t area, const char *fmt, ...) void fatal(logs area, const char *fmt, ...)
{ {
logger *l = logger::s_log; logger *l = logger::s_log;
if (!l) return; if (!l) return;

View File

@@ -8,21 +8,27 @@
#include <util/bip_buffer.h> #include <util/bip_buffer.h>
#include <util/spinlock.h> #include <util/spinlock.h>
enum class logs : uint8_t {
#define LOG(name, lvl) name,
#include <j6/tables/log_areas.inc>
#undef LOG
COUNT
};
namespace log { namespace log {
using area_t = uint8_t;
enum class level : uint8_t { enum class level : uint8_t {
none, debug, info, warn, error, fatal, max none, debug, info, warn, error, fatal, max
}; };
constexpr unsigned areas_count =
static_cast<unsigned>(logs::COUNT);
class logger class logger
{ {
public: public:
/// Callback type for immediate-mode logging /// Callback type for immediate-mode logging
typedef void (*immediate_cb)(area_t, level, const char *); typedef void (*immediate_cb)(logs, level, const char *);
/// Callback type for log flushing
typedef void (*flush_cb)();
/// Default constructor. Creates a logger without a backing store. /// Default constructor. Creates a logger without a backing store.
/// \arg output Immediate-mode logging output function /// \arg output Immediate-mode logging output function
@@ -34,23 +40,17 @@ public:
/// \arg output Immediate-mode logging output function /// \arg output Immediate-mode logging output function
logger(uint8_t *buffer, size_t size, immediate_cb output = nullptr); logger(uint8_t *buffer, size_t size, immediate_cb output = nullptr);
/// Register a log area for future use. /// Get the current immediate-mode callback
/// \arg area The key for the new area inline immediate_cb get_immediate() const { return m_immediate; }
/// \arg name The area name
/// \arg verbosity What level of logs to print for this area
void register_area(area_t area, const char *name, level verbosity);
/// Register an immediate-mode log callback /// Register an immediate-mode log callback
inline void set_immediate(immediate_cb 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. /// Get the default logger.
inline logger & get() { return *s_log; } inline logger & get() { return *s_log; }
/// Get the registered name for a given area /// Get the registered name for a given area
inline const char * area_name(area_t area) const { return m_names[area]; } inline const char * area_name(logs area) const { return s_area_names[static_cast<unsigned>(area)]; }
/// Get the name of a level /// Get the name of a level
inline const char * level_name(level l) const { return s_level_names[static_cast<unsigned>(l)]; } inline const char * level_name(level l) const { return s_level_names[static_cast<unsigned>(l)]; }
@@ -59,7 +59,7 @@ public:
/// \arg severity The severity of the message /// \arg severity The severity of the message
/// \arg area The log area to write to /// \arg area The log area to write to
/// \arg fmt A printf-like format string /// \arg fmt A printf-like format string
inline void log(level severity, area_t area, const char *fmt, ...) inline void log(level severity, logs area, const char *fmt, ...)
{ {
level limit = get_level(area); level limit = get_level(area);
if (limit == level::none || severity < limit) if (limit == level::none || severity < limit)
@@ -74,7 +74,7 @@ public:
struct entry struct entry
{ {
uint8_t bytes; uint8_t bytes;
area_t area; logs area;
level severity; level severity;
uint8_t sequence; uint8_t sequence;
char message[0]; char message[0];
@@ -91,22 +91,24 @@ public:
inline bool has_log() const { return m_buffer.size(); } inline bool has_log() const { return m_buffer.size(); }
private: private:
friend void debug(area_t area, const char *fmt, ...); friend void debug(logs area, const char *fmt, ...);
friend void info (area_t area, const char *fmt, ...); friend void info (logs area, const char *fmt, ...);
friend void warn (area_t area, const char *fmt, ...); friend void warn (logs area, const char *fmt, ...);
friend void error(area_t area, const char *fmt, ...); friend void error(logs area, const char *fmt, ...);
friend void fatal(area_t area, const char *fmt, ...); friend void fatal(logs area, const char *fmt, ...);
void output(level severity, area_t area, const char *fmt, va_list args); void output(level severity, logs area, const char *fmt, va_list args);
void set_level(area_t area, level l); inline void set_level(logs area, level l) {
level get_level(area_t area); m_levels[static_cast<unsigned>(area)] = l;
}
static const unsigned num_areas = 1 << (sizeof(area_t) * 8); inline level get_level(logs area) {
uint8_t m_levels[num_areas / 2]; return m_levels[static_cast<unsigned>(area)];
const char *m_names[num_areas]; }
level m_levels[areas_count];
immediate_cb m_immediate; immediate_cb m_immediate;
flush_cb m_flush;
uint8_t m_sequence; uint8_t m_sequence;
@@ -114,21 +116,16 @@ private:
util::spinlock m_lock; util::spinlock m_lock;
static logger *s_log; static logger *s_log;
static const char *s_area_names[areas_count+1];
static const char *s_level_names[static_cast<unsigned>(level::max)]; static const char *s_level_names[static_cast<unsigned>(level::max)];
}; };
void debug(area_t area, const char *fmt, ...); void debug(logs area, const char *fmt, ...);
void info (area_t area, const char *fmt, ...); void info (logs area, const char *fmt, ...);
void warn (area_t area, const char *fmt, ...); void warn (logs area, const char *fmt, ...);
void error(area_t area, const char *fmt, ...); void error(logs area, const char *fmt, ...);
void fatal(area_t area, const char *fmt, ...); void fatal(logs area, const char *fmt, ...);
extern log::logger &g_logger; extern log::logger &g_logger;
} // namespace log } // namespace log
namespace logs {
#define LOG(name, lvl) extern const log::area_t name;
#include <j6/tables/log_areas.inc>
#undef LOG
} // namespace logs

View File

@@ -1,16 +1,16 @@
LOG(apic, info); LOG(apic, info)
LOG(boot, debug); LOG(boot, debug)
LOG(clock, debug); LOG(clock, debug)
LOG(device, debug); LOG(device, debug)
LOG(driver, info); LOG(driver, info)
LOG(fs, info); LOG(fs, info)
LOG(irq, info); LOG(irq, info)
LOG(loader, debug); LOG(loader, debug)
LOG(memory, debug); LOG(memory, debug)
LOG(objs, debug); LOG(objs, debug)
LOG(paging, info); LOG(paging, info)
LOG(sched, info); LOG(sched, info)
LOG(syscall,info); LOG(syscall,debug)
LOG(task, debug); LOG(task, debug)
LOG(timer, debug); LOG(timer, debug)
LOG(vmem, debug); LOG(vmem, debug)