Architectural Support: x86_64 (#37)
[lunaix-os.git] / lunaix-os / kernel / kprint / kprintf.c
1 #include <lunaix/fs/twifs.h>
2 #include <lunaix/fs/twimap.h>
3 #include <lunaix/syscall.h>
4 #include <lunaix/syscall_utils.h>
5 #include <lunaix/syslog.h>
6 #include <lunaix/device.h>
7 #include <lunaix/owloysius.h>
8
9 #include <hal/term.h>
10
11 #include <klibc/strfmt.h>
12
13 #include "kp_records.h"
14
15 #define MAX_BUFSZ 512
16 #define MAX_BUFSZ_HLF 256
17 #define MAX_KPENT_NUM 1024
18
19 static char tmp_buf[MAX_BUFSZ];
20
21 static struct kp_records kprecs = {
22     .kp_ents = { .ents = { .next = &kprecs.kp_ents.ents,
23                            .prev = &kprecs.kp_ents.ents } },
24     .max_recs = MAX_KPENT_NUM,
25     .kp_ent_wp = &kprecs.kp_ents.ents
26 };
27 export_symbol(debug, kprintf, kprecs);
28
29 static char*
30 shift_level(const char* str, int* level)
31 {
32     if (str[0] == KMSG_LVLSTART) {
33         *level = KMSG_LOGLEVEL(str[1]);
34
35         return str += 2;
36     }
37
38     *level = KLOG_INFO;
39     return str;
40 }
41
42 static inline void
43 kprintf_put(int level, const char* buf, size_t sz)
44 {
45     kprec_put(&kprecs, level, buf, sz);
46
47     if (likely(sysconsole)) {
48         sysconsole->ops.write(sysconsole, buf, 0, sz);
49     }
50 }
51
52 static inline void
53 kprintf_ml(const char* component, int level, const char* fmt, va_list args)
54 {
55     char* buf = &tmp_buf[MAX_BUFSZ_HLF];
56     ksnprintf(buf, MAX_BUFSZ_HLF, "%s: %s\n", component, fmt);
57
58     size_t sz = ksnprintfv(tmp_buf, buf, MAX_BUFSZ_HLF, args);
59     kprintf_put(level, tmp_buf, sz);
60 }
61
62 void
63 kprintf_m(const char* component, const char* fmt, va_list args)
64 {
65     int level;
66     fmt = shift_level(fmt, &level);
67
68     kprintf_ml(component, level, fmt, args);
69 }
70
71 static void
72 __twimap_kprintf_read(struct twimap* map)
73 {
74     struct kp_records* __kprecs = twimap_data(map, struct kp_records*);
75
76     /*
77         XXX we can foreach all records in a single twimap read call,
78             as records is monotonic increasing by design.
79     */
80     struct kp_entry *pos, *n;
81     llist_for_each(pos, n, __kprecs->kp_ent_wp, ents)
82     {
83         time_t s = pos->time / 1000;
84         time_t ms = pos->time % 1000;
85         twimap_printf(map, "[%05d.%03d] %s\n", s, ms, pos->content);
86     }
87 }
88
89 static void
90 kprintf_mapping_init()
91 {
92     twimap_entry_simple(NULL, "kmsg", &kprecs, __twimap_kprintf_read);
93 }
94 EXPORT_TWIFS_PLUGIN(kprintf, kprintf_mapping_init);
95
96
97 void 
98 kprintf_dump_logs() {
99     if (unlikely(!sysconsole)) {
100         return;
101     }
102
103     struct kp_entry *pos, *n;
104     llist_for_each(pos, n, kprecs.kp_ent_wp, ents)
105     {
106         sysconsole->ops.write(sysconsole, pos->content, 0, pos->len);
107     }
108 }
109
110 __DEFINE_LXSYSCALL3(void, syslog, int, level, 
111                     const char*, buf, unsigned int, size)
112 {
113     kprintf_put(level, buf, size);
114 }