Changes in kernel/generic/src/ipc/event.c [0496c17:da1bafb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
r0496c17 rda1bafb 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 events[i].imethod = 0; 60 events[i].masked = false; 61 events[i].unmask_cb = NULL; 59 events[i].method = 0; 62 60 } 63 61 } 64 62 65 /** Unsubscribe kernel events associated with an answerbox 66 * 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 event 102 * 103 * @param evno Event type. 104 * @param mask Mask further notifications after a successful 105 * 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 are 115 * currently masked. 116 * @return ENOENT if the notifications of the given type are 117 * 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 } else 155 ret = ENOMEM; 156 } else 157 ret = EBUSY; 158 } else 159 ret = ENOENT; 160 161 spinlock_unlock(&events[evno].lock); 162 163 return ret; 164 } 165 166 /** Subscribe event notifications 167 * 168 * @param evno Event type. 169 * @param imethod IPC interface and method to be used for 170 * 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 are 175 * already subscribed. 176 * 177 */ 178 static int event_subscribe(event_type_t evno, sysarg_t imethod, 63 static int event_subscribe(event_type_t evno, unative_t method, 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); … … 187 73 if (events[evno].answerbox == NULL) { 188 74 events[evno].answerbox = answerbox; 189 events[evno]. imethod = imethod;75 events[evno].method = method; 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 notifications 202 * 203 * @param evno Event type to unmask. 204 * 205 */ 206 static void event_unmask(event_type_t evno) 86 unative_t sys_event_subscribe(unative_t evno, unative_t method) 207 87 { 208 void (*cb)(void); 88 return (unative_t) event_subscribe((event_type_t) evno, (unative_t) 89 method, &TASK->answerbox); 90 } 91 92 bool event_is_subscribed(event_type_t evno) 93 { 94 bool res; 95 209 96 ASSERT(evno < EVENT_END); 210 97 211 98 spinlock_lock(&events[evno].lock); 212 events[evno].masked = false; 213 cb = events[evno].unmask_cb; 99 res = events[evno].answerbox != NULL; 214 100 spinlock_unlock(&events[evno].lock); 215 101 216 /* 217 * Check if there is an unmask callback function defined for this event. 218 */ 219 if (cb) 220 cb(); 102 return res; 221 103 } 222 104 223 /** Event notification syscall wrapper 224 * 225 * @param evno Event type to subscribe. 226 * @param imethod IPC interface and method to be used for 227 * 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 are 232 * already subscribed. 233 * 234 */ 235 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod) 105 106 void event_cleanup_answerbox(answerbox_t *answerbox) 236 107 { 237 if (evno >= EVENT_END) 238 return ELIMIT; 108 unsigned int i; 239 109 240 return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t) 241 imethod, &TASK->answerbox); 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].method = 0; 116 } 117 spinlock_unlock(&events[i].lock); 118 } 242 119 } 243 120 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) 121 void event_notify(event_type_t evno, unative_t a1, unative_t a2, unative_t a3, 122 unative_t a4, unative_t a5) 258 123 { 259 if (evno >= EVENT_END) 260 return ELIMIT; 124 ASSERT(evno < EVENT_END); 261 125 262 event_unmask((event_type_t) evno); 263 return EOK; 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_METHOD(call->data, events[evno].method); 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
Note:
See TracChangeset
for help on using the changeset viewer.