Changeset f9061b4 in mainline for kernel/generic/src/ipc/event.c
- Timestamp:
- 2011-05-16T13:38:04Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4e1a2f5
- Parents:
- e0f52bf
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
re0f52bf rf9061b4 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; 60 61 } 61 62 } 62 63 64 /** Unsubscribe kernel events associated with an answerbox 65 * 66 * @param answerbox Answerbox to be unsubscribed. 67 * 68 */ 69 void event_cleanup_answerbox(answerbox_t *answerbox) 70 { 71 for (unsigned int i = 0; i < EVENT_END; i++) { 72 spinlock_lock(&events[i].lock); 73 74 if (events[i].answerbox == answerbox) { 75 events[i].answerbox = NULL; 76 events[i].counter = 0; 77 events[i].imethod = 0; 78 events[i].masked = false; 79 } 80 81 spinlock_unlock(&events[i].lock); 82 } 83 } 84 85 /** Send kernel notification event 86 * 87 * @param evno Event type. 88 * @param mask Mask further notifications after a successful 89 * sending. 90 * @param a1 First argument. 91 * @param a2 Second argument. 92 * @param a3 Third argument. 93 * @param a4 Fourth argument. 94 * @param a5 Fifth argument. 95 * 96 * @return EOK if notification was successfully sent. 97 * @return ENOMEM if the notification IPC message failed to allocate. 98 * @return EBUSY if the notifications of the given type are 99 * currently masked. 100 * @return ENOENT if the notifications of the given type are 101 * currently not subscribed. 102 * 103 */ 104 int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2, 105 sysarg_t a3, sysarg_t a4, sysarg_t a5) 106 { 107 ASSERT(evno < EVENT_END); 108 109 spinlock_lock(&events[evno].lock); 110 111 int ret; 112 113 if (events[evno].answerbox != NULL) { 114 if (!events[evno].masked) { 115 call_t *call = ipc_call_alloc(FRAME_ATOMIC); 116 117 if (call) { 118 call->flags |= IPC_CALL_NOTIF; 119 call->priv = ++events[evno].counter; 120 121 IPC_SET_IMETHOD(call->data, events[evno].imethod); 122 IPC_SET_ARG1(call->data, a1); 123 IPC_SET_ARG2(call->data, a2); 124 IPC_SET_ARG3(call->data, a3); 125 IPC_SET_ARG4(call->data, a4); 126 IPC_SET_ARG5(call->data, a5); 127 128 irq_spinlock_lock(&events[evno].answerbox->irq_lock, true); 129 list_append(&call->link, &events[evno].answerbox->irq_notifs); 130 irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true); 131 132 waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST); 133 134 if (mask) 135 events[evno].masked = true; 136 137 ret = EOK; 138 } else 139 ret = ENOMEM; 140 } else 141 ret = EBUSY; 142 } else 143 ret = ENOENT; 144 145 spinlock_unlock(&events[evno].lock); 146 147 return ret; 148 } 149 150 /** Subscribe event notifications 151 * 152 * @param evno Event type. 153 * @param imethod IPC interface and method to be used for 154 * the notifications. 155 * @param answerbox Answerbox to send the notifications to. 156 * 157 * @return EOK if the subscription was successful. 158 * @return EEXISTS if the notifications of the given type are 159 * already subscribed. 160 * 161 */ 63 162 static int event_subscribe(event_type_t evno, sysarg_t imethod, 64 163 answerbox_t *answerbox) 65 164 { 66 if (evno >= EVENT_END) 67 return ELIMIT; 165 ASSERT(evno < EVENT_END); 68 166 69 167 spinlock_lock(&events[evno].lock); … … 75 173 events[evno].imethod = imethod; 76 174 events[evno].counter = 0; 175 events[evno].masked = false; 77 176 res = EOK; 78 177 } else … … 84 183 } 85 184 185 /** Unmask event notifications 186 * 187 * @param evno Event type to unmask. 188 * 189 */ 190 static void event_unmask(event_type_t evno) 191 { 192 ASSERT(evno < EVENT_END); 193 194 spinlock_lock(&events[evno].lock); 195 events[evno].masked = false; 196 spinlock_unlock(&events[evno].lock); 197 } 198 199 /** Event notification syscall wrapper 200 * 201 * @param evno Event type to subscribe. 202 * @param imethod IPC interface and method to be used for 203 * the notifications. 204 * 205 * @return EOK on success. 206 * @return ELIMIT on unknown event type. 207 * @return EEXISTS if the notifications of the given type are 208 * already subscribed. 209 * 210 */ 86 211 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod) 87 212 { 213 if (evno >= EVENT_END) 214 return ELIMIT; 215 88 216 return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t) 89 217 imethod, &TASK->answerbox); 90 218 } 91 219 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); 220 /** Event notification unmask syscall wrapper 221 * 222 * Note that currently no tests are performed whether the calling 223 * task is entitled to unmask the notifications. However, thanks 224 * to the fact that notification masking is only a performance 225 * optimization, this has probably no security implications. 226 * 227 * @param evno Event type to unmask. 228 * 229 * @return EOK on success. 230 * @return ELIMIT on unknown event type. 231 * 232 */ 233 sysarg_t sys_event_unmask(sysarg_t evno) 234 { 235 if (evno >= EVENT_END) 236 return ELIMIT; 237 238 event_unmask((event_type_t) evno); 239 return EOK; 147 240 } 148 241
Note:
See TracChangeset
for help on using the changeset viewer.