Changeset 5d0500c in mainline


Ignore:
Timestamp:
2011-08-16T21:51:22Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fdd4898
Parents:
b585dfa9
Message:

Introduce per-task kernel event notifications.

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • abi/include/ipc/event.h

    rb585dfa9 r5d0500c  
    4646} event_type_t;
    4747
     48/** Per-task events. */
     49typedef enum event_task_type {
     50        EVENT_TASK_STATE_CHANGE = EVENT_END,
     51        EVENT_TASK_END
     52} event_task_type_t;
     53
    4854#endif
    4955
  • kernel/generic/include/console/console.h

    rb585dfa9 r5d0500c  
    6363
    6464extern void klog_init(void);
    65 extern void klog_update(void);
     65extern void klog_update(void *);
    6666
    6767extern wchar_t getc(indev_t *indev);
  • kernel/generic/include/ipc/event.h

    rb585dfa9 r5d0500c  
    4141#include <ipc/ipc.h>
    4242
    43 typedef void (*event_callback_t)(void);
     43typedef struct task task_t;
     44
     45typedef void (*event_callback_t)(void *);
    4446
    4547/** Event notification structure. */
     
    6163
    6264extern void event_init(void);
     65extern void event_task_init(task_t *);
    6366extern void event_cleanup_answerbox(answerbox_t *);
    6467extern void event_set_unmask_callback(event_type_t, event_callback_t);
     68extern void event_task_set_unmask_callback(task_t *, event_task_type_t,
     69    event_callback_t);
    6570
    6671#define event_notify_0(e, m) \
     
    7782        event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
    7883
     84#define event_task_notify_0(t, e, m) \
     85        event_task_notify((t), (e), (m), 0, 0, 0, 0, 0)
     86#define event_task_notify_1(t, e, m, a1) \
     87        event_task_notify((t), (e), (m), (a1), 0, 0, 0, 0)
     88#define event_task_notify_2(t, e, m, a1, a2) \
     89        event_task_notify((t), (e), (m), (a1), (a2), 0, 0, 0)
     90#define event_task_notify_3(t, e, m, a1, a2, a3) \
     91        event_task_notify((t), (e), (m), (a1), (a2), (a3), 0, 0)
     92#define event_task_notify_4(t, e, m, a1, a2, a3, a4) \
     93        event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), 0)
     94#define event_task_notify_5(t, e, m, a1, a2, a3, a4, a5) \
     95        event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), (a5))
     96
    7997extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
    8098    sysarg_t, sysarg_t);
     99extern int event_task_notify(task_t *, event_task_type_t, bool, sysarg_t, sysarg_t,
     100    sysarg_t, sysarg_t, sysarg_t);
    81101
    82102extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
  • kernel/generic/include/proc/task.h

    rb585dfa9 r5d0500c  
    3838#include <cpu.h>
    3939#include <ipc/ipc.h>
     40#include <ipc/event.h>
     41#include <ipc/kbox.h>
    4042#include <synch/spinlock.h>
    4143#include <synch/mutex.h>
     
    5355#include <proc/scheduler.h>
    5456#include <udebug/udebug.h>
    55 #include <ipc/kbox.h>
    5657#include <mm/as.h>
    5758#include <abi/sysinfo.h>
     
    9394        phone_t phones[IPC_MAX_PHONES];
    9495        stats_ipc_t ipc_info;   /**< IPC statistics */
    95         /** List of synchronous answerboxes. */
    96         list_t sync_boxes;
     96        list_t sync_boxes;      /**< List of synchronous answerboxes. */
     97        event_t events[EVENT_TASK_END - EVENT_END];
    9798       
    9899#ifdef CONFIG_UDEBUG
  • kernel/generic/src/console/console.c

    rb585dfa9 r5d0500c  
    248248}
    249249
    250 void klog_update(void)
     250void klog_update(void *e)
    251251{
    252252        if (!atomic_get(&klog_inited))
     
    327327        /* Force notification on newline */
    328328        if (ch == '\n')
    329                 klog_update();
     329                klog_update(NULL);
    330330}
    331331
     
    358358                free(data);
    359359        } else
    360                 klog_update();
     360                klog_update(NULL);
    361361       
    362362        return size;
  • kernel/generic/src/ipc/event.c

    rb585dfa9 r5d0500c  
    4040#include <synch/spinlock.h>
    4141#include <console/console.h>
     42#include <proc/task.h>
    4243#include <memstr.h>
    4344#include <errno.h>
     
    4748static event_t events[EVENT_END];
    4849
     50static void event_initialize(event_t *event)
     51{
     52        spinlock_initialize(&event->lock, "event.lock");
     53        event->answerbox = NULL;
     54        event->counter = 0;
     55        event->imethod = 0;
     56        event->masked = false;
     57        event->unmask_callback = NULL;
     58}
     59
     60static event_t *evno2event(int evno, task_t *t)
     61{
     62        ASSERT(evno < EVENT_TASK_END);
     63
     64        event_t *event;
     65
     66        if (evno < EVENT_END)
     67                event = &events[(event_type_t) evno];
     68        else
     69                event = &t->events[(event_task_type_t) evno - EVENT_END];
     70
     71        return event;
     72}
     73
    4974/** Initialize kernel events.
    5075 *
     
    5277void event_init(void)
    5378{
    54         for (unsigned int i = 0; i < EVENT_END; i++) {
    55                 spinlock_initialize(&events[i].lock, "event.lock");
    56                 events[i].answerbox = NULL;
    57                 events[i].counter = 0;
    58                 events[i].imethod = 0;
    59                 events[i].masked = false;
    60                 events[i].unmask_callback = NULL;
    61         }
    62 }
     79        for (unsigned int i = 0; i < EVENT_END; i++)
     80                event_initialize(evno2event(i, NULL));
     81}
     82
     83void event_task_init(task_t *t)
     84{
     85        for (unsigned int i = EVENT_END; i < EVENT_TASK_END; i++)
     86                event_initialize(evno2event(i, t));
     87}
     88
    6389
    6490/** Unsubscribe kernel events associated with an answerbox
     
    83109}
    84110
     111static void _event_set_unmask_callback(event_t *event, event_callback_t callback)
     112{
     113        spinlock_lock(&event->lock);
     114        event->unmask_callback = callback;
     115        spinlock_unlock(&event->lock);
     116}
     117
    85118/** Define a callback function for the event unmask event.
    86119 *
     
    94127        ASSERT(evno < EVENT_END);
    95128       
    96         spinlock_lock(&events[evno].lock);
    97         events[evno].unmask_callback = callback;
    98         spinlock_unlock(&events[evno].lock);
     129        _event_set_unmask_callback(evno2event(evno, NULL), callback);
     130}
     131
     132void event_task_set_unmask_callback(task_t *t, event_task_type_t evno,
     133    event_callback_t callback)
     134{
     135        ASSERT(evno >= (int) EVENT_END);
     136        ASSERT(evno < EVENT_TASK_END);
     137               
     138        _event_set_unmask_callback(evno2event(evno, t), callback);
     139}
     140
     141static int event_enqueue(event_t *event, bool mask, sysarg_t a1, sysarg_t a2,
     142    sysarg_t a3, sysarg_t a4, sysarg_t a5)
     143{
     144        int res;
     145
     146        spinlock_lock(&event->lock);
     147       
     148        if (event->answerbox != NULL) {
     149                if (!event->masked) {
     150                        call_t *call = ipc_call_alloc(FRAME_ATOMIC);
     151                       
     152                        if (call) {
     153                                call->flags |= IPC_CALL_NOTIF;
     154                                call->priv = ++event->counter;
     155                               
     156                                IPC_SET_IMETHOD(call->data, event->imethod);
     157                                IPC_SET_ARG1(call->data, a1);
     158                                IPC_SET_ARG2(call->data, a2);
     159                                IPC_SET_ARG3(call->data, a3);
     160                                IPC_SET_ARG4(call->data, a4);
     161                                IPC_SET_ARG5(call->data, a5);
     162                               
     163                                irq_spinlock_lock(&event->answerbox->irq_lock, true);
     164                                list_append(&call->link, &event->answerbox->irq_notifs);
     165                                irq_spinlock_unlock(&event->answerbox->irq_lock, true);
     166                               
     167                                waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST);
     168                               
     169                                if (mask)
     170                                        event->masked = true;
     171                               
     172                                res = EOK;
     173                        } else
     174                                res = ENOMEM;
     175                } else
     176                        res = EBUSY;
     177        } else
     178                res = ENOENT;
     179       
     180        spinlock_unlock(&event->lock);
     181        return res;
    99182}
    100183
     
    123206        ASSERT(evno < EVENT_END);
    124207       
    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;
     208        return event_enqueue(evno2event(evno, NULL), mask, a1, a2, a3, a4, a5);
     209}
     210
     211/** Send per-task kernel notification event
     212 *
     213 * @param t    Destination task.
     214 * @param evno Event type.
     215 * @param mask Mask further notifications after a successful
     216 *             sending.
     217 * @param a1   First argument.
     218 * @param a2   Second argument.
     219 * @param a3   Third argument.
     220 * @param a4   Fourth argument.
     221 * @param a5   Fifth argument.
     222 *
     223 * @return EOK if notification was successfully sent.
     224 * @return ENOMEM if the notification IPC message failed to allocate.
     225 * @return EBUSY if the notifications of the given type are
     226 *         currently masked.
     227 * @return ENOENT if the notifications of the given type are
     228 *         currently not subscribed.
     229 *
     230 */
     231int event_task_notify(task_t *t, event_task_type_t evno, bool mask, sysarg_t a1,
     232    sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5)
     233{
     234        ASSERT(evno >= (int) EVENT_END);
     235        ASSERT(evno < EVENT_TASK_END);
     236       
     237        return event_enqueue(evno2event(evno, t), mask, a1, a2, a3, a4, a5);
    164238}
    165239
     
    176250 *
    177251 */
    178 static int event_subscribe(event_type_t evno, sysarg_t imethod,
     252static int event_subscribe(event_t *event, sysarg_t imethod,
    179253    answerbox_t *answerbox)
    180254{
    181         ASSERT(evno < EVENT_END);
    182        
    183         spinlock_lock(&events[evno].lock);
    184        
    185255        int res;
    186        
    187         if (events[evno].answerbox == NULL) {
    188                 events[evno].answerbox = answerbox;
    189                 events[evno].imethod = imethod;
    190                 events[evno].counter = 0;
    191                 events[evno].masked = false;
     256
     257        spinlock_lock(&event->lock);
     258       
     259        if (event->answerbox == NULL) {
     260                event->answerbox = answerbox;
     261                event->imethod = imethod;
     262                event->counter = 0;
     263                event->masked = false;
    192264                res = EOK;
    193265        } else
    194266                res = EEXISTS;
    195267       
    196         spinlock_unlock(&events[evno].lock);
     268        spinlock_unlock(&event->lock);
    197269       
    198270        return res;
     
    204276 *
    205277 */
    206 static void event_unmask(event_type_t evno)
    207 {
    208         ASSERT(evno < EVENT_END);
    209        
    210         spinlock_lock(&events[evno].lock);
    211         events[evno].masked = false;
    212         event_callback_t callback = events[evno].unmask_callback;
    213         spinlock_unlock(&events[evno].lock);
     278static void event_unmask(event_t *event)
     279{
     280        spinlock_lock(&event->lock);
     281        event->masked = false;
     282        event_callback_t callback = event->unmask_callback;
     283        spinlock_unlock(&event->lock);
    214284       
    215285        /*
     
    218288         */
    219289        if (callback != NULL)
    220                 callback();
     290                callback(event);
    221291}
    222292
     
    235305sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    236306{
    237         if (evno >= EVENT_END)
     307        if (evno >= EVENT_TASK_END)
    238308                return ELIMIT;
    239309       
    240         return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    241             imethod, &TASK->answerbox);
     310        return (sysarg_t) event_subscribe(evno2event(evno, TASK),
     311            (sysarg_t) imethod, &TASK->answerbox);
    242312}
    243313
     
    257327sysarg_t sys_event_unmask(sysarg_t evno)
    258328{
    259         if (evno >= EVENT_END)
     329        if (evno >= EVENT_TASK_END)
    260330                return ELIMIT;
    261331       
    262         event_unmask((event_type_t) evno);
     332        event_unmask(evno2event(evno, TASK));
     333
    263334        return EOK;
    264335}
  • kernel/generic/src/proc/task.c

    rb585dfa9 r5d0500c  
    5050#include <ipc/ipc.h>
    5151#include <ipc/ipcrsc.h>
     52#include <ipc/event.h>
    5253#include <print.h>
    5354#include <errno.h>
     
    5758#include <syscall/copy.h>
    5859#include <macros.h>
    59 #include <ipc/event.h>
    6060
    6161/** Spinlock protecting the tasks_tree AVL tree. */
     
    201201        task->ipc_info.irq_notif_received = 0;
    202202        task->ipc_info.forwarded = 0;
     203
     204        event_task_init(task);
    203205       
    204206#ifdef CONFIG_UDEBUG
Note: See TracChangeset for help on using the changeset viewer.