Changes in uspace/app/klog/klog.c [3815efb:382cd26] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/klog/klog.c
r3815efb r382cd26 44 44 #include <io/klog.h> 45 45 #include <sysinfo.h> 46 #include <malloc.h>47 #include <fibril_synch.h>48 #include <adt/list.h>49 #include <adt/prodcons.h>50 46 51 47 #define NAME "klog" 52 48 #define LOG_FNAME "/log/klog" 53 54 /* Producer/consumer buffers */55 typedef struct {56 link_t link;57 size_t length;58 wchar_t *data;59 } item_t;60 61 static prodcons_t pc;62 49 63 50 /* Pointer to klog area */ … … 65 52 static size_t klog_length; 66 53 67 /* Notification mutex */ 68 static FIBRIL_MUTEX_INITIALIZE(mtx); 54 static FILE *log; 69 55 70 /** Klog producer 71 * 72 * Copies the contents of a character buffer to local 73 * producer/consumer queue. 74 * 75 * @param length Number of characters to copy. 76 * @param data Pointer to the kernel klog buffer. 77 * 78 */ 79 static void producer(size_t length, wchar_t *data) 56 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) 80 57 { 81 item_t *item = (item_t *) malloc(sizeof(item_t));82 if (item == NULL)83 return;84 85 size_t sz = sizeof(wchar_t) * length;86 wchar_t *buf = (wchar_t *) malloc(sz);87 if (data == NULL) {88 free(item);89 return;90 }91 92 memcpy(buf, data, sz);93 94 link_initialize(&item->link);95 item->length = length;96 item->data = buf;97 prodcons_produce(&pc, &item->link);98 }99 100 /** Klog consumer101 *102 * Waits in an infinite loop for the character data created by103 * the producer and outputs them to stdout and optionally into104 * a file.105 *106 * @param data Unused.107 *108 * @return Always EOK (unreachable).109 *110 */111 static int consumer(void *data)112 {113 FILE *log = fopen(LOG_FNAME, "a");114 if (log == NULL)115 printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,116 str_error(errno));117 118 while (true) {119 link_t *link = prodcons_consume(&pc);120 item_t *item = list_get_instance(link, item_t, link);121 122 for (size_t i = 0; i < item->length; i++)123 putchar(item->data[i]);124 125 if (log != NULL) {126 for (size_t i = 0; i < item->length; i++)127 fputc(item->data[i], log);128 129 fflush(log);130 fsync(fileno(log));131 }132 133 free(item->data);134 free(item);135 }136 137 fclose(log);138 return EOK;139 }140 141 /** Kernel notification handler142 *143 * Receives kernel klog notifications.144 *145 * @param callid IPC call ID146 * @param call IPC call structure147 * @param arg Local argument148 *149 */150 static void notification_received(ipc_callid_t callid, ipc_call_t *call)151 {152 /*153 * Make sure we process only a single notification154 * at any time to limit the chance of the consumer155 * starving.156 *157 * Note: Usually the automatic masking of the klog158 * notifications on the kernel side does the trick159 * of limiting the chance of accidentally copying160 * the same data multiple times. However, due to161 * the non-blocking architecture of klog notifications,162 * this possibility cannot be generally avoided.163 */164 165 fibril_mutex_lock(&mtx);166 167 58 size_t klog_start = (size_t) IPC_GET_ARG1(*call); 168 59 size_t klog_len = (size_t) IPC_GET_ARG2(*call); 169 60 size_t klog_stored = (size_t) IPC_GET_ARG3(*call); 61 size_t i; 170 62 171 size_t offset = (klog_start + klog_len - klog_stored) % klog_length; 63 for (i = klog_len - klog_stored; i < klog_len; i++) { 64 wchar_t ch = klog[(klog_start + i) % klog_length]; 65 66 putchar(ch); 67 68 if (log != NULL) 69 fputc(ch, log); 70 } 172 71 173 /* Copy data from the ring buffer */ 174 if (offset + klog_stored >= klog_length) { 175 size_t split = klog_length - offset; 176 177 producer(split, klog + offset); 178 producer(klog_stored - split, klog); 179 } else 180 producer(klog_stored, klog + offset); 181 182 event_unmask(EVENT_KLOG); 183 fibril_mutex_unlock(&mtx); 72 if (log != NULL) { 73 fflush(log); 74 fsync(fileno(log)); 75 } 184 76 } 185 77 … … 219 111 } 220 112 221 prodcons_initialize(&pc);222 async_set_interrupt_received(notification_received);223 113 rc = event_subscribe(EVENT_KLOG, 0); 224 114 if (rc != EOK) { … … 228 118 } 229 119 230 fid_t fid = fibril_create(consumer, NULL); 231 if (!fid) { 232 fprintf(stderr, "%s: Unable to create consumer fibril\n", 233 NAME); 234 return ENOMEM; 235 } 120 log = fopen(LOG_FNAME, "a"); 121 if (log == NULL) 122 printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME, 123 str_error(errno)); 236 124 237 fibril_add_ready(fid); 238 event_unmask(EVENT_KLOG); 125 async_set_interrupt_received(interrupt_received); 239 126 klog_update(); 240 241 task_retval(0);242 127 async_manager(); 243 128
Note:
See TracChangeset
for help on using the changeset viewer.