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
16static spinlock_t global_syslog_lock;
17
18static 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
55long 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
86mos::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
105mos::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