Changes in kernel/generic/src/ipc/event.c [97d42d5:228e490] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
r97d42d5 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_callback = 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 callback Callback function to be called when90 * the event is unmasked.91 *92 */93 void event_set_unmask_callback(event_type_t evno, event_callback_t callback)94 {95 ASSERT(evno < EVENT_END);96 97 spinlock_lock(&events[evno].lock);98 events[evno].unmask_callback = callback;99 spinlock_unlock(&events[evno].lock);100 }101 102 /** Send kernel notification event103 *104 * @param evno Event type.105 * @param mask Mask further notifications after a successful106 * sending.107 * @param a1 First argument.108 * @param a2 Second argument.109 * @param a3 Third argument.110 * @param a4 Fourth argument.111 * @param a5 Fifth argument.112 *113 * @return EOK if notification was successfully sent.114 * @return ENOMEM if the notification IPC message failed to allocate.115 * @return EBUSY if the notifications of the given type are116 * currently masked.117 * @return ENOENT if the notifications of the given type are118 * currently not subscribed.119 *120 */121 int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2,122 sysarg_t a3, sysarg_t a4, sysarg_t a5)123 {124 ASSERT(evno < EVENT_END);125 126 spinlock_lock(&events[evno].lock);127 128 int ret;129 130 if (events[evno].answerbox != NULL) {131 if (!events[evno].masked) {132 call_t *call = ipc_call_alloc(FRAME_ATOMIC);133 134 if (call) {135 call->flags |= IPC_CALL_NOTIF;136 call->priv = ++events[evno].counter;137 138 IPC_SET_IMETHOD(call->data, events[evno].imethod);139 IPC_SET_ARG1(call->data, a1);140 IPC_SET_ARG2(call->data, a2);141 IPC_SET_ARG3(call->data, a3);142 IPC_SET_ARG4(call->data, a4);143 IPC_SET_ARG5(call->data, a5);144 145 irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);146 list_append(&call->link, &events[evno].answerbox->irq_notifs);147 irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);148 149 waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);150 151 if (mask)152 events[evno].masked = true;153 154 ret = EOK;155 } else156 ret = ENOMEM;157 } else158 ret = EBUSY;159 } else160 ret = ENOENT;161 162 spinlock_unlock(&events[evno].lock);163 164 return ret;165 }166 167 /** Subscribe event notifications168 *169 * @param evno Event type.170 * @param imethod IPC interface and method to be used for171 * the notifications.172 * @param answerbox Answerbox to send the notifications to.173 *174 * @return EOK if the subscription was successful.175 * @return EEXISTS if the notifications of the given type are176 * already subscribed.177 *178 */179 63 static int event_subscribe(event_type_t evno, sysarg_t imethod, 180 64 answerbox_t *answerbox) 181 65 { 182 ASSERT(evno < EVENT_END); 66 if (evno >= EVENT_END) 67 return ELIMIT; 183 68 184 69 spinlock_lock(&events[evno].lock); … … 190 75 events[evno].imethod = imethod; 191 76 events[evno].counter = 0; 192 events[evno].masked = false;193 77 res = EOK; 194 78 } else … … 200 84 } 201 85 202 /** Unmask event notifications 203 * 204 * @param evno Event type to unmask. 205 * 206 */ 207 static void event_unmask(event_type_t evno) 86 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod) 87 { 88 return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t) 89 imethod, &TASK->answerbox); 90 } 91 92 bool event_is_subscribed(event_type_t evno) 93 { 94 bool res; 95 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) 208 123 { 209 124 ASSERT(evno < EVENT_END); 210 125 211 126 spinlock_lock(&events[evno].lock); 212 events[evno].masked = false; 213 event_callback_t callback = events[evno].unmask_callback; 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 } 214 146 spinlock_unlock(&events[evno].lock); 215 216 /*217 * Check if there is an unmask callback218 * function defined for this event.219 */220 if (callback != NULL)221 callback();222 }223 224 /** Event notification syscall wrapper225 *226 * @param evno Event type to subscribe.227 * @param imethod IPC interface and method to be used for228 * the notifications.229 *230 * @return EOK on success.231 * @return ELIMIT on unknown event type.232 * @return EEXISTS if the notifications of the given type are233 * already subscribed.234 *235 */236 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)237 {238 if (evno >= EVENT_END)239 return ELIMIT;240 241 return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)242 imethod, &TASK->answerbox);243 }244 245 /** Event notification unmask syscall wrapper246 *247 * Note that currently no tests are performed whether the calling248 * task is entitled to unmask the notifications. However, thanks249 * to the fact that notification masking is only a performance250 * optimization, this has probably no security implications.251 *252 * @param evno Event type to unmask.253 *254 * @return EOK on success.255 * @return ELIMIT on unknown event type.256 *257 */258 sysarg_t sys_event_unmask(sysarg_t evno)259 {260 if (evno >= EVENT_END)261 return ELIMIT;262 263 event_unmask((event_type_t) evno);264 return EOK;265 147 } 266 148
Note:
See TracChangeset
for help on using the changeset viewer.