Changeset 544a2e4 in mainline for kernel/generic/src/ipc/event.c
- Timestamp:
- 2011-05-30T21:37:43Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7b712b60
- Parents:
- 18ba2e4f (diff), 0743493a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
r18ba2e4f r544a2e4 48 48 static event_t events[EVENT_END]; 49 49 50 /** Initialize kernel events. */ 50 /** Initialize kernel events. 51 * 52 */ 51 53 void event_init(void) 52 54 { 53 unsigned int i; 54 55 for (i = 0; i < EVENT_END; i++) { 55 for (unsigned int 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; 60 62 } 61 63 } 62 64 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 callback Callback function to be called when 90 * 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 event 103 * 104 * @param evno Event type. 105 * @param mask Mask further notifications after a successful 106 * 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 are 116 * currently masked. 117 * @return ENOENT if the notifications of the given type are 118 * 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 } else 156 ret = ENOMEM; 157 } else 158 ret = EBUSY; 159 } else 160 ret = ENOENT; 161 162 spinlock_unlock(&events[evno].lock); 163 164 return ret; 165 } 166 167 /** Subscribe event notifications 168 * 169 * @param evno Event type. 170 * @param imethod IPC interface and method to be used for 171 * 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 are 176 * already subscribed. 177 * 178 */ 63 179 static int event_subscribe(event_type_t evno, sysarg_t imethod, 64 180 answerbox_t *answerbox) 65 181 { 66 if (evno >= EVENT_END) 67 return ELIMIT; 182 ASSERT(evno < EVENT_END); 68 183 69 184 spinlock_lock(&events[evno].lock); … … 75 190 events[evno].imethod = imethod; 76 191 events[evno].counter = 0; 192 events[evno].masked = false; 77 193 res = EOK; 78 194 } else … … 84 200 } 85 201 202 /** Unmask event notifications 203 * 204 * @param evno Event type to unmask. 205 * 206 */ 207 static void event_unmask(event_type_t evno) 208 { 209 ASSERT(evno < EVENT_END); 210 211 spinlock_lock(&events[evno].lock); 212 events[evno].masked = false; 213 event_callback_t callback = events[evno].unmask_callback; 214 spinlock_unlock(&events[evno].lock); 215 216 /* 217 * Check if there is an unmask callback 218 * function defined for this event. 219 */ 220 if (callback != NULL) 221 callback(); 222 } 223 224 /** Event notification syscall wrapper 225 * 226 * @param evno Event type to subscribe. 227 * @param imethod IPC interface and method to be used for 228 * 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 are 233 * already subscribed. 234 * 235 */ 86 236 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod) 87 237 { 238 if (evno >= EVENT_END) 239 return ELIMIT; 240 88 241 return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t) 89 242 imethod, &TASK->answerbox); 90 243 } 91 244 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) 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); 245 /** Event notification unmask syscall wrapper 246 * 247 * Note that currently no tests are performed whether the calling 248 * task is entitled to unmask the notifications. However, thanks 249 * to the fact that notification masking is only a performance 250 * 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; 147 265 } 148 266
Note:
See TracChangeset
for help on using the changeset viewer.