-
Notifications
You must be signed in to change notification settings - Fork 18
Logging rewrite #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Logging rewrite #92
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,97 @@ | ||
| #include "klog.h" | ||
|
|
||
| #include <stdarg.h> | ||
| #include <stdbigos/stdio.h> | ||
| #include <stdbigos/types.h> | ||
|
|
||
| // NOTE: In the future this lib should manage logging (formating and outputing to the screen or uart) on its own. | ||
| // Right now I will leave it as is, will change once the basic kernel at least runs. | ||
| #include "debug/debug_stdio.h" | ||
|
|
||
| static u32 g_indent_level = 0; | ||
| static const char* g_prefixes[] = {"[ERROR]", "[WARNING]", "[ ]", "[~]"}; | ||
| static const char* g_overflow_warning = "[WARNING]Some of the logs were lost due to overflow"; | ||
|
|
||
| #ifdef __DEBUG__ | ||
| #define RING_BUF_SIZE (1 << 20) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no point of using macros, just use const size_t RING_BUF_SIZE = ...; |
||
| #else | ||
| #define RING_BUF_SIZE (1 << 16) | ||
| #endif // !__DEBUG__ | ||
|
|
||
| #define TEMP_BUF_SIZE (1 << 12) | ||
|
|
||
| typedef struct { | ||
| char ring[RING_BUF_SIZE]; | ||
| i32 read; | ||
| i32 write; | ||
| bool full; | ||
| bool overflown; | ||
| void (*uart_tx)(char c); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this should be a part of the ring buffer structure. |
||
| } ring_buffer_t; | ||
|
|
||
| static ring_buffer_t g_buffer; | ||
|
|
||
| static ring_buffer_t* get_buffer() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this function necessary? |
||
| return &g_buffer; | ||
| } | ||
|
|
||
| static void put_char(ring_buffer_t* rb, const char c) { | ||
| if (c == '\0') | ||
| return; // Null characters are not suppossed to be logged. | ||
| rb->ring[rb->write++] = c; | ||
| rb->write %= RING_BUF_SIZE; | ||
| if (rb->full) { | ||
| rb->read = (rb->read + 1) % RING_BUF_SIZE; | ||
| rb->overflown = true; | ||
| } | ||
| rb->full = rb->read == rb->write; | ||
| if (rb->uart_tx) | ||
| rb->uart_tx(c); | ||
| } | ||
|
|
||
| static void put_string(ring_buffer_t* rb, const char* str) { | ||
| size_t it = 0; | ||
| while (str[it]) put_char(rb, str[it++]); | ||
| } | ||
|
|
||
| static void put_overflow_warning(ring_buffer_t* rb) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no point in copying this message to the ring buffer since it is stored already in static memory. |
||
| size_t it = 0; | ||
| i32 temp_write = rb->write; | ||
| while (g_overflow_warning[it]) { | ||
| rb->ring[temp_write++] = g_overflow_warning[it++]; | ||
| temp_write %= RING_BUF_SIZE; | ||
| } | ||
| } | ||
|
|
||
| static void put_msg(ring_buffer_t* rb, const char* msg) { | ||
| put_string(rb, msg); | ||
| if (rb->overflown) | ||
| put_overflow_warning(rb); | ||
| } | ||
|
|
||
| char ring_buffer_get_char() { | ||
| ring_buffer_t* rb = get_buffer(); | ||
| if (rb->read == rb->write && !rb->full) | ||
| return 0; | ||
| const char ret = rb->ring[rb->read++]; | ||
| rb->read %= RING_BUF_SIZE; | ||
| rb->full = false; | ||
| rb->overflown = false; | ||
| return ret; | ||
| } | ||
|
|
||
| void ring_buffer_flush_to_uart() { | ||
| ring_buffer_t* rb = get_buffer(); | ||
| if (!rb->uart_tx) | ||
| return; | ||
| char c; | ||
| while ((c = ring_buffer_get_char())) rb->uart_tx(c); | ||
| } | ||
|
|
||
| void ring_buffer_set_uart_tx_function(void (*uart_tx)(char c), bool flush) { | ||
| ring_buffer_t* rb = get_buffer(); | ||
| rb->uart_tx = uart_tx; | ||
| if (flush) | ||
| ring_buffer_flush_to_uart(); | ||
| } | ||
|
|
||
| void klog_indent_increase() { | ||
| ++g_indent_level; | ||
|
|
@@ -20,22 +103,45 @@ void klog_indent_decrease() { | |
| } | ||
|
|
||
| static void klogv(klog_severity_level_t loglvl, const char* fmt, va_list va) { | ||
| (void)fmt; | ||
| (void)va; | ||
| char temp_buffer[TEMP_BUF_SIZE]; | ||
|
|
||
| if (loglvl > KLSL_TRACE) { | ||
| KLOGLN_ERROR("Invalid loglvl passed to klog"); | ||
| loglvl = KLSL_ERROR; | ||
| } | ||
|
|
||
| DEBUG_PUTGAP(g_indent_level); | ||
| DEBUG_PRINTF("%s ", g_prefixes[loglvl]); | ||
| DEBUG_VPRINTF(fmt, va); | ||
| size_t written = 0; | ||
| for (u32 i = 0; i < g_indent_level && written < TEMP_BUF_SIZE - 1; i++) temp_buffer[written++] = ' '; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storing '\t' chars in the ring buffer can be potentially wasteful. ASCII values between 0 and 8 are not and will be not important for logger so we can store those values and when printing interpret then as the size of the indentation. |
||
|
|
||
| const char* prefix = g_prefixes[loglvl]; | ||
| for (size_t i = 0; prefix[i] && written < TEMP_BUF_SIZE - 1; i++) temp_buffer[written++] = prefix[i]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a space after the loglvl prefix. |
||
|
|
||
| va_list copy; | ||
| va_copy(copy, va); | ||
| int n = vsnprintf(temp_buffer + written, TEMP_BUF_SIZE - written, fmt, copy); | ||
| va_end(copy); | ||
|
|
||
| // stbsp_vsnprintf doesn't return errors, so just check for truncation | ||
| if (n < 0) | ||
| n = 0; | ||
| written += (size_t)n; | ||
|
|
||
| if (written >= TEMP_BUF_SIZE) | ||
| written = TEMP_BUF_SIZE - 1; | ||
| temp_buffer[written] = '\0'; | ||
|
|
||
| ring_buffer_t* rb = get_buffer(); | ||
| put_msg(rb, temp_buffer); | ||
|
|
||
| // DEBUG_PUTGAP(g_indent_level); | ||
| // DEBUG_PRINTF("%s ", g_prefixes[loglvl]); | ||
| // DEBUG_VPRINTF(fmt, va); | ||
| } | ||
|
|
||
| static void kloglnv(klog_severity_level_t loglvl, const char* fmt, va_list va) { | ||
| klogv(loglvl, fmt, va); | ||
| DEBUG_PUTC('\n'); | ||
| put_msg(&g_buffer, "\n"); | ||
| // DEBUG_PUTC('\n'); | ||
| } | ||
|
|
||
| void klog(klog_severity_level_t loglvl, const char* fmt, ...) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,9 @@ typedef enum { | |
| KLSL_TRACE = 3, | ||
| } klog_severity_level_t; | ||
|
|
||
| char ring_buffer_get_char(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existence of the ring buffer is some unimportant implementation detail for the logger user, there is no point in providing this information. Those function should be named something like "klog_flush_serial" "klog_set_serial_handler", the functionality of getting chars from the buffer is unnecessary. |
||
| void ring_buffer_flush_to_uart(); | ||
| void ring_buffer_set_uart_tx_function(void (*uart_tx)(char c), bool flush); | ||
| void klog_indent_increase(); | ||
| void klog_indent_decrease(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a space after the loglvl prefix.