Changeset d5b37b6 in mainline


Ignore:
Timestamp:
2025-04-17T15:14:03Z (5 days ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
690ad20
Parents:
571cc2d
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-04-11 17:35:09)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-04-17 15:14:03)
Message:

Use a new syscall, SYS_KIO_READ, for reading from KIO buffer

Originally, the buffer memory was shared between kernel and
uspace, presumably to avoid the overhead of syscalls.
However, this makes synchronization with kernel impossible,
so it is not possible to ensure it works reliably without
random glitches. Also, relative to everything else /app/kio
does with the data, the syscall overhead is positively tiny.

Files:
8 edited

Legend:

Unmodified
Added
Removed
  • abi/include/abi/syscall.h

    r571cc2d rd5b37b6  
    110110        SYS_DEBUG_CONSOLE,
    111111
    112         SYS_KLOG
     112        SYS_KLOG,
     113        SYS_KIO_READ,
    113114} syscall_t;
    114115
  • kernel/generic/include/console/console.h

    r571cc2d rd5b37b6  
    3636#define KERN_CONSOLE_H_
    3737
    38 #include <typedefs.h>
    39 #include <print.h>
    4038#include <console/chardev.h>
    4139#include <synch/spinlock.h>
     
    6967extern irq_spinlock_t kio_lock;
    7068
     69extern sysarg_t sys_kio_read(uspace_addr_t buf, size_t size, size_t at);
    7170extern sys_errno_t sys_kio(int cmd, uspace_addr_t buf, size_t size);
    7271
  • kernel/generic/src/console/console.c

    r571cc2d rd5b37b6  
    22 * Copyright (c) 2003 Josef Cejka
    33 * Copyright (c) 2005 Jakub Jermar
     4 * Copyright (c) 2025 Jiří Zárevúcky
    45 * All rights reserved.
    56 *
     
    3536
    3637#include <abi/kio.h>
    37 #include <arch.h>
    38 #include <assert.h>
    39 #include <atomic.h>
    4038#include <console/chardev.h>
    4139#include <console/console.h>
    42 #include <ddi/ddi.h>
    43 #include <ddi/irq.h>
    4440#include <errno.h>
    4541#include <ipc/event.h>
    46 #include <ipc/irq.h>
    47 #include <mm/frame.h> /* SIZE2FRAMES */
    4842#include <panic.h>
    4943#include <preemption.h>
    50 #include <proc/thread.h>
     44#include <proc/task.h>
    5145#include <putchar.h>
    5246#include <stdatomic.h>
    5347#include <stdio.h>
    5448#include <stdlib.h>  /* malloc */
    55 #include <str.h>
    5649#include <synch/mutex.h>
    5750#include <synch/spinlock.h>
    58 #include <synch/waitq.h>
    5951#include <syscall/copy.h>
    6052#include <sysinfo/sysinfo.h>
    61 #include <typedefs.h>
    6253
    6354#define KIO_PAGES    8
     
    6556
    6657/** Kernel log cyclic buffer */
    67 char32_t kio[KIO_LENGTH] __attribute__((aligned(PAGE_SIZE)));
     58static char32_t kio[KIO_LENGTH];
    6859
    6960/** Kernel log initialized */
     
    8778/** Kernel log spinlock */
    8879IRQ_SPINLOCK_INITIALIZE(kio_lock);
    89 
    90 /** Physical memory area used for kio buffer */
    91 static parea_t kio_parea;
    9280
    9381static indev_t stdin_sink;
     
    187175
    188176/** Initialize kernel logging facility
    189  *
    190  * The shared area contains kernel cyclic buffer. Userspace application may
    191  * be notified on new data with indication of position and size
    192  * of the data within the circular buffer.
    193  *
    194177 */
    195178void kio_init(void)
    196179{
    197         void *faddr = (void *) KA2PA(kio);
    198 
    199         assert((uintptr_t) faddr % FRAME_SIZE == 0);
    200 
    201         ddi_parea_init(&kio_parea);
    202         kio_parea.pbase = (uintptr_t) faddr;
    203         kio_parea.frames = SIZE2FRAMES(sizeof(kio));
    204         kio_parea.unpriv = false;
    205         kio_parea.mapped = false;
    206         ddi_parea_register(&kio_parea);
    207 
    208         sysinfo_set_item_val("kio.faddr", NULL, (sysarg_t) faddr);
    209         sysinfo_set_item_val("kio.pages", NULL, KIO_PAGES);
    210 
    211180        event_set_unmask_callback(EVENT_KIO, kio_update);
    212181        atomic_store(&kio_inited, true);
     
    332301        if (ch == '\n')
    333302                kio_update(NULL);
     303}
     304
     305/** Reads up to `size` characters from kio buffer starting at character `at`.
     306 *
     307 * @param size  Maximum number of characters that can be stored in buffer.
     308 *              Values greater than KIO_LENGTH are silently treated as KIO_LENGTH
     309 *              for the purposes of calculating the return value.
     310 * @return Number of characters read. Can be more than `size`.
     311 *         In that case, `size` characters are written to user buffer
     312 *         and the extra amount is the number of characters missed.
     313 */
     314sysarg_t sys_kio_read(uspace_addr_t buf, size_t size, size_t at)
     315{
     316        errno_t rc;
     317        size_t missed = 0;
     318
     319        irq_spinlock_lock(&kio_lock, true);
     320
     321        if (at == kio_written) {
     322                irq_spinlock_unlock(&kio_lock, true);
     323                return 0;
     324        }
     325
     326        size_t readable_chars = kio_written - at;
     327        if (readable_chars > KIO_LENGTH) {
     328                missed = readable_chars - KIO_LENGTH;
     329                readable_chars = KIO_LENGTH;
     330        }
     331
     332        size_t actual_read = min(readable_chars, size);
     333        size_t offset = (kio_written - readable_chars) % KIO_LENGTH;
     334
     335        if (offset + actual_read > KIO_LENGTH) {
     336                size_t first = KIO_LENGTH - offset;
     337                size_t last = actual_read - first;
     338                size_t first_bytes = first * sizeof(kio[0]);
     339                size_t last_bytes = last * sizeof(kio[0]);
     340
     341                rc = copy_to_uspace(buf, &kio[offset], first_bytes);
     342                if (rc == EOK)
     343                        rc = copy_to_uspace(buf + first_bytes, &kio[0], last_bytes);
     344        } else {
     345                rc = copy_to_uspace(buf, &kio[offset], actual_read * sizeof(kio[0]));
     346        }
     347
     348        irq_spinlock_unlock(&kio_lock, true);
     349
     350        if (rc != EOK) {
     351                log(LF_OTHER, LVL_WARN,
     352                    "[%s(%" PRIu64 ")] Terminating due to invalid memory buffer"
     353                    " in SYS_KIO_READ.\n", TASK->name, TASK->taskid);
     354                task_kill_self(true);
     355        }
     356
     357        return actual_read + missed;
    334358}
    335359
  • kernel/generic/src/syscall/syscall.c

    r571cc2d rd5b37b6  
    137137
    138138        [SYS_KLOG] = (syshandler_t) sys_klog,
     139        [SYS_KIO_READ] = (syshandler_t) sys_kio_read,
    139140};
    140141
  • uspace/app/kio/kio.c

    r571cc2d rd5b37b6  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
     3 * Copyright (c) 2025 Jiří Zárevúcky
    34 * All rights reserved.
    45 *
     
    3435 */
    3536
     37#include <_bits/decls.h>
     38#include <libarch/config.h>
    3639#include <stdio.h>
    3740#include <async.h>
     
    4750#include <adt/prodcons.h>
    4851#include <tinput.h>
     52#include <uchar.h>
    4953#include <vfs/vfs.h>
    5054
     
    6165static prodcons_t pc;
    6266
    63 /* Pointer to kio area */
    64 static char32_t *kio = (char32_t *) AS_AREA_ANY;
    65 static size_t kio_length;
    66 
    6767/* Notification mutex */
    6868static FIBRIL_MUTEX_INITIALIZE(mtx);
    6969
    70 static size_t last_notification;
     70#define READ_BUFFER_SIZE (PAGE_SIZE / sizeof(char32_t))
     71
     72static size_t current_at;
     73static char32_t read_buffer[READ_BUFFER_SIZE];
    7174
    7275/** Klog producer
     
    151154static void kio_notification_handler(ipc_call_t *call, void *arg)
    152155{
     156        size_t kio_written = (size_t) ipc_get_arg1(call);
     157
    153158        /*
    154159         * Make sure we process only a single notification
     
    159164        fibril_mutex_lock(&mtx);
    160165
    161         size_t kio_written = (size_t) ipc_get_arg1(call);
    162 
    163         /* This works just fine even when kio_written overflows. */
    164         size_t new_chars = kio_written - last_notification;
    165         last_notification = kio_written;
    166 
    167         if (new_chars > kio_length) {
    168                 /* We missed some data. */
    169                 // TODO: Send a message with the number of lost bytes to the consumer.
    170                 new_chars = kio_length;
    171         }
    172 
    173         size_t offset = (kio_written - new_chars) % kio_length;
    174 
    175         /* Copy data from the ring buffer */
    176         if (offset + new_chars > kio_length) {
    177                 size_t split = kio_length - offset;
    178 
    179                 producer(split, kio + offset);
    180                 producer(new_chars - split, kio);
    181         } else {
    182                 producer(new_chars, kio + offset);
     166        while (current_at != kio_written) {
     167                size_t read = kio_read(read_buffer, READ_BUFFER_SIZE, current_at);
     168                if (read == 0)
     169                        break;
     170
     171                current_at += read;
     172
     173                if (read > READ_BUFFER_SIZE) {
     174                        /* We missed some data. */
     175                        // TODO: Send a message with the number of lost characters to the consumer.
     176                        read = READ_BUFFER_SIZE;
     177                }
     178
     179                producer(read, read_buffer);
    183180        }
    184181
     
    189186int main(int argc, char *argv[])
    190187{
    191         size_t pages;
    192         errno_t rc = sysinfo_get_value("kio.pages", &pages);
    193         if (rc != EOK) {
    194                 fprintf(stderr, "%s: Unable to get number of kio pages\n",
    195                     NAME);
    196                 return rc;
    197         }
    198 
    199         uintptr_t faddr;
    200         rc = sysinfo_get_value("kio.faddr", &faddr);
    201         if (rc != EOK) {
    202                 fprintf(stderr, "%s: Unable to get kio physical address\n",
    203                     NAME);
    204                 return rc;
    205         }
    206 
    207         size_t size = pages * PAGE_SIZE;
    208         kio_length = size / sizeof(char32_t);
    209 
    210         rc = physmem_map(faddr, pages, AS_AREA_READ | AS_AREA_CACHEABLE,
    211             (void *) &kio);
    212         if (rc != EOK) {
    213                 fprintf(stderr, "%s: Unable to map kio\n", NAME);
    214                 return rc;
    215         }
    216 
    217188        prodcons_initialize(&pc);
    218         rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);
     189        errno_t rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);
    219190        if (rc != EOK) {
    220191                fprintf(stderr, "%s: Unable to register kio notifications\n",
  • uspace/app/trace/syscalls.c

    r571cc2d rd5b37b6  
    115115        [SYS_DEBUG_CONSOLE] = { "debug_console", 0, V_ERRNO },
    116116
    117         [SYS_KLOG] = { "klog", 5, V_ERRNO }
     117        [SYS_KLOG] = { "klog", 5, V_ERRNO },
     118        [SYS_KIO_READ] = { "kio_read", 3, V_INTEGER },
    118119};
    119120
  • uspace/lib/c/generic/io/kio.c

    r571cc2d rd5b37b6  
    3434 */
    3535
     36#include <abi/syscall.h>
    3637#include <stddef.h>
    3738#include <libc.h>
     
    112113}
    113114
     115size_t kio_read(char32_t *buf, size_t n, size_t at)
     116{
     117        return __SYSCALL3(SYS_KIO_READ, (sysarg_t) buf, n, at);
     118}
     119
    114120/** Print formatted text to kio.
    115121 *
  • uspace/lib/c/include/io/kio.h

    r571cc2d rd5b37b6  
    3636#define _LIBC_IO_KIO_H_
    3737
    38 #include <stddef.h>
    39 #include <stdarg.h>
    40 #include <io/verify.h>
    4138#include <_bits/errno.h>
    4239#include <_bits/size_t.h>
     40#include <io/verify.h>
     41#include <stdarg.h>
     42#include <stddef.h>
     43#include <uchar.h>
    4344
    4445extern void __kio_init(void);
     
    5051    _HELENOS_PRINTF_ATTRIBUTE(1, 2);
    5152extern int kio_vprintf(const char *, va_list);
     53
     54extern size_t kio_read(char32_t *buf, size_t n, size_t at);
    5255
    5356/*
Note: See TracChangeset for help on using the changeset viewer.