diff --git a/.gitignore b/.gitignore index 67af79a..33e7cad 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ build/ drive.img drive.tar qemu_log.txt + +cross-build/ diff --git a/design/logging.md b/design/logging.md new file mode 100644 index 0000000..65ddaae --- /dev/null +++ b/design/logging.md @@ -0,0 +1,164 @@ +# Logging + + +\[ [Usage](#usage) \] + +The kernel logging system provides convenient, standardized and configurable +logging. + +Features include + +- Formatted log messages with time, level, file name / line number, service and message +- printf style string formatting +- Lazy evaluation of string formatting +- Macros to exclude log levels at compile time +- Runtime configurable log level +- File and level service names +- Compile time configurable file level logging level + +> [!IMPORTANT] +> Currently all logging is written to serial port 1. No logs are retained in +> memory or on disk. + +## Usage + +Each C file should define `KLOG_SERVICE` as the first line in the file. This +must be defined before including `"kernel/logs.h"`. The service name should be +all uppercase with the component name and file path under the components src/ +separated by `/` (eg. src/kernel/src/memory.c would be `KERNEL/MEMORY` excluding +the prefix and interior src/). + +```c +#define KLOG_SERVICE "KERNEL/MEMORY" +#include "kernel/logs.h" +... +``` + +To modify the compile time log level, also define `KLOG_LEVEL` in the file +before including `"kernel/logs.h"`. + +```c +#define KLOG_SERVICE "KERNEL/MEMORY" +#define KLOG_LEVEL KERNEL_LOG_LEVEL_TRACE // default level is debug +#include "kernel/logs.h" +... +``` + +Logging macros use printf style string formatting. The message should not +include newlines (those are appended by the logging system during formatting). + +```c +KLOG_INFO("message %u name %s", 42, "hello world"); +``` + +The logging system is limited to the kernel and should not be used in +application or user space code. + +| Level | Macro | Usage | +| ------- | -------------- | ------------------------------------------------- | +| Error | `KLOG_ERROR` | Something is wrong with the code | +| Warning | `KLOG_WARNING` | Someone is using the code incorrectly | +| Info | `KLOG_INFO` | Information that's useful during normal operation | +| Debug | `KLOG_DEBUG` | Information that's useful during troubleshooting | +| Trace | `KLOG_TRACE` | Information that's useful during development | + + +### When to use Error + +Use the Error level when the code must stop execution due to some condition. +This can be checking results of a function call or when performing input +validation. These messages should be short but descriptive avoiding format +variables where practical (ie. don't include all function args in the message). + +Error messages typically mean something is wrong with the code. + +Error should not be used when a return path is intended (eg. passing through +an error). If an error happens, there should only be 1 log message for it as +close to the error as possible. Any callers that receive the error should avoid +further logging if possible. + +**Example** + +```c +int open_something(const char * path) { + if (!path) { + KLOG_ERROR("Trying to open path from null pointer"); + return 0; + } + ... +} +int check_something(const char * path) { + int id = open_something(path); + if (!id) { + // The error was already logged so no error log is needed. Use lower levels if needed. + return 0; + } + ... +} +``` + +### When to use Warning + +**TODO** this might get more use in place of ERROR + +Use the Warning level for conditions that are unexpected or errors that do not +prevent further execution. This can be These messages should be short but descriptive +avoiding format variables where practical (ie. don't include all function args +in the message). + +Warning messages typically mean code is being used incorrectly. + +**Example** + +```c +int malloc(size_t size) { + if (!size) { + KLOG_WARNING("Malloc called with size 0"); + } + ... +} +``` + +### When to use Info + +**TODO** might need to split how DEBUG is being used so info gets more use + +There aren't many examples of using the Info level. It's mostly reserved for +major state transitions or user events (eg. opening a connection or device). + +**Example** + +```c +KLOG_INFO("Loader Start"); +KLOG_INFO("Kernel Start"); +... +KLOG_INFO("Halting"); +``` + +### When to use Debug + +Use the debug level for state or decisions. These can include printf values when +relevant but logging many variables should use trace where possible. Avoid using +in loops or functions with high call frequency. + +**Example** + +```c +KLOG_DEBUG("vga init finished"); +``` + +### When to use Trace + +Use the trace level for information useful during development or debugging, but +considered noise during normal operation. These log messages are pruned at +compile time by default so they do not incur any additional costs at runtime. + +> [!IMPORTANT] +> Try to avoid calling calling expensive functions as parameters to trace level +> messages. + +**Example** + +```c +KLOG_TRACE("Freed temporary page %u with virtual address %p from physical address %p", i, vaddr, paddr); +``` diff --git a/design/style_guide/code.md b/design/style_guide/code.md new file mode 100644 index 0000000..7f55a9c --- /dev/null +++ b/design/style_guide/code.md @@ -0,0 +1,36 @@ +# Style Guide for Code + + +\[ [Header Guards](#header-guards) \] +\[ [Function Names](#function-names) \] +\[ [Memory Ownership](#memory-ownership) \] + +## Header Guards + +All C code in src/ should use traditional guard style with the file path +(excluding src prefix) in upper snake case separated with underscores. A +comment should be included on the `#endif` line with the same name. + +```c +#ifndef PATH_UPPER_SNAKE_CASE_H +#define PATH_UPPER_SNAKE_CASE_H +... +#endif // PATH_UPPER_SNAKE_CASE_H +``` + +All C++ code or C code outside src/ should use `#pragma once` + +```c++ +#pragma once +... +``` + +## Function Names + +Function names should include the module (ie. path) as a prefix using snake +case. + +## Memory Ownership + +TODO + diff --git a/design/STYLE.md b/design/style_guide/design_docs.md similarity index 100% rename from design/STYLE.md rename to design/style_guide/design_docs.md