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


Ignore:
Timestamp:
2011-05-17T07:58:39Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7d521e24
Parents:
e913cc9 (diff), 3375bd4 (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.
Message:

Merge development/ changes

File:
1 edited

Legend:

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

    re913cc9 r04c418d  
    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;
     61                events[i].unmask_cb = NULL;
    6062        }
    6163}
    6264
     65/** Unsubscribe kernel events associated with an answerbox
     66 *
     67 * @param answerbox Answerbox to be unsubscribed.
     68 *
     69 */
     70void 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 */
     92void 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 */
     120int 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 */
    63178static int event_subscribe(event_type_t evno, sysarg_t imethod,
    64179    answerbox_t *answerbox)
    65180{
    66         if (evno >= EVENT_END)
    67                 return ELIMIT;
     181        ASSERT(evno < EVENT_END);
    68182       
    69183        spinlock_lock(&events[evno].lock);
     
    75189                events[evno].imethod = imethod;
    76190                events[evno].counter = 0;
     191                events[evno].masked = false;
    77192                res = EOK;
    78193        } else
     
    84199}
    85200
     201/** Unmask event notifications
     202 *
     203 * @param evno Event type to unmask.
     204 *
     205 */
     206static void event_unmask(event_type_t evno)
     207{
     208        void (*cb)(void);
     209        ASSERT(evno < EVENT_END);
     210       
     211        spinlock_lock(&events[evno].lock);
     212        events[evno].masked = false;
     213        cb = events[evno].unmask_cb;
     214        spinlock_unlock(&events[evno].lock);
     215       
     216        /*
     217         * Check if there is an unmask callback function defined for this event.
     218         */
     219        if (cb)
     220            cb();
     221}
     222
     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 */
    86235sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    87236{
     237        if (evno >= EVENT_END)
     238                return ELIMIT;
     239       
    88240        return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    89241            imethod, &TASK->answerbox);
    90242}
    91243
    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);
     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 */
     257sysarg_t sys_event_unmask(sysarg_t evno)
     258{
     259        if (evno >= EVENT_END)
     260                return ELIMIT;
     261       
     262        event_unmask((event_type_t) evno);
     263        return EOK;
    147264}
    148265
Note: See TracChangeset for help on using the changeset viewer.