source: mainline/uspace/srv/klog/klog.c

Last change on this file was 4122410, checked in by Jakub Jermar <jakub@…>, 7 years ago

Improve Doxygen documentaion

This is stil WiP. A number of libraries, drivers and services were
converted to using a more hierarchical and decentralized scheme when it
comes to specifying to which doxygen group they belong.

  • 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
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
38#include <async.h>
39#include <as.h>
40#include <ddi.h>
41#include <errno.h>
42#include <str_error.h>
43#include <io/klog.h>
44#include <sysinfo.h>
45#include <stdlib.h>
46#include <fibril_synch.h>
47#include <adt/list.h>
48#include <adt/prodcons.h>
49#include <io/log.h>
50#include <io/logctl.h>
51
52#define NAME "klog"
53
54typedef size_t __attribute__((aligned(1))) unaligned_size_t;
55
56typedef struct {
57 size_t entry_len;
58 uint32_t serial;
59 uint32_t facility;
60 uint32_t level;
61 char message[0];
62
63} __attribute__((__packed__)) log_entry_t;
64
65/* Producer/consumer buffers */
66typedef struct {
67 link_t link;
68 size_t size;
69 log_entry_t *data;
70} item_t;
71
72static prodcons_t pc;
73
74/* Pointer to buffer where kernel stores new entries */
75#define BUFFER_SIZE PAGE_SIZE
76static void *buffer;
77
78/* Notification mutex */
79static FIBRIL_MUTEX_INITIALIZE(mtx);
80
81static log_t kernel_ctx;
82static const char *facility_name[] = {
83 "other",
84 "uspace",
85 "arch"
86};
87
88#define facility_len (sizeof(facility_name) / sizeof(const char *))
89static log_t facility_ctx[facility_len];
90
91/** Klog producer
92 *
93 * Copies the log entries to a producer/consumer queue.
94 *
95 * @param length Number of characters to copy.
96 * @param data Pointer to the kernel klog buffer.
97 *
98 */
99static void producer(void)
100{
101 size_t len = 0;
102 errno_t rc = klog_read(buffer, BUFFER_SIZE, &len);
103 if (rc != EOK) {
104 log_msg(LOG_DEFAULT, LVL_ERROR, "klog_read failed, rc = %s",
105 str_error_name(rc));
106 return;
107 }
108
109 size_t offset = 0;
110 while (offset < len) {
111 size_t entry_len = *((unaligned_size_t *) (buffer + offset));
112
113 if (offset + entry_len > len || entry_len < sizeof(log_entry_t))
114 break;
115
116 log_entry_t *buf = malloc(entry_len + 1);
117 if (buf == NULL)
118 break;
119
120 item_t *item = malloc(sizeof(item_t));
121 if (item == NULL) {
122 free(buf);
123 break;
124 }
125
126 memcpy(buf, buffer + offset, entry_len);
127 *((uint8_t *) buf + entry_len) = 0;
128 link_initialize(&item->link);
129 item->size = entry_len;
130 item->data = buf;
131 prodcons_produce(&pc, &item->link);
132
133 offset += entry_len;
134 }
135}
136
137/** Klog consumer
138 *
139 * Waits in an infinite loop for the log data created by
140 * the producer and logs them to the logger.
141 *
142 * @param data Unused.
143 *
144 * @return Always EOK (unreachable).
145 *
146 */
147static errno_t consumer(void *data)
148{
149
150 while (true) {
151 link_t *link = prodcons_consume(&pc);
152 item_t *item = list_get_instance(link, item_t, link);
153
154 if (item->size < sizeof(log_entry_t)) {
155 free(item->data);
156 free(item);
157 continue;
158 }
159
160 if (item->data->facility == LF_USPACE) {
161 /* Avoid reposting messages */
162 free(item->data);
163 free(item);
164 continue;
165 }
166
167 log_t ctx = kernel_ctx;
168 if (item->data->facility < facility_len) {
169 ctx = facility_ctx[item->data->facility];
170 }
171
172 log_level_t lvl = item->data->level;
173 if (lvl > LVL_LIMIT)
174 lvl = LVL_NOTE;
175
176 log_msg(ctx, lvl, "%s", item->data->message);
177
178 free(item->data);
179 free(item);
180 }
181
182 return EOK;
183}
184
185/** Kernel notification handler
186 *
187 * Receives kernel klog notifications.
188 *
189 * @param call IPC call structure
190 * @param arg Local argument
191 *
192 */
193static void klog_notification_received(ipc_call_t *call, void *arg)
194{
195 /*
196 * Make sure we process only a single notification
197 * at any time to limit the chance of the consumer
198 * starving.
199 */
200
201 fibril_mutex_lock(&mtx);
202
203 producer();
204
205 async_event_unmask(EVENT_KLOG);
206 fibril_mutex_unlock(&mtx);
207}
208
209int main(int argc, char *argv[])
210{
211 errno_t rc = log_init(NAME);
212 if (rc != EOK) {
213 fprintf(stderr, "%s: Unable to initialize log\n", NAME);
214 return rc;
215 }
216
217 kernel_ctx = log_create("kernel", LOG_NO_PARENT);
218 for (unsigned int i = 0; i < facility_len; i++) {
219 facility_ctx[i] = log_create(facility_name[i], kernel_ctx);
220 }
221
222 buffer = malloc(BUFFER_SIZE);
223 if (buffer == NULL) {
224 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to allocate buffer");
225 return 1;
226 }
227
228 prodcons_initialize(&pc);
229 rc = async_event_subscribe(EVENT_KLOG, klog_notification_received, NULL);
230 if (rc != EOK) {
231 log_msg(LOG_DEFAULT, LVL_ERROR,
232 "Unable to register klog notifications");
233 return rc;
234 }
235
236 fid_t fid = fibril_create(consumer, NULL);
237 if (!fid) {
238 log_msg(LOG_DEFAULT, LVL_ERROR,
239 "Unable to create consumer fibril");
240 return ENOMEM;
241 }
242
243 fibril_add_ready(fid);
244 async_event_unmask(EVENT_KLOG);
245
246 fibril_mutex_lock(&mtx);
247 producer();
248 fibril_mutex_unlock(&mtx);
249
250 task_retval(0);
251 async_manager();
252
253 return 0;
254}
255
256/** @}
257 */
Note: See TracBrowser for help on using the repository browser.