source: mainline/uspace/srv/klog/klog.c@ 1420cae9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1420cae9 was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2006 Ondrej Palkovsky
3 * Copyright (c) 2013 Martin Sucha
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup klog KLog
31 * @brief HelenOS KLog
32 * @{
33 */
34/**
35 * @file
36 */
37
38#include <stdio.h>
39#include <async.h>
40#include <as.h>
41#include <ddi.h>
42#include <errno.h>
43#include <str_error.h>
44#include <io/klog.h>
45#include <sysinfo.h>
46#include <stdlib.h>
47#include <fibril_synch.h>
48#include <adt/list.h>
49#include <adt/prodcons.h>
50#include <io/log.h>
51#include <io/logctl.h>
52
53#define NAME "klog"
54
55typedef size_t __attribute__((aligned(1))) unaligned_size_t;
56
57typedef struct {
58 size_t entry_len;
59 uint32_t serial;
60 uint32_t facility;
61 uint32_t level;
62 char message[0];
63
64} __attribute__((__packed__)) log_entry_t;
65
66/* Producer/consumer buffers */
67typedef struct {
68 link_t link;
69 size_t size;
70 log_entry_t *data;
71} item_t;
72
73static prodcons_t pc;
74
75/* Pointer to buffer where kernel stores new entries */
76#define BUFFER_SIZE PAGE_SIZE
77static void *buffer;
78
79/* Notification mutex */
80static FIBRIL_MUTEX_INITIALIZE(mtx);
81
82static log_t kernel_ctx;
83static const char *facility_name[] = {
84 "other",
85 "uspace",
86 "arch"
87};
88
89#define facility_len (sizeof(facility_name) / sizeof(const char *))
90static log_t facility_ctx[facility_len];
91
92/** Klog producer
93 *
94 * Copies the log entries to a producer/consumer queue.
95 *
96 * @param length Number of characters to copy.
97 * @param data Pointer to the kernel klog buffer.
98 *
99 */
100static void producer(void)
101{
102 size_t len = 0;
103 errno_t rc = klog_read(buffer, BUFFER_SIZE, &len);
104 if (rc != EOK) {
105 log_msg(LOG_DEFAULT, LVL_ERROR, "klog_read failed, rc = %s",
106 str_error_name(rc));
107 return;
108 }
109
110 size_t offset = 0;
111 while (offset < len) {
112 size_t entry_len = *((unaligned_size_t *) (buffer + offset));
113
114 if (offset + entry_len > len || entry_len < sizeof(log_entry_t))
115 break;
116
117 log_entry_t *buf = malloc(entry_len + 1);
118 if (buf == NULL)
119 break;
120
121 item_t *item = malloc(sizeof(item_t));
122 if (item == NULL) {
123 free(buf);
124 break;
125 }
126
127 memcpy(buf, buffer + offset, entry_len);
128 *((uint8_t *) buf + entry_len) = 0;
129 link_initialize(&item->link);
130 item->size = entry_len;
131 item->data = buf;
132 prodcons_produce(&pc, &item->link);
133
134 offset += entry_len;
135 }
136}
137
138/** Klog consumer
139 *
140 * Waits in an infinite loop for the log data created by
141 * the producer and logs them to the logger.
142 *
143 * @param data Unused.
144 *
145 * @return Always EOK (unreachable).
146 *
147 */
148static errno_t consumer(void *data)
149{
150
151 while (true) {
152 link_t *link = prodcons_consume(&pc);
153 item_t *item = list_get_instance(link, item_t, link);
154
155 if (item->size < sizeof(log_entry_t)) {
156 free(item->data);
157 free(item);
158 continue;
159 }
160
161 if (item->data->facility == LF_USPACE) {
162 /* Avoid reposting messages */
163 free(item->data);
164 free(item);
165 continue;
166 }
167
168 log_t ctx = kernel_ctx;
169 if (item->data->facility < facility_len) {
170 ctx = facility_ctx[item->data->facility];
171 }
172
173 log_level_t lvl = item->data->level;
174 if (lvl > LVL_LIMIT)
175 lvl = LVL_NOTE;
176
177 log_msg(ctx, lvl, "%s", item->data->message);
178
179 free(item->data);
180 free(item);
181 }
182
183 return EOK;
184}
185
186/** Kernel notification handler
187 *
188 * Receives kernel klog notifications.
189 *
190 * @param call IPC call structure
191 * @param arg Local argument
192 *
193 */
194static void klog_notification_received(ipc_call_t *call, void *arg)
195{
196 /*
197 * Make sure we process only a single notification
198 * at any time to limit the chance of the consumer
199 * starving.
200 */
201
202 fibril_mutex_lock(&mtx);
203
204 producer();
205
206 async_event_unmask(EVENT_KLOG);
207 fibril_mutex_unlock(&mtx);
208}
209
210int main(int argc, char *argv[])
211{
212 errno_t rc = log_init(NAME);
213 if (rc != EOK) {
214 fprintf(stderr, "%s: Unable to initialize log\n", NAME);
215 return rc;
216 }
217
218 kernel_ctx = log_create("kernel", LOG_NO_PARENT);
219 for (unsigned int i = 0; i < facility_len; i++) {
220 facility_ctx[i] = log_create(facility_name[i], kernel_ctx);
221 }
222
223 buffer = malloc(BUFFER_SIZE);
224 if (buffer == NULL) {
225 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to allocate buffer");
226 return 1;
227 }
228
229 prodcons_initialize(&pc);
230 rc = async_event_subscribe(EVENT_KLOG, klog_notification_received, NULL);
231 if (rc != EOK) {
232 log_msg(LOG_DEFAULT, LVL_ERROR,
233 "Unable to register klog notifications");
234 return rc;
235 }
236
237 fid_t fid = fibril_create(consumer, NULL);
238 if (!fid) {
239 log_msg(LOG_DEFAULT, LVL_ERROR,
240 "Unable to create consumer fibril");
241 return ENOMEM;
242 }
243
244 fibril_add_ready(fid);
245 async_event_unmask(EVENT_KLOG);
246
247 fibril_mutex_lock(&mtx);
248 producer();
249 fibril_mutex_unlock(&mtx);
250
251 task_retval(0);
252 async_manager();
253
254 return 0;
255}
256
257/** @}
258 */
Note: See TracBrowser for help on using the repository browser.