| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "mos/syslog/syslog.hpp" |
| 4 | |
| 5 | #include "mos/device/console.hpp" |
| 6 | #include "mos/platform/platform.hpp" |
| 7 | #include "mos/tasks/task_types.hpp" |
| 8 | #include "proto/syslog.pb.h" |
| 9 | |
| 10 | #include <ansi_colors.h> |
| 11 | #include <mos/compiler.h> |
| 12 | #include <mos/mos_global.h> |
| 13 | #include <mos_stdio.hpp> |
| 14 | #include <pb_encode.h> |
| 15 | |
| 16 | static spinlock_t global_syslog_lock; |
| 17 | |
| 18 | static void do_print_syslog(const pb_syslog_message *msg, const debug_info_entry *feat) |
| 19 | { |
| 20 | const LogLevel level = (LogLevel) msg->info.level; |
| 21 | spinlock_acquire(&global_syslog_lock); |
| 22 | |
| 23 | if (level != LogLevel::UNSET) |
| 24 | { |
| 25 | lprintk(loglevel: level, format: "\r\n" ); |
| 26 | if (feat) |
| 27 | lprintk(loglevel: level, format: "%-10s | " , feat->name); |
| 28 | |
| 29 | #if MOS_CONFIG(MOS_PRINTK_WITH_TIMESTAMP) |
| 30 | lprintk(level, "%-16lu | " , msg->timestamp); |
| 31 | #endif |
| 32 | |
| 33 | #if MOS_CONFIG(MOS_PRINTK_WITH_DATETIME) |
| 34 | lprintk(level, "%s | " , (const char *) platform_get_datetime_str()); |
| 35 | #endif |
| 36 | |
| 37 | #if MOS_CONFIG(MOS_PRINTK_WITH_CPU_ID) |
| 38 | lprintk(level, "cpu %2d | " , msg->cpu_id); |
| 39 | #endif |
| 40 | |
| 41 | #if MOS_CONFIG(MOS_PRINTK_WITH_FILENAME) |
| 42 | lprintk(loglevel: level, format: "%-15s | " , msg->info.source_location.filename); |
| 43 | #endif |
| 44 | |
| 45 | #if MOS_CONFIG(MOS_PRINTK_WITH_THREAD_ID) |
| 46 | lprintk(level, "[t%d:%s]\t| " , msg->thread.tid, msg->thread.name); |
| 47 | #endif |
| 48 | } |
| 49 | |
| 50 | lprintk(loglevel: level, format: "%s" , msg->message); |
| 51 | |
| 52 | spinlock_release(&global_syslog_lock); |
| 53 | } |
| 54 | |
| 55 | long do_syslog(LogLevel level, const char *file, const char *func, int line, const debug_info_entry *feat, const char *fmt, ...) |
| 56 | { |
| 57 | auto const thread = current_thread; |
| 58 | pb_syslog_message msg = { |
| 59 | .timestamp = platform_get_timestamp(), |
| 60 | .cpu_id = platform_current_cpu_id(), |
| 61 | }; |
| 62 | |
| 63 | msg.info.level = (syslog_level) level; |
| 64 | msg.info.featid = feat ? feat->id : 0; |
| 65 | msg.info.source_location.line = line; |
| 66 | strncpy(dest: msg.info.source_location.filename, src: file, n: sizeof(msg.info.source_location.filename)); |
| 67 | strncpy(dest: msg.info.source_location.function, src: func, n: sizeof(msg.info.source_location.function)); |
| 68 | |
| 69 | if (thread) |
| 70 | { |
| 71 | msg.thread.tid = thread->tid; |
| 72 | msg.process.pid = thread->owner->pid; |
| 73 | strncpy(dest: msg.thread.name, src: thread->name.c_str(), n: sizeof(msg.thread.name)); |
| 74 | strncpy(dest: msg.process.name, src: thread->owner->name.c_str(), n: sizeof(msg.process.name)); |
| 75 | } |
| 76 | |
| 77 | va_list args; |
| 78 | va_start(args, fmt); |
| 79 | vsnprintf(buf: msg.message, size: sizeof(msg.message), format: fmt, args); |
| 80 | va_end(args); |
| 81 | |
| 82 | do_print_syslog(msg: &msg, feat); |
| 83 | return 0; |
| 84 | } |
| 85 | |
| 86 | mos::SyslogStreamWriter::SyslogStreamWriter(DebugFeature feature, LogLevel level, RCCore *rcCore, SyslogBuffer &fmtbuffer) |
| 87 | : RefCounted(rcCore), // |
| 88 | fmtbuffer(fmtbuffer), // |
| 89 | timestamp(platform_get_timestamp()), // |
| 90 | feature(feature), // |
| 91 | level(level), // |
| 92 | should_print(!mos_debug_info_map[feature] || mos_debug_info_map[feature]->enabled) // |
| 93 | { |
| 94 | if (level != LogLevel::UNSET) |
| 95 | { |
| 96 | pos++; |
| 97 | fmtbuffer[0] = '\n'; |
| 98 | fmtbuffer[1] = '\0'; |
| 99 | } |
| 100 | |
| 101 | if (should_print && mos_debug_info_map[feature]) |
| 102 | pos += snprintf(str: fmtbuffer.data() + pos, MOS_PRINTK_BUFFER_SIZE - pos, format: "%-10s | " , mos_debug_info_map[feature]->name); |
| 103 | } |
| 104 | |
| 105 | mos::SyslogStreamWriter::~SyslogStreamWriter() |
| 106 | { |
| 107 | if (GetRef() == 1) |
| 108 | { |
| 109 | if (!should_print) |
| 110 | return; |
| 111 | |
| 112 | if (unlikely(!printk_console)) |
| 113 | printk_console = consoles.front(); |
| 114 | |
| 115 | print_to_console(con: printk_console, loglevel: level, message: fmtbuffer.data(), len: pos); |
| 116 | fmtbuffer[0] = '\0'; |
| 117 | pos = -1; |
| 118 | } |
| 119 | } |
| 120 | |