Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f9061b4 in mainline


Ignore:
Timestamp:
2011-05-16T13:38:04Z (11 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
4e1a2f5
Parents:
e0f52bf
Message:

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

Files:
11 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/event.h

    re0f52bf rf9061b4  
    5151        /** Counter. */
    5252        size_t counter;
     53        /** Masked flag. */
     54        bool masked;
    5355} event_t;
    5456
    5557extern void event_init(void);
    56 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
    57 extern bool event_is_subscribed(event_type_t);
    5858extern void event_cleanup_answerbox(answerbox_t *);
    5959
    60 #define event_notify_0(e) \
    61         event_notify((e), 0, 0, 0, 0, 0)
    62 #define event_notify_1(e, a1) \
    63         event_notify((e), (a1), 0, 0, 0, 0)
    64 #define event_notify_2(e, a1, a2) \
    65         event_notify((e), (a1), (a2), 0, 0, 0)
    66 #define event_notify_3(e, a1, a2, a3) \
    67         event_notify((e), (a1), (a2), (a3), 0, 0)
    68 #define event_notify_4(e, a1, a2, a3, a4) \
    69         event_notify((e), (a1), (a2), (a3), (a4), 0)
    70 #define event_notify_5(e, a1, a2, a3, a4, a5) \
    71         event_notify((e), (a1), (a2), (a3), (a4), (a5))
     60#define event_notify_0(e, m) \
     61        event_notify((e), (m), 0, 0, 0, 0, 0)
     62#define event_notify_1(e, m, a1) \
     63        event_notify((e), (m), (a1), 0, 0, 0, 0)
     64#define event_notify_2(e, m, a1, a2) \
     65        event_notify((e), (m), (a1), (a2), 0, 0, 0)
     66#define event_notify_3(e, m, a1, a2, a3) \
     67        event_notify((e), (m), (a1), (a2), (a3), 0, 0)
     68#define event_notify_4(e, m, a1, a2, a3, a4) \
     69        event_notify((e), (m), (a1), (a2), (a3), (a4), 0)
     70#define event_notify_5(e, m, a1, a2, a3, a4, a5) \
     71        event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
    7272
    73 extern void event_notify(event_type_t, sysarg_t, sysarg_t, sysarg_t,
     73extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
    7474    sysarg_t, sysarg_t);
     75
     76extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
     77extern sysarg_t sys_event_unmask(sysarg_t);
    7578
    7679#endif
  • kernel/generic/include/ipc/event_types.h

    re0f52bf rf9061b4  
    3939        /** New data available in kernel log */
    4040        EVENT_KLOG = 0,
    41         /** Returning from kernel console to userspace */
     41        /** Returning from kernel console to uspace */
    4242        EVENT_KCONSOLE,
    4343        /** A task/thread has faulted and will be terminated */
  • kernel/generic/include/syscall/syscall.h

    re0f52bf rf9061b4  
    7575       
    7676        SYS_EVENT_SUBSCRIBE,
     77        SYS_EVENT_UNMASK,
    7778       
    7879        SYS_CAP_GRANT,
  • kernel/generic/src/console/cmd.c

    re0f52bf rf9061b4  
    11071107        release_console();
    11081108       
    1109         event_notify_0(EVENT_KCONSOLE);
     1109        event_notify_0(EVENT_KCONSOLE, false);
    11101110        indev_pop_character(stdin);
    11111111       
  • kernel/generic/src/console/console.c

    re0f52bf rf9061b4  
    265265        spinlock_lock(&klog_lock);
    266266       
    267         if ((klog_inited) && (event_is_subscribed(EVENT_KLOG)) && (klog_uspace > 0)) {
    268                 event_notify_3(EVENT_KLOG, klog_start, klog_len, klog_uspace);
    269                 klog_uspace = 0;
     267        if ((klog_inited) && (klog_uspace > 0)) {
     268                if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
     269                    klog_uspace) == EOK)
     270                        klog_uspace = 0;
    270271        }
    271272       
  • 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
  • kernel/generic/src/proc/task.c

    re0f52bf rf9061b4  
    534534        */
    535535        if (notify) {
    536                 if (event_is_subscribed(EVENT_FAULT)) {
    537                         /* Notify the subscriber that a fault occurred. */
    538                         event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
    539                             UPPER32(TASK->taskid), (sysarg_t) THREAD);
    540                
     536                /* Notify the subscriber that a fault occurred. */
     537                if (event_notify_3(EVENT_FAULT, false, LOWER32(TASK->taskid),
     538                    UPPER32(TASK->taskid), (sysarg_t) THREAD) == EOK) {
    541539#ifdef CONFIG_UDEBUG
    542540                        /* Wait for a debugging session. */
  • kernel/generic/src/syscall/syscall.c

    re0f52bf rf9061b4  
    161161        /* Event notification syscalls. */
    162162        (syshandler_t) sys_event_subscribe,
     163        (syshandler_t) sys_event_unmask,
    163164       
    164165        /* Capabilities related syscalls. */
  • uspace/app/klog/klog.c

    re0f52bf rf9061b4  
    7474                fsync(fileno(log));
    7575        }
     76       
     77        event_unmask(EVENT_KLOG);
    7678}
    7779
     
    111113        }
    112114       
    113         rc = event_subscribe(EVENT_KLOG, 0);
    114         if (rc != EOK) {
    115                 fprintf(stderr, "%s: Unable to register klog notifications\n",
    116                     NAME);
    117                 return rc;
    118         }
    119        
    120115        log = fopen(LOG_FNAME, "a");
    121116        if (log == NULL)
     
    124119       
    125120        async_set_interrupt_received(interrupt_received);
     121        rc = event_subscribe(EVENT_KLOG, 0);
     122        if (rc != EOK) {
     123                fclose(log);
     124                fprintf(stderr, "%s: Unable to register klog notifications\n",
     125                    NAME);
     126                return rc;
     127        }
     128       
     129        event_unmask(EVENT_KLOG);
     130       
    126131        klog_update();
    127132        async_manager();
  • uspace/lib/c/generic/event.c

    re0f52bf rf9061b4  
    4141#include <kernel/ipc/event_types.h>
    4242
    43 /** Subscribe for event notifications.
     43/** Subscribe event notifications.
    4444 *
    45  * @param evno   Event number.
    46  * @param method Use this method for notifying me.
     45 * @param evno    Event type to subscribe.
     46 * @param imethod Use this interface and method for notifying me.
    4747 *
    4848 * @return Value returned by the kernel.
     49 *
    4950 */
    50 int event_subscribe(event_type_t e, sysarg_t method)
     51int event_subscribe(event_type_t evno, sysarg_t imethod)
    5152{
    52         return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method);
     53        return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
     54            (sysarg_t) imethod);
     55}
     56
     57/** Unmask event notifications.
     58 *
     59 * @param evno Event type to unmask.
     60 *
     61 * @return Value returned by the kernel.
     62 *
     63 */
     64int event_unmask(event_type_t evno)
     65{
     66        return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
    5367}
    5468
  • uspace/lib/c/include/event.h

    re0f52bf rf9061b4  
    3939
    4040extern int event_subscribe(event_type_t, sysarg_t);
     41extern int event_unmask(event_type_t);
    4142
    4243#endif
Note: See TracChangeset for help on using the changeset viewer.