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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • 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.