Changes in kernel/generic/src/ipc/event.c [0496c17:228e490] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
r0496c17 r228e490 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
Note:
See TracChangeset
for help on using the changeset viewer.