Changes in / [0d8a304:8d308b9] in mainline


Ignore:
Files:
12 edited

Legend:

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

    r0d8a304 r8d308b9  
    5151        /** Counter. */
    5252        size_t counter;
    53         /** Masked flag. */
    54         bool masked;
    55         /** Unmask callback. */
    56         void (*unmask_cb)(void);
    5753} event_t;
    5854
    5955extern void event_init(void);
     56extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
     57extern bool event_is_subscribed(event_type_t);
    6058extern void event_cleanup_answerbox(answerbox_t *);
    61 extern void event_set_unmask_callback(event_type_t, void (*)(void));
    6259
    63 #define event_notify_0(e, m) \
    64         event_notify((e), (m), 0, 0, 0, 0, 0)
    65 #define event_notify_1(e, m, a1) \
    66         event_notify((e), (m), (a1), 0, 0, 0, 0)
    67 #define event_notify_2(e, m, a1, a2) \
    68         event_notify((e), (m), (a1), (a2), 0, 0, 0)
    69 #define event_notify_3(e, m, a1, a2, a3) \
    70         event_notify((e), (m), (a1), (a2), (a3), 0, 0)
    71 #define event_notify_4(e, m, a1, a2, a3, a4) \
    72         event_notify((e), (m), (a1), (a2), (a3), (a4), 0)
    73 #define event_notify_5(e, m, a1, a2, a3, a4, a5) \
    74         event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
     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))
    7572
    76 extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
     73extern void event_notify(event_type_t, sysarg_t, sysarg_t, sysarg_t,
    7774    sysarg_t, sysarg_t);
    78 
    79 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
    80 extern sysarg_t sys_event_unmask(sysarg_t);
    8175
    8276#endif
  • kernel/generic/include/ipc/event_types.h

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

    r0d8a304 r8d308b9  
    7575       
    7676        SYS_EVENT_SUBSCRIBE,
    77         SYS_EVENT_UNMASK,
    7877       
    7978        SYS_CAP_GRANT,
  • kernel/generic/src/console/cmd.c

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

    r0d8a304 r8d308b9  
    5353#include <str.h>
    5454
    55 #define KLOG_PAGES    8
     55#define KLOG_PAGES    4
    5656#define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
    5757#define KLOG_LATENCY  8
     
    165165        sysinfo_set_item_val("klog.faddr", NULL, (sysarg_t) faddr);
    166166        sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES);
    167 
    168         event_set_unmask_callback(EVENT_KLOG, klog_update);
    169167       
    170168        spinlock_lock(&klog_lock);
     
    267265        spinlock_lock(&klog_lock);
    268266       
    269         if ((klog_inited) && (klog_uspace > 0)) {
    270                 if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
    271                     klog_uspace) == EOK)
    272                         klog_uspace = 0;
     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;
    273270        }
    274271       
  • kernel/generic/src/ipc/event.c

    r0d8a304 r8d308b9  
    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_cb = 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 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  */
    17863static int event_subscribe(event_type_t evno, sysarg_t imethod,
    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);
     
    18975                events[evno].imethod = imethod;
    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)
    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  */
    23586sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    23687{
    237         if (evno >= EVENT_END)
    238                 return ELIMIT;
    239        
    24088        return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    24189            imethod, &TASK->answerbox);
    24290}
    24391
    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)
     92bool event_is_subscribed(event_type_t evno)
    25893{
    259         if (evno >= EVENT_END)
    260                 return ELIMIT;
     94        bool res;
    26195       
    262         event_unmask((event_type_t) evno);
    263         return EOK;
     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)
     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);
    264147}
    265148
  • kernel/generic/src/proc/task.c

    r0d8a304 r8d308b9  
    534534        */
    535535        if (notify) {
    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) {
     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               
    539541#ifdef CONFIG_UDEBUG
    540542                        /* Wait for a debugging session. */
  • kernel/generic/src/syscall/syscall.c

    r0d8a304 r8d308b9  
    161161        /* Event notification syscalls. */
    162162        (syshandler_t) sys_event_subscribe,
    163         (syshandler_t) sys_event_unmask,
    164163       
    165164        /* Capabilities related syscalls. */
  • uspace/app/klog/klog.c

    r0d8a304 r8d308b9  
    4444#include <io/klog.h>
    4545#include <sysinfo.h>
    46 #include <malloc.h>
    47 #include <fibril_synch.h>
    48 #include <adt/list.h>
    49 #include <adt/prodcons.h>
    5046
    5147#define NAME       "klog"
    5248#define LOG_FNAME  "/log/klog"
    53 
    54 /* Producer/consumer buffers */
    55 typedef struct {
    56         link_t link;
    57         size_t length;
    58         wchar_t *data;
    59 } item_t;
    60 
    61 static prodcons_t pc;
    6249
    6350/* Pointer to klog area */
     
    6552static size_t klog_length;
    6653
    67 /* Notification mutex */
    68 static FIBRIL_MUTEX_INITIALIZE(mtx);
     54static FILE *log;
    6955
    70 /** Klog producer
    71  *
    72  * Copies the contents of a character buffer to local
    73  * producer/consumer queue.
    74  *
    75  * @param length Number of characters to copy.
    76  * @param data   Pointer to the kernel klog buffer.
    77  *
    78  */
    79 static void producer(size_t length, wchar_t *data)
     56static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
    8057{
    81         item_t *item = (item_t *) malloc(sizeof(item_t));
    82         if (item == NULL)
    83                 return;
    84        
    85         size_t sz = sizeof(wchar_t) * length;
    86         wchar_t *buf = (wchar_t *) malloc(sz);
    87         if (data == NULL) {
    88                 free(item);
    89                 return;
    90         }
    91        
    92         memcpy(buf, data, sz);
    93        
    94         link_initialize(&item->link);
    95         item->length = length;
    96         item->data = buf;
    97         prodcons_produce(&pc, &item->link);
    98 }
    99 
    100 /** Klog consumer
    101  *
    102  * Waits in an infinite loop for the character data created by
    103  * the producer and outputs them to stdout and optionally into
    104  * a file.
    105  *
    106  * @param data Unused.
    107  *
    108  * @return Always EOK (unreachable).
    109  *
    110  */
    111 static int consumer(void *data)
    112 {
    113         FILE *log = fopen(LOG_FNAME, "a");
    114         if (log == NULL)
    115                 printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
    116                     str_error(errno));
    117        
    118         while (true) {
    119                 link_t *link = prodcons_consume(&pc);
    120                 item_t *item = list_get_instance(link, item_t, link);
    121                
    122                 for (size_t i = 0; i < item->length; i++)
    123                         putchar(item->data[i]);
    124                
    125                 if (log != NULL) {
    126                         for (size_t i = 0; i < item->length; i++)
    127                                 fputc(item->data[i], log);
    128                        
    129                         fflush(log);
    130                         fsync(fileno(log));
    131                 }
    132                
    133                 free(item->data);
    134                 free(item);
    135         }
    136        
    137         fclose(log);
    138         return EOK;
    139 }
    140 
    141 /** Kernel notification handler
    142  *
    143  * Receives kernel klog notifications.
    144  *
    145  * @param callid IPC call ID.
    146  * @param call   IPC call structure.
    147  *
    148  */
    149 static void notification_received(ipc_callid_t callid, ipc_call_t *call)
    150 {
    151         /*
    152          * Make sure we process only a single notification
    153          * at any time to limit the chance of the consumer
    154          * starving.
    155          *
    156          * Note: Usually the automatic masking of the klog
    157          * notifications on the kernel side does the trick
    158          * of limiting the chance of accidentally copying
    159          * the same data multiple times. However, due to
    160          * the non-blocking architecture of klog notifications,
    161          * this possibility cannot be generally avoided.
    162          */
    163        
    164         fibril_mutex_lock(&mtx);
    165        
    16658        size_t klog_start = (size_t) IPC_GET_ARG1(*call);
    16759        size_t klog_len = (size_t) IPC_GET_ARG2(*call);
    16860        size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
     61        size_t i;
    16962       
    170         size_t offset = (klog_start + klog_len - klog_stored) % klog_length;
     63        for (i = klog_len - klog_stored; i < klog_len; i++) {
     64                wchar_t ch = klog[(klog_start + i) % klog_length];
     65               
     66                putchar(ch);
     67               
     68                if (log != NULL)
     69                        fputc(ch, log);
     70        }
    17171       
    172         /* Copy data from the ring buffer */
    173         if (offset + klog_stored >= klog_length) {
    174                 size_t split = klog_length - offset;
    175                
    176                 producer(split, klog + offset);
    177                 producer(klog_stored - split, klog);
    178         } else
    179                 producer(klog_stored, klog + offset);
    180        
    181         event_unmask(EVENT_KLOG);
    182         fibril_mutex_unlock(&mtx);
     72        if (log != NULL) {
     73                fflush(log);
     74                fsync(fileno(log));
     75        }
    18376}
    18477
     
    218111        }
    219112       
    220         prodcons_initialize(&pc);
    221         async_set_interrupt_received(notification_received);
    222113        rc = event_subscribe(EVENT_KLOG, 0);
    223114        if (rc != EOK) {
     
    227118        }
    228119       
    229         fid_t fid = fibril_create(consumer, NULL);
    230         if (!fid) {
    231                 fprintf(stderr, "%s: Unable to create consumer fibril\n",
    232                     NAME);
    233                 return ENOMEM;
    234         }
     120        log = fopen(LOG_FNAME, "a");
     121        if (log == NULL)
     122                printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
     123                    str_error(errno));
    235124       
    236         fibril_add_ready(fid);
    237         event_unmask(EVENT_KLOG);
     125        async_set_interrupt_received(interrupt_received);
    238126        klog_update();
    239        
    240         task_retval(0);
    241127        async_manager();
    242128       
  • uspace/lib/c/Makefile

    r0d8a304 r8d308b9  
    108108        generic/adt/measured_strings.c \
    109109        generic/adt/char_map.c \
    110         generic/adt/prodcons.c \
    111110        generic/time.c \
    112111        generic/stdlib.c \
  • uspace/lib/c/generic/event.c

    r0d8a304 r8d308b9  
    4141#include <kernel/ipc/event_types.h>
    4242
    43 /** Subscribe event notifications.
     43/** Subscribe for event notifications.
    4444 *
    45  * @param evno    Event type to subscribe.
    46  * @param imethod Use this interface and method for notifying me.
     45 * @param evno   Event number.
     46 * @param method Use this method for notifying me.
    4747 *
    4848 * @return Value returned by the kernel.
    49  *
    5049 */
    51 int event_subscribe(event_type_t evno, sysarg_t imethod)
     50int event_subscribe(event_type_t e, sysarg_t method)
    5251{
    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  */
    64 int event_unmask(event_type_t evno)
    65 {
    66         return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
     52        return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method);
    6753}
    6854
  • uspace/lib/c/include/event.h

    r0d8a304 r8d308b9  
    3939
    4040extern int event_subscribe(event_type_t, sysarg_t);
    41 extern int event_unmask(event_type_t);
    4241
    4342#endif
Note: See TracChangeset for help on using the changeset viewer.