mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[kernel] Run global constructors
Look up the global constructor list that the linker outputs, and run them all. Required creation of the `kutil::no_construct` template for objects that are constructed before the global constructors are run. Also split the `memory_initialize` function into two - one for just those objects that need to happen before the global ctors, and one after. Tags: memory c++
This commit is contained in:
@@ -20,6 +20,12 @@ SECTIONS
|
|||||||
*(.rodata)
|
*(.rodata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ctors : ALIGN(8) {
|
||||||
|
__ctors = .;
|
||||||
|
KEEP(*(.ctors))
|
||||||
|
__ctors_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
.bss ALIGN(4096) : {
|
.bss ALIGN(4096) : {
|
||||||
__bss_start = .;
|
__bss_start = .;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "kutil/coord.h"
|
#include "kutil/coord.h"
|
||||||
#include "kutil/guid.h"
|
#include "kutil/guid.h"
|
||||||
#include "kutil/memory.h"
|
#include "kutil/memory.h"
|
||||||
|
#include "kutil/no_construct.h"
|
||||||
#include "kutil/printf.h"
|
#include "kutil/printf.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
@@ -9,7 +10,9 @@
|
|||||||
|
|
||||||
|
|
||||||
const char digits[] = "0123456789abcdef";
|
const char digits[] = "0123456789abcdef";
|
||||||
console g_console;
|
|
||||||
|
static kutil::no_construct<console> __g_console_storage;
|
||||||
|
console &g_console = __g_console_storage.value;
|
||||||
|
|
||||||
|
|
||||||
class console::screen_out
|
class console::screen_out
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ private:
|
|||||||
serial_port *m_serial;
|
serial_port *m_serial;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern console g_console;
|
extern console &g_console;
|
||||||
inline console * console::get() { return &g_console; }
|
inline console * console::get() { return &g_console; }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
static const char expected_signature[] = "RSD PTR ";
|
static const char expected_signature[] = "RSD PTR ";
|
||||||
|
|
||||||
device_manager device_manager::s_instance(nullptr, kutil::allocator::invalid);
|
device_manager device_manager::s_instance;
|
||||||
|
|
||||||
struct acpi1_rsdp
|
struct acpi1_rsdp
|
||||||
{
|
{
|
||||||
@@ -59,8 +59,17 @@ void irq4_callback(void *)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
device_manager::device_manager(const void *root_table, kutil::allocator &alloc) :
|
device_manager::device_manager() :
|
||||||
m_lapic(nullptr)
|
m_lapic(nullptr)
|
||||||
|
{
|
||||||
|
m_irqs.ensure_capacity(32);
|
||||||
|
m_irqs.set_size(16);
|
||||||
|
m_irqs[2] = {"Clock interrupt", irq2_callback, nullptr};
|
||||||
|
m_irqs[4] = {"Serial interrupt", irq4_callback, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
device_manager::parse_acpi(const void *root_table)
|
||||||
{
|
{
|
||||||
kassert(root_table != 0, "ACPI root table pointer is null.");
|
kassert(root_table != 0, "ACPI root table pointer is null.");
|
||||||
|
|
||||||
@@ -83,11 +92,6 @@ device_manager::device_manager(const void *root_table, kutil::allocator &alloc)
|
|||||||
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
|
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
|
||||||
|
|
||||||
load_xsdt(reinterpret_cast<const acpi_xsdt *>(acpi2->xsdt_address));
|
load_xsdt(reinterpret_cast<const acpi_xsdt *>(acpi2->xsdt_address));
|
||||||
|
|
||||||
m_irqs.ensure_capacity(32);
|
|
||||||
m_irqs.set_size(16);
|
|
||||||
m_irqs[2] = {"Clock interrupt", irq2_callback, nullptr};
|
|
||||||
m_irqs[4] = {"Serial interrupt", irq4_callback, nullptr};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ioapic *
|
ioapic *
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ class device_manager
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// \arg root_table Pointer to the ACPI RSDP
|
device_manager();
|
||||||
/// \arg alloc Allocator for device arrays
|
|
||||||
device_manager(const void *root_table, kutil::allocator &alloc);
|
|
||||||
|
|
||||||
/// Get the system global device manager.
|
/// Get the system global device manager.
|
||||||
/// \returns A reference to the system device manager
|
/// \returns A reference to the system device manager
|
||||||
@@ -36,6 +34,10 @@ public:
|
|||||||
/// otherwise nullptr.
|
/// otherwise nullptr.
|
||||||
ioapic * get_ioapic(int i);
|
ioapic * get_ioapic(int i);
|
||||||
|
|
||||||
|
/// Parse ACPI tables.
|
||||||
|
/// \arg root_table Pointer to the ACPI RSDP
|
||||||
|
void parse_acpi(const void *root_table);
|
||||||
|
|
||||||
/// Intialize drivers for the current device list.
|
/// Intialize drivers for the current device list.
|
||||||
void init_drivers();
|
void init_drivers();
|
||||||
|
|
||||||
@@ -122,7 +124,6 @@ private:
|
|||||||
|
|
||||||
static device_manager s_instance;
|
static device_manager s_instance;
|
||||||
|
|
||||||
device_manager() = delete;
|
|
||||||
device_manager(const device_manager &) = delete;
|
device_manager(const device_manager &) = delete;
|
||||||
device_manager operator=(const device_manager &) = delete;
|
device_manager operator=(const device_manager &) = delete;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ using memory::frame_size;
|
|||||||
using memory::page_offset;
|
using memory::page_offset;
|
||||||
using frame_block_node = kutil::list_node<frame_block>;
|
using frame_block_node = kutil::list_node<frame_block>;
|
||||||
|
|
||||||
frame_allocator g_frame_allocator;
|
|
||||||
|
|
||||||
int
|
int
|
||||||
frame_block::compare(const frame_block *rhs) const
|
frame_block::compare(const frame_block *rhs) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,5 +66,3 @@ struct frame_block
|
|||||||
int compare(const frame_block *rhs) const;
|
int compare(const frame_block *rhs) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern frame_allocator g_frame_allocator;
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
#include "kutil/memory.h"
|
#include "kutil/memory.h"
|
||||||
|
#include "kutil/no_construct.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
|
||||||
|
|
||||||
static uint8_t log_buffer[0x10000];
|
static uint8_t log_buffer[0x10000];
|
||||||
static log::logger g_logger(log_buffer, sizeof(log_buffer));
|
|
||||||
|
// The logger is initialized _before_ global constructors are called,
|
||||||
|
// so that we can start log output immediately. Keep its constructor
|
||||||
|
// from being called here so as to not overwrite the previous initialization.
|
||||||
|
static kutil::no_construct<log::logger> __g_logger_storage;
|
||||||
|
static 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};
|
||||||
|
|
||||||
@@ -50,6 +55,5 @@ logger_task()
|
|||||||
|
|
||||||
void logger_init()
|
void logger_init()
|
||||||
{
|
{
|
||||||
new (&g_logger) log::logger(log_buffer, sizeof(log_buffer));
|
new (&g_logger) log::logger(log_buffer, sizeof(log_buffer), output_log);
|
||||||
g_logger.set_immediate(output_log);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "initrd/initrd.h"
|
#include "initrd/initrd.h"
|
||||||
#include "kutil/assert.h"
|
#include "kutil/assert.h"
|
||||||
#include "kutil/heap_allocator.h"
|
|
||||||
#include "kutil/vm_space.h"
|
#include "kutil/vm_space.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#include "block_device.h"
|
#include "block_device.h"
|
||||||
@@ -27,12 +26,35 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void kernel_main(kernel::args::header *header);
|
void kernel_main(kernel::args::header *header);
|
||||||
void *__bss_start, *__bss_end;
|
void (*__ctors)(void);
|
||||||
|
void (*__ctors_end)(void);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run_constructors()
|
||||||
|
{
|
||||||
|
void (**p)(void) = &__ctors;
|
||||||
|
while (p < &__ctors_end) {
|
||||||
|
void (*ctor)(void) = *p++;
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class test_ctor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
test_ctor(int value) : value(value) {}
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
test_ctor ctor_tester(42);
|
||||||
|
|
||||||
extern void __kernel_assert(const char *, unsigned, const char *);
|
extern void __kernel_assert(const char *, unsigned, const char *);
|
||||||
|
|
||||||
extern kutil::heap_allocator g_kernel_heap;
|
/// Bootstrap the memory managers.
|
||||||
|
void memory_initialize_pre_ctors(kernel::args::header *kargs);
|
||||||
|
void memory_initialize_post_ctors(kernel::args::header *kargs);
|
||||||
|
|
||||||
using namespace kernel;
|
using namespace kernel;
|
||||||
|
|
||||||
class test_observer :
|
class test_observer :
|
||||||
@@ -65,7 +87,6 @@ init_console()
|
|||||||
cons->puts("jsix OS ");
|
cons->puts("jsix OS ");
|
||||||
cons->set_color(0x08, 0x00);
|
cons->set_color(0x08, 0x00);
|
||||||
cons->puts(GIT_VERSION " booting...\n");
|
cons->puts(GIT_VERSION " booting...\n");
|
||||||
|
|
||||||
logger_init();
|
logger_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +99,14 @@ kernel_main(args::header *header)
|
|||||||
gdt_init();
|
gdt_init();
|
||||||
interrupts_init();
|
interrupts_init();
|
||||||
|
|
||||||
|
memory_initialize_pre_ctors(header);
|
||||||
|
kutil::memset(&ctor_tester, 0, sizeof(ctor_tester));
|
||||||
|
run_constructors();
|
||||||
|
memory_initialize_post_ctors(header);
|
||||||
|
|
||||||
cpu_id cpu;
|
cpu_id cpu;
|
||||||
cpu.validate();
|
cpu.validate();
|
||||||
|
|
||||||
memory_initialize(header);
|
|
||||||
|
|
||||||
kutil::allocator &heap = g_kernel_heap;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (header->frame_buffer && header->frame_buffer_length) {
|
if (header->frame_buffer && header->frame_buffer_length) {
|
||||||
page_manager::get()->map_offset_pointer(
|
page_manager::get()->map_offset_pointer(
|
||||||
@@ -116,8 +138,8 @@ kernel_main(args::header *header)
|
|||||||
page_manager::get()->dump_blocks(true);
|
page_manager::get()->dump_blocks(true);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
device_manager *devices =
|
device_manager &devices = device_manager::get();
|
||||||
new (&device_manager::get()) device_manager(header->acpi_table, heap);
|
devices.parse_acpi(header->acpi_table);
|
||||||
|
|
||||||
interrupts_enable();
|
interrupts_enable();
|
||||||
|
|
||||||
@@ -130,7 +152,7 @@ kernel_main(args::header *header)
|
|||||||
log::info(logs::boot, "cr4: %016x", cr4);
|
log::info(logs::boot, "cr4: %016x", cr4);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
devices->init_drivers();
|
devices.init_drivers();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
block_device *disk = devices->get_block_device(0);
|
block_device *disk = devices->get_block_device(0);
|
||||||
@@ -156,10 +178,10 @@ kernel_main(args::header *header)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
devices->get_lapic()->calibrate_timer();
|
devices.get_lapic()->calibrate_timer();
|
||||||
|
|
||||||
syscall_enable();
|
syscall_enable();
|
||||||
scheduler *sched = new (&scheduler::get()) scheduler(devices->get_lapic());
|
scheduler *sched = new (&scheduler::get()) scheduler(devices.get_lapic());
|
||||||
|
|
||||||
sched->create_kernel_task(-1, logger_task);
|
sched->create_kernel_task(-1, logger_task);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "kutil/assert.h"
|
#include "kutil/assert.h"
|
||||||
#include "kutil/heap_allocator.h"
|
#include "kutil/heap_allocator.h"
|
||||||
|
#include "kutil/no_construct.h"
|
||||||
#include "kutil/vm_space.h"
|
#include "kutil/vm_space.h"
|
||||||
|
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
@@ -24,7 +25,18 @@ using memory::table_entries;
|
|||||||
using namespace kernel;
|
using namespace kernel;
|
||||||
|
|
||||||
kutil::vm_space g_kernel_space;
|
kutil::vm_space g_kernel_space;
|
||||||
kutil::heap_allocator g_kernel_heap;
|
|
||||||
|
// These objects are initialized _before_ global constructors are called,
|
||||||
|
// so we don't want them to have global constructors at all, lest they
|
||||||
|
// overwrite the previous initialization.
|
||||||
|
static kutil::no_construct<kutil::heap_allocator> __g_kernel_heap_storage;
|
||||||
|
kutil::heap_allocator &g_kernel_heap = __g_kernel_heap_storage.value;
|
||||||
|
|
||||||
|
static kutil::no_construct<page_manager> __g_page_manager_storage;
|
||||||
|
page_manager &g_page_manager = __g_page_manager_storage.value;
|
||||||
|
|
||||||
|
static kutil::no_construct<frame_allocator> __g_frame_allocator_storage;
|
||||||
|
frame_allocator &g_frame_allocator = __g_frame_allocator_storage.value;
|
||||||
|
|
||||||
void * operator new(size_t size) { return g_kernel_heap.allocate(size); }
|
void * operator new(size_t size) { return g_kernel_heap.allocate(size); }
|
||||||
void * operator new [] (size_t size) { return g_kernel_heap.allocate(size); }
|
void * operator new [] (size_t size) { return g_kernel_heap.allocate(size); }
|
||||||
@@ -74,7 +86,7 @@ void walk_page_table(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
memory_initialize(args::header *kargs)
|
memory_initialize_pre_ctors(args::header *kargs)
|
||||||
{
|
{
|
||||||
args::mem_entry *entries = kargs->mem_map;
|
args::mem_entry *entries = kargs->mem_map;
|
||||||
size_t entry_count = kargs->num_map_entries;
|
size_t entry_count = kargs->num_map_entries;
|
||||||
@@ -82,26 +94,30 @@ memory_initialize(args::header *kargs)
|
|||||||
|
|
||||||
new (&g_kernel_heap) kutil::heap_allocator {heap_start, kernel_max_heap};
|
new (&g_kernel_heap) kutil::heap_allocator {heap_start, kernel_max_heap};
|
||||||
|
|
||||||
frame_allocator *fa = new (&g_frame_allocator) frame_allocator;
|
new (&g_frame_allocator) frame_allocator;
|
||||||
for (unsigned i = 0; i < entry_count; ++i) {
|
for (unsigned i = 0; i < entry_count; ++i) {
|
||||||
// TODO: use entry attributes
|
// TODO: use entry attributes
|
||||||
args::mem_entry &e = entries[i];
|
args::mem_entry &e = entries[i];
|
||||||
if (e.type == args::mem_type::free)
|
if (e.type == args::mem_type::free)
|
||||||
fa->free(e.start, e.pages);
|
g_frame_allocator.free(e.start, e.pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the page manager
|
// Create the page manager
|
||||||
page_manager *pm = new (&g_page_manager) page_manager(*fa, kpml4);
|
new (&g_page_manager) page_manager {g_frame_allocator, kpml4};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_initialize_post_ctors(args::header *kargs)
|
||||||
|
{
|
||||||
new (&g_kernel_space) kutil::vm_space {
|
new (&g_kernel_space) kutil::vm_space {
|
||||||
kernel_offset,
|
kernel_offset,
|
||||||
(page_offset-kernel_offset)};
|
(page_offset-kernel_offset)};
|
||||||
|
|
||||||
|
|
||||||
uintptr_t current_start = 0;
|
uintptr_t current_start = 0;
|
||||||
size_t current_bytes = 0;
|
size_t current_bytes = 0;
|
||||||
|
|
||||||
// TODO: Should we exclude the top of this area? (eg, buffers, stacks, etc)
|
// TODO: Should we exclude the top of this area? (eg, buffers, stacks, etc)
|
||||||
|
page_table *kpml4 = reinterpret_cast<page_table*>(kargs->pml4);
|
||||||
for (unsigned i = pml4e_kernel; i < pml4e_offset; ++i) {
|
for (unsigned i = pml4e_kernel; i < pml4e_offset; ++i) {
|
||||||
page_table *pdp = kpml4->get(i);
|
page_table *pdp = kpml4->get(i);
|
||||||
|
|
||||||
@@ -118,5 +134,7 @@ memory_initialize(args::header *kargs)
|
|||||||
g_kernel_space);
|
g_kernel_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
fa->free(reinterpret_cast<uintptr_t>(kargs->page_table_cache), kargs->num_free_tables);
|
g_frame_allocator.free(
|
||||||
|
reinterpret_cast<uintptr_t>(kargs->page_table_cache),
|
||||||
|
kargs->num_free_tables);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
#include "j6/errors.h"
|
#include "j6/errors.h"
|
||||||
#include "j6/signals.h"
|
#include "j6/signals.h"
|
||||||
#include "j6/types.h"
|
#include "j6/types.h"
|
||||||
#include "kutil/heap_allocator.h"
|
|
||||||
#include "objects/kobject.h"
|
#include "objects/kobject.h"
|
||||||
|
|
||||||
extern kutil::heap_allocator g_kernel_heap;
|
|
||||||
|
|
||||||
// TODO: per-cpu this?
|
// TODO: per-cpu this?
|
||||||
static j6_koid_t next_koid;
|
static j6_koid_t next_koid;
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ using memory::page_mappable;
|
|||||||
using memory::pml4e_kernel;
|
using memory::pml4e_kernel;
|
||||||
using memory::table_entries;
|
using memory::table_entries;
|
||||||
|
|
||||||
page_manager g_page_manager(g_frame_allocator, 0);
|
|
||||||
extern kutil::vm_space g_kernel_space;
|
|
||||||
|
|
||||||
// NB: in 4KiB page table entries, bit 7 isn't pagesize but PAT. Currently this
|
// NB: in 4KiB page table entries, bit 7 isn't pagesize but PAT. Currently this
|
||||||
// doesn't matter, becasue in the default PAT table, both 000 and 100 are WB.
|
// doesn't matter, becasue in the default PAT table, both 000 and 100 are WB.
|
||||||
constexpr uint64_t sys_page_flags = 0x183; // global, pagesize, write, present
|
constexpr uint64_t sys_page_flags = 0x183; // global, pagesize, write, present
|
||||||
@@ -321,6 +318,7 @@ page_manager::fault_handler(uintptr_t addr)
|
|||||||
if (!addr)
|
if (!addr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
extern kutil::vm_space g_kernel_space;
|
||||||
bool is_heap = addr >= ::memory::heap_start &&
|
bool is_heap = addr >= ::memory::heap_start &&
|
||||||
addr < ::memory::heap_start + ::memory::kernel_max_heap;
|
addr < ::memory::heap_start + ::memory::kernel_max_heap;
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Global page manager.
|
/// Global page manager.
|
||||||
extern page_manager g_page_manager;
|
extern page_manager &g_page_manager;
|
||||||
|
|
||||||
inline page_manager * page_manager::get() { return &g_page_manager; }
|
inline page_manager * page_manager::get() { return &g_page_manager; }
|
||||||
|
|
||||||
@@ -206,12 +206,3 @@ page_table_align(T p)
|
|||||||
{
|
{
|
||||||
return ((p - 1) & ~0x1fffffull) + 0x200000;
|
return ((p - 1) & ~0x1fffffull) + 0x200000;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace kernel {
|
|
||||||
namespace args {
|
|
||||||
struct header;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Bootstrap the memory managers.
|
|
||||||
void memory_initialize(kernel::args::header *mem_map);
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
serial_port g_com1;
|
serial_port g_com1(COM1);
|
||||||
|
|
||||||
|
|
||||||
serial_port::serial_port() :
|
serial_port::serial_port() :
|
||||||
|
|||||||
@@ -18,11 +18,18 @@ enum class level : uint8_t {
|
|||||||
class logger
|
class logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// Callback type for immediate-mode logging
|
||||||
|
typedef void (*immediate)(area_t, level, const char *);
|
||||||
|
|
||||||
/// Default constructor. Creates a logger without a backing store.
|
/// Default constructor. Creates a logger without a backing store.
|
||||||
logger();
|
/// \arg output Immediate-mode logging output function
|
||||||
|
logger(immediate output = nullptr);
|
||||||
|
|
||||||
/// Constructor. Logs are written to the given buffer.
|
/// Constructor. Logs are written to the given buffer.
|
||||||
logger(uint8_t *buffer, size_t size);
|
/// \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);
|
||||||
|
|
||||||
/// Register a log area for future use.
|
/// Register a log area for future use.
|
||||||
/// \arg area The key for the new area
|
/// \arg area The key for the new area
|
||||||
@@ -30,9 +37,6 @@ public:
|
|||||||
/// \arg verbosity What level of logs to print for this area
|
/// \arg verbosity What level of logs to print for this area
|
||||||
void register_area(area_t area, const char *name, level verbosity);
|
void register_area(area_t area, const char *name, level verbosity);
|
||||||
|
|
||||||
/// Callback type for immediate-mode logging
|
|
||||||
typedef void (*immediate)(area_t, level, const char *);
|
|
||||||
|
|
||||||
/// Register an immediate-mode log callback
|
/// Register an immediate-mode log callback
|
||||||
inline void set_immediate(immediate cb) { m_immediate = cb; }
|
inline void set_immediate(immediate cb) { m_immediate = cb; }
|
||||||
|
|
||||||
|
|||||||
15
src/libraries/kutil/include/kutil/no_construct.h
Normal file
15
src/libraries/kutil/include/kutil/no_construct.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
/// \file no_construct.h
|
||||||
|
/// Tools for creating objects witout running constructors
|
||||||
|
|
||||||
|
namespace kutil {
|
||||||
|
|
||||||
|
/// Helper template for creating objects witout running constructors
|
||||||
|
template <typename T>
|
||||||
|
union no_construct
|
||||||
|
{
|
||||||
|
T value;
|
||||||
|
no_construct() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kutil
|
||||||
@@ -21,9 +21,9 @@ using kutil::memcpy;
|
|||||||
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"};
|
||||||
|
|
||||||
logger::logger() :
|
logger::logger(logger::immediate output) :
|
||||||
m_buffer(nullptr, 0),
|
m_buffer(nullptr, 0),
|
||||||
m_immediate(nullptr),
|
m_immediate(output),
|
||||||
m_sequence(0)
|
m_sequence(0)
|
||||||
{
|
{
|
||||||
memset(&m_levels, 0, sizeof(m_levels));
|
memset(&m_levels, 0, sizeof(m_levels));
|
||||||
@@ -31,9 +31,9 @@ logger::logger() :
|
|||||||
s_log = this;
|
s_log = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger::logger(uint8_t *buffer, size_t size) :
|
logger::logger(uint8_t *buffer, size_t size, logger::immediate output) :
|
||||||
m_buffer(buffer, size),
|
m_buffer(buffer, size),
|
||||||
m_immediate(nullptr),
|
m_immediate(output),
|
||||||
m_sequence(0)
|
m_sequence(0)
|
||||||
{
|
{
|
||||||
memset(&m_levels, 0, sizeof(m_levels));
|
memset(&m_levels, 0, sizeof(m_levels));
|
||||||
|
|||||||
Reference in New Issue
Block a user