Changeset f9061b4 in mainline for kernel/generic/src/ipc/event.c


Ignore:
Timestamp:
2011-05-16T13:38:04Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4e1a2f5
Parents:
e0f52bf
Message:

add kernel event notification masking (currently used only for EVENT_KLOG)
improve kernel event notification API

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/event.c

    re0f52bf rf9061b4  
    4848static event_t events[EVENT_END];
    4949
    50 /** Initialize kernel events. */
     50/** Initialize kernel events.
     51 *
     52 */
    5153void event_init(void)
    5254{
    53         unsigned int i;
    54        
    55         for (i = 0; i < EVENT_END; i++) {
     55        for (unsigned int i = 0; i < EVENT_END; i++) {
    5656                spinlock_initialize(&events[i].lock, "event.lock");
    5757                events[i].answerbox = NULL;
    5858                events[i].counter = 0;
    5959                events[i].imethod = 0;
     60                events[i].masked = false;
    6061        }
    6162}
    6263
     64/** Unsubscribe kernel events associated with an answerbox
     65 *
     66 * @param answerbox Answerbox to be unsubscribed.
     67 *
     68 */
     69void 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 */
     104int 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 */
    63162static int event_subscribe(event_type_t evno, sysarg_t imethod,
    64163    answerbox_t *answerbox)
    65164{
    66         if (evno >= EVENT_END)
    67                 return ELIMIT;
     165        ASSERT(evno < EVENT_END);
    68166       
    69167        spinlock_lock(&events[evno].lock);
     
    75173                events[evno].imethod = imethod;
    76174                events[evno].counter = 0;
     175                events[evno].masked = false;
    77176                res = EOK;
    78177        } else
     
    84183}
    85184
     185/** Unmask event notifications
     186 *
     187 * @param evno Event type to unmask.
     188 *
     189 */
     190static 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 */
    86211sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    87212{
     213        if (evno >= EVENT_END)
     214                return ELIMIT;
     215       
    88216        return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    89217            imethod, &TASK->answerbox);
    90218}
    91219
    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 */
     233sysarg_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;
    147240}
    148241
Note: See TracChangeset for help on using the changeset viewer.