Ignore:
File:
1 edited

Legend:

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

    r97d42d5 r228e490  
    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;
    5959                events[i].imethod = 0;
    60                 events[i].masked = false;
    61                 events[i].unmask_callback = NULL;
    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 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  */
    17963static int event_subscribe(event_type_t evno, sysarg_t imethod,
    18064    answerbox_t *answerbox)
    18165{
    182         ASSERT(evno < EVENT_END);
     66        if (evno >= EVENT_END)
     67                return ELIMIT;
    18368       
    18469        spinlock_lock(&events[evno].lock);
     
    19075                events[evno].imethod = imethod;
    19176                events[evno].counter = 0;
    192                 events[evno].masked = false;
    19377                res = EOK;
    19478        } else
     
    20084}
    20185
    202 /** Unmask event notifications
    203  *
    204  * @param evno Event type to unmask.
    205  *
    206  */
    207 static void event_unmask(event_type_t evno)
     86sysarg_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
     92bool 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
     106void 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
     121void event_notify(event_type_t evno, sysarg_t a1, sysarg_t a2, sysarg_t a3,
     122    sysarg_t a4, sysarg_t a5)
    208123{
    209124        ASSERT(evno < EVENT_END);
    210125       
    211126        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        }
    214146        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  */
    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 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;
    265147}
    266148
Note: See TracChangeset for help on using the changeset viewer.