Changes in / [0d8a304:8d308b9] in mainline
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/ipc/event.h
r0d8a304 r8d308b9 51 51 /** Counter. */ 52 52 size_t counter; 53 /** Masked flag. */54 bool masked;55 /** Unmask callback. */56 void (*unmask_cb)(void);57 53 } event_t; 58 54 59 55 extern void event_init(void); 56 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t); 57 extern bool event_is_subscribed(event_type_t); 60 58 extern void event_cleanup_answerbox(answerbox_t *); 61 extern void event_set_unmask_callback(event_type_t, void (*)(void));62 59 63 #define event_notify_0(e , m) \64 event_notify((e), (m),0, 0, 0, 0, 0)65 #define event_notify_1(e, m,a1) \66 event_notify((e), ( m), (a1), 0, 0, 0, 0)67 #define event_notify_2(e, m,a1, a2) \68 event_notify((e), ( m), (a1), (a2), 0, 0, 0)69 #define event_notify_3(e, m,a1, a2, a3) \70 event_notify((e), ( m), (a1), (a2), (a3), 0, 0)71 #define event_notify_4(e, m,a1, a2, a3, a4) \72 event_notify((e), ( m), (a1), (a2), (a3), (a4), 0)73 #define event_notify_5(e, m,a1, a2, a3, a4, a5) \74 event_notify((e), ( m), (a1), (a2), (a3), (a4), (a5))60 #define event_notify_0(e) \ 61 event_notify((e), 0, 0, 0, 0, 0) 62 #define event_notify_1(e, a1) \ 63 event_notify((e), (a1), 0, 0, 0, 0) 64 #define event_notify_2(e, a1, a2) \ 65 event_notify((e), (a1), (a2), 0, 0, 0) 66 #define event_notify_3(e, a1, a2, a3) \ 67 event_notify((e), (a1), (a2), (a3), 0, 0) 68 #define event_notify_4(e, a1, a2, a3, a4) \ 69 event_notify((e), (a1), (a2), (a3), (a4), 0) 70 #define event_notify_5(e, a1, a2, a3, a4, a5) \ 71 event_notify((e), (a1), (a2), (a3), (a4), (a5)) 75 72 76 extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,73 extern void event_notify(event_type_t, sysarg_t, sysarg_t, sysarg_t, 77 74 sysarg_t, sysarg_t); 78 79 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);80 extern sysarg_t sys_event_unmask(sysarg_t);81 75 82 76 #endif -
kernel/generic/include/ipc/event_types.h
r0d8a304 r8d308b9 39 39 /** New data available in kernel log */ 40 40 EVENT_KLOG = 0, 41 /** Returning from kernel console to us pace */41 /** Returning from kernel console to userspace */ 42 42 EVENT_KCONSOLE, 43 43 /** A task/thread has faulted and will be terminated */ -
kernel/generic/include/syscall/syscall.h
r0d8a304 r8d308b9 75 75 76 76 SYS_EVENT_SUBSCRIBE, 77 SYS_EVENT_UNMASK,78 77 79 78 SYS_CAP_GRANT, -
kernel/generic/src/console/cmd.c
r0d8a304 r8d308b9 1107 1107 release_console(); 1108 1108 1109 event_notify_0(EVENT_KCONSOLE , false);1109 event_notify_0(EVENT_KCONSOLE); 1110 1110 indev_pop_character(stdin); 1111 1111 -
kernel/generic/src/console/console.c
r0d8a304 r8d308b9 53 53 #include <str.h> 54 54 55 #define KLOG_PAGES 855 #define KLOG_PAGES 4 56 56 #define KLOG_LENGTH (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t)) 57 57 #define KLOG_LATENCY 8 … … 165 165 sysinfo_set_item_val("klog.faddr", NULL, (sysarg_t) faddr); 166 166 sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES); 167 168 event_set_unmask_callback(EVENT_KLOG, klog_update);169 167 170 168 spinlock_lock(&klog_lock); … … 267 265 spinlock_lock(&klog_lock); 268 266 269 if ((klog_inited) && (klog_uspace > 0)) { 270 if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len, 271 klog_uspace) == EOK) 272 klog_uspace = 0; 267 if ((klog_inited) && (event_is_subscribed(EVENT_KLOG)) && (klog_uspace > 0)) { 268 event_notify_3(EVENT_KLOG, klog_start, klog_len, klog_uspace); 269 klog_uspace = 0; 273 270 } 274 271 -
kernel/generic/src/ipc/event.c
r0d8a304 r8d308b9 48 48 static event_t events[EVENT_END]; 49 49 50 /** Initialize kernel events. 51 * 52 */ 50 /** Initialize kernel events. */ 53 51 void event_init(void) 54 52 { 55 for (unsigned int i = 0; i < EVENT_END; i++) { 53 unsigned int i; 54 55 for (i = 0; i < EVENT_END; i++) { 56 56 spinlock_initialize(&events[i].lock, "event.lock"); 57 57 events[i].answerbox = NULL; 58 58 events[i].counter = 0; 59 59 events[i].imethod = 0; 60 events[i].masked = false;61 events[i].unmask_cb = NULL;62 60 } 63 61 } 64 62 65 /** Unsubscribe kernel events associated with an answerbox66 *67 * @param answerbox Answerbox to be unsubscribed.68 *69 */70 void event_cleanup_answerbox(answerbox_t *answerbox)71 {72 for (unsigned int i = 0; i < EVENT_END; i++) {73 spinlock_lock(&events[i].lock);74 75 if (events[i].answerbox == answerbox) {76 events[i].answerbox = NULL;77 events[i].counter = 0;78 events[i].imethod = 0;79 events[i].masked = false;80 }81 82 spinlock_unlock(&events[i].lock);83 }84 }85 86 /** Define a callback function for the event unmask event.87 *88 * @param evno Event type.89 * @param cb Callback function to be called when the event is unmasked.90 *91 */92 void event_set_unmask_callback(event_type_t evno, void (*cb)(void))93 {94 ASSERT(evno < EVENT_END);95 96 spinlock_lock(&events[evno].lock);97 events[evno].unmask_cb = cb;98 spinlock_unlock(&events[evno].lock);99 }100 101 /** Send kernel notification event102 *103 * @param evno Event type.104 * @param mask Mask further notifications after a successful105 * sending.106 * @param a1 First argument.107 * @param a2 Second argument.108 * @param a3 Third argument.109 * @param a4 Fourth argument.110 * @param a5 Fifth argument.111 *112 * @return EOK if notification was successfully sent.113 * @return ENOMEM if the notification IPC message failed to allocate.114 * @return EBUSY if the notifications of the given type are115 * currently masked.116 * @return ENOENT if the notifications of the given type are117 * currently not subscribed.118 *119 */120 int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2,121 sysarg_t a3, sysarg_t a4, sysarg_t a5)122 {123 ASSERT(evno < EVENT_END);124 125 spinlock_lock(&events[evno].lock);126 127 int ret;128 129 if (events[evno].answerbox != NULL) {130 if (!events[evno].masked) {131 call_t *call = ipc_call_alloc(FRAME_ATOMIC);132 133 if (call) {134 call->flags |= IPC_CALL_NOTIF;135 call->priv = ++events[evno].counter;136 137 IPC_SET_IMETHOD(call->data, events[evno].imethod);138 IPC_SET_ARG1(call->data, a1);139 IPC_SET_ARG2(call->data, a2);140 IPC_SET_ARG3(call->data, a3);141 IPC_SET_ARG4(call->data, a4);142 IPC_SET_ARG5(call->data, a5);143 144 irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);145 list_append(&call->link, &events[evno].answerbox->irq_notifs);146 irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);147 148 waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);149 150 if (mask)151 events[evno].masked = true;152 153 ret = EOK;154 } else155 ret = ENOMEM;156 } else157 ret = EBUSY;158 } else159 ret = ENOENT;160 161 spinlock_unlock(&events[evno].lock);162 163 return ret;164 }165 166 /** Subscribe event notifications167 *168 * @param evno Event type.169 * @param imethod IPC interface and method to be used for170 * the notifications.171 * @param answerbox Answerbox to send the notifications to.172 *173 * @return EOK if the subscription was successful.174 * @return EEXISTS if the notifications of the given type are175 * already subscribed.176 *177 */178 63 static int event_subscribe(event_type_t evno, sysarg_t imethod, 179 64 answerbox_t *answerbox) 180 65 { 181 ASSERT(evno < EVENT_END); 66 if (evno >= EVENT_END) 67 return ELIMIT; 182 68 183 69 spinlock_lock(&events[evno].lock); … … 189 75 events[evno].imethod = imethod; 190 76 events[evno].counter = 0; 191 events[evno].masked = false;192 77 res = EOK; 193 78 } else … … 199 84 } 200 85 201 /** Unmask event notifications202 *203 * @param evno Event type to unmask.204 *205 */206 static void event_unmask(event_type_t evno)207 {208 void (*cb)(void);209 ASSERT(evno < EVENT_END);210 211 spinlock_lock(&events[evno].lock);212 events[evno].masked = false;213 cb = events[evno].unmask_cb;214 spinlock_unlock(&events[evno].lock);215 216 /*217 * Check if there is an unmask callback function defined for this event.218 */219 if (cb)220 cb();221 }222 223 /** Event notification syscall wrapper224 *225 * @param evno Event type to subscribe.226 * @param imethod IPC interface and method to be used for227 * the notifications.228 *229 * @return EOK on success.230 * @return ELIMIT on unknown event type.231 * @return EEXISTS if the notifications of the given type are232 * already subscribed.233 *234 */235 86 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod) 236 87 { 237 if (evno >= EVENT_END)238 return ELIMIT;239 240 88 return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t) 241 89 imethod, &TASK->answerbox); 242 90 } 243 91 244 /** Event notification unmask syscall wrapper 245 * 246 * Note that currently no tests are performed whether the calling 247 * task is entitled to unmask the notifications. However, thanks 248 * to the fact that notification masking is only a performance 249 * optimization, this has probably no security implications. 250 * 251 * @param evno Event type to unmask. 252 * 253 * @return EOK on success. 254 * @return ELIMIT on unknown event type. 255 * 256 */ 257 sysarg_t sys_event_unmask(sysarg_t evno) 92 bool event_is_subscribed(event_type_t evno) 258 93 { 259 if (evno >= EVENT_END) 260 return ELIMIT; 94 bool res; 261 95 262 event_unmask((event_type_t) evno); 263 return EOK; 96 ASSERT(evno < EVENT_END); 97 98 spinlock_lock(&events[evno].lock); 99 res = events[evno].answerbox != NULL; 100 spinlock_unlock(&events[evno].lock); 101 102 return res; 103 } 104 105 106 void event_cleanup_answerbox(answerbox_t *answerbox) 107 { 108 unsigned int i; 109 110 for (i = 0; i < EVENT_END; i++) { 111 spinlock_lock(&events[i].lock); 112 if (events[i].answerbox == answerbox) { 113 events[i].answerbox = NULL; 114 events[i].counter = 0; 115 events[i].imethod = 0; 116 } 117 spinlock_unlock(&events[i].lock); 118 } 119 } 120 121 void event_notify(event_type_t evno, sysarg_t a1, sysarg_t a2, sysarg_t a3, 122 sysarg_t a4, sysarg_t a5) 123 { 124 ASSERT(evno < EVENT_END); 125 126 spinlock_lock(&events[evno].lock); 127 if (events[evno].answerbox != NULL) { 128 call_t *call = ipc_call_alloc(FRAME_ATOMIC); 129 if (call) { 130 call->flags |= IPC_CALL_NOTIF; 131 call->priv = ++events[evno].counter; 132 IPC_SET_IMETHOD(call->data, events[evno].imethod); 133 IPC_SET_ARG1(call->data, a1); 134 IPC_SET_ARG2(call->data, a2); 135 IPC_SET_ARG3(call->data, a3); 136 IPC_SET_ARG4(call->data, a4); 137 IPC_SET_ARG5(call->data, a5); 138 139 irq_spinlock_lock(&events[evno].answerbox->irq_lock, true); 140 list_append(&call->link, &events[evno].answerbox->irq_notifs); 141 irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true); 142 143 waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST); 144 } 145 } 146 spinlock_unlock(&events[evno].lock); 264 147 } 265 148 -
kernel/generic/src/proc/task.c
r0d8a304 r8d308b9 534 534 */ 535 535 if (notify) { 536 /* Notify the subscriber that a fault occurred. */ 537 if (event_notify_3(EVENT_FAULT, false, LOWER32(TASK->taskid), 538 UPPER32(TASK->taskid), (sysarg_t) THREAD) == EOK) { 536 if (event_is_subscribed(EVENT_FAULT)) { 537 /* Notify the subscriber that a fault occurred. */ 538 event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid), 539 UPPER32(TASK->taskid), (sysarg_t) THREAD); 540 539 541 #ifdef CONFIG_UDEBUG 540 542 /* Wait for a debugging session. */ -
kernel/generic/src/syscall/syscall.c
r0d8a304 r8d308b9 161 161 /* Event notification syscalls. */ 162 162 (syshandler_t) sys_event_subscribe, 163 (syshandler_t) sys_event_unmask,164 163 165 164 /* Capabilities related syscalls. */ -
uspace/app/klog/klog.c
r0d8a304 r8d308b9 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 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)); 235 124 236 fibril_add_ready(fid); 237 event_unmask(EVENT_KLOG); 125 async_set_interrupt_received(interrupt_received); 238 126 klog_update(); 239 240 task_retval(0);241 127 async_manager(); 242 128 -
uspace/lib/c/Makefile
r0d8a304 r8d308b9 108 108 generic/adt/measured_strings.c \ 109 109 generic/adt/char_map.c \ 110 generic/adt/prodcons.c \111 110 generic/time.c \ 112 111 generic/stdlib.c \ -
uspace/lib/c/generic/event.c
r0d8a304 r8d308b9 41 41 #include <kernel/ipc/event_types.h> 42 42 43 /** Subscribe event notifications.43 /** Subscribe for event notifications. 44 44 * 45 * @param evno Event type to subscribe.46 * @param imethod Use this interface andmethod for notifying me.45 * @param evno Event number. 46 * @param method Use this method for notifying me. 47 47 * 48 48 * @return Value returned by the kernel. 49 *50 49 */ 51 int event_subscribe(event_type_t e vno, sysarg_t imethod)50 int event_subscribe(event_type_t e, sysarg_t method) 52 51 { 53 return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno, 54 (sysarg_t) imethod); 55 } 56 57 /** Unmask event notifications. 58 * 59 * @param evno Event type to unmask. 60 * 61 * @return Value returned by the kernel. 62 * 63 */ 64 int event_unmask(event_type_t evno) 65 { 66 return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno); 52 return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method); 67 53 } 68 54 -
uspace/lib/c/include/event.h
r0d8a304 r8d308b9 39 39 40 40 extern int event_subscribe(event_type_t, sysarg_t); 41 extern int event_unmask(event_type_t);42 41 43 42 #endif
Note:
See TracChangeset
for help on using the changeset viewer.