Ignore:
File:
1 edited

Legend:

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

    r0496c17 rda1bafb  
    4848static event_t events[EVENT_END];
    4949
    50 /** Initialize kernel events.
    51  *
    52  */
     50/** Initialize kernel events. */
    5351void event_init(void)
    5452{
    55         for (unsigned int i = 0; i < EVENT_END; i++) {
     53        unsigned int i;
     54       
     55        for (i = 0; i < EVENT_END; i++) {
    5656                spinlock_initialize(&events[i].lock, "event.lock");
    5757                events[i].answerbox = NULL;
    5858                events[i].counter = 0;
    59                 events[i].imethod = 0;
    60                 events[i].masked = false;
    61                 events[i].unmask_cb = NULL;
     59                events[i].method = 0;
    6260        }
    6361}
    6462
    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 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 event
    102  *
    103  * @param evno Event type.
    104  * @param mask Mask further notifications after a successful
    105  *             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 are
    115  *         currently masked.
    116  * @return ENOENT if the notifications of the given type are
    117  *         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                         } else
    155                                 ret = ENOMEM;
    156                 } else
    157                         ret = EBUSY;
    158         } else
    159                 ret = ENOENT;
    160        
    161         spinlock_unlock(&events[evno].lock);
    162        
    163         return ret;
    164 }
    165 
    166 /** Subscribe event notifications
    167  *
    168  * @param evno      Event type.
    169  * @param imethod   IPC interface and method to be used for
    170  *                  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 are
    175  *         already subscribed.
    176  *
    177  */
    178 static int event_subscribe(event_type_t evno, sysarg_t imethod,
     63static int event_subscribe(event_type_t evno, unative_t method,
    17964    answerbox_t *answerbox)
    18065{
    181         ASSERT(evno < EVENT_END);
     66        if (evno >= EVENT_END)
     67                return ELIMIT;
    18268       
    18369        spinlock_lock(&events[evno].lock);
     
    18773        if (events[evno].answerbox == NULL) {
    18874                events[evno].answerbox = answerbox;
    189                 events[evno].imethod = imethod;
     75                events[evno].method = method;
    19076                events[evno].counter = 0;
    191                 events[evno].masked = false;
    19277                res = EOK;
    19378        } else
     
    19984}
    20085
    201 /** Unmask event notifications
    202  *
    203  * @param evno Event type to unmask.
    204  *
    205  */
    206 static void event_unmask(event_type_t evno)
     86unative_t sys_event_subscribe(unative_t evno, unative_t method)
    20787{
    208         void (*cb)(void);
     88        return (unative_t) event_subscribe((event_type_t) evno, (unative_t)
     89            method, &TASK->answerbox);
     90}
     91
     92bool event_is_subscribed(event_type_t evno)
     93{
     94        bool res;
     95       
    20996        ASSERT(evno < EVENT_END);
    21097       
    21198        spinlock_lock(&events[evno].lock);
    212         events[evno].masked = false;
    213         cb = events[evno].unmask_cb;
     99        res = events[evno].answerbox != NULL;
    214100        spinlock_unlock(&events[evno].lock);
    215101       
    216         /*
    217          * Check if there is an unmask callback function defined for this event.
    218          */
    219         if (cb)
    220             cb();
     102        return res;
    221103}
    222104
    223 /** Event notification syscall wrapper
    224  *
    225  * @param evno    Event type to subscribe.
    226  * @param imethod IPC interface and method to be used for
    227  *                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 are
    232  *         already subscribed.
    233  *
    234  */
    235 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
     105
     106void event_cleanup_answerbox(answerbox_t *answerbox)
    236107{
    237         if (evno >= EVENT_END)
    238                 return ELIMIT;
     108        unsigned int i;
    239109       
    240         return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    241             imethod, &TASK->answerbox);
     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].method = 0;
     116                }
     117                spinlock_unlock(&events[i].lock);
     118        }
    242119}
    243120
    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)
     121void event_notify(event_type_t evno, unative_t a1, unative_t a2, unative_t a3,
     122    unative_t a4, unative_t a5)
    258123{
    259         if (evno >= EVENT_END)
    260                 return ELIMIT;
     124        ASSERT(evno < EVENT_END);
    261125       
    262         event_unmask((event_type_t) evno);
    263         return EOK;
     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_METHOD(call->data, events[evno].method);
     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);
    264147}
    265148
Note: See TracChangeset for help on using the changeset viewer.