Changes in uspace/app/klog/klog.c [4e1a2f5:6119f24] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/klog/klog.c
r4e1a2f5 r6119f24 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 ID.146 * @param call IPC call structure.147 *148 */149 static void notification_received(ipc_callid_t callid, ipc_call_t *call)150 {151 /*152 * Make sure we process only a single notification153 * at any time to limit the chance of the consumer154 * starving.155 *156 * Note: Usually the automatic masking of the klog157 * notifications on the kernel side does the trick158 * of limiting the chance of accidentally copying159 * the same data multiple times. However, due to160 * the non-blocking architecture of klog notifications,161 * this possibility cannot be generally avoided.162 */163 164 fibril_mutex_lock(&mtx);165 166 58 size_t klog_start = (size_t) IPC_GET_ARG1(*call); 167 59 size_t klog_len = (size_t) IPC_GET_ARG2(*call); 168 60 size_t klog_stored = (size_t) IPC_GET_ARG3(*call); 61 size_t i; 169 62 170 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 } 171 71 172 /* Copy data from the ring buffer */ 173 if (offset + klog_stored >= klog_length) { 174 size_t split = klog_length - offset; 175 176 producer(split, klog + offset); 177 producer(klog_stored - split, klog); 178 } else 179 producer(klog_stored, klog + offset); 180 181 event_unmask(EVENT_KLOG); 182 fibril_mutex_unlock(&mtx); 72 if (log != NULL) { 73 fflush(log); 74 fsync(fileno(log)); 75 } 183 76 } 184 77 … … 218 111 } 219 112 220 prodcons_initialize(&pc);221 async_set_interrupt_received(notification_received);222 113 rc = event_subscribe(EVENT_KLOG, 0); 223 114 if (rc != EOK) { … … 227 118 } 228 119 229 fid_t fid = fibril_create(consumer, NULL); 230 if (!fid) { 231 fprintf(stderr, "%s: Unable to create consumer fibril\n", 232 NAME); 233 return ENOMEM; 234 } 120 /* 121 * Mode "a" would be definitively much better here, but it is 122 * not well supported by the FAT driver. 123 */ 124 log = fopen(LOG_FNAME, "w"); 125 if (log == NULL) 126 printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME, 127 str_error(errno)); 235 128 236 fibril_add_ready(fid); 237 event_unmask(EVENT_KLOG); 129 async_set_interrupt_received(interrupt_received); 238 130 klog_update(); 239 240 task_retval(0);241 131 async_manager(); 242 132
Note:
See TracChangeset
for help on using the changeset viewer.