Changeset c4cfe4c in mainline for uspace/app/kio/kio.c


Ignore:
Timestamp:
2025-04-17T16:01:16Z (5 days ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
888c06e
Parents:
1db4e2ae (diff), 250a435 (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.
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-04-17 15:51:11)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-04-17 16:01:16)
Message:

Convert kernel console writing to byte arrays

More buffer per buffer (the original char32_t buffer takes up four
times as much space for the same amount of backlog, which is wasteful).
It is also faster, possibly thanks to bigger chunks being processed in bulk.
Gonna try to figure out if the locking can be improved further.

Also changed to use a syscall for reading KIO buffer from uspace,
to allow better synchronization.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/kio/kio.c

    r1db4e2ae rc4cfe4c  
    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
     
    5559typedef struct {
    5660        link_t link;
    57         size_t length;
    58         char32_t *data;
     61        size_t bytes;
     62        char *data;
    5963} item_t;
    6064
    6165static prodcons_t pc;
    62 
    63 /* Pointer to kio area */
    64 static char32_t *kio = (char32_t *) AS_AREA_ANY;
    65 static size_t kio_length;
    6666
    6767/* Notification mutex */
    6868static FIBRIL_MUTEX_INITIALIZE(mtx);
    6969
     70#define READ_BUFFER_SIZE PAGE_SIZE
     71
     72static size_t current_at;
     73static char read_buffer[READ_BUFFER_SIZE];
     74
    7075/** Klog producer
    7176 *
     
    7782 *
    7883 */
    79 static void producer(size_t length, char32_t *data)
    80 {
    81         item_t *item = (item_t *) malloc(sizeof(item_t));
     84static void producer(size_t bytes, char *data)
     85{
     86        item_t *item = malloc(sizeof(item_t));
    8287        if (item == NULL)
    8388                return;
    8489
    85         size_t sz = sizeof(char32_t) * length;
    86         char32_t *buf = (char32_t *) malloc(sz);
    87         if (buf == NULL) {
     90        item->bytes = bytes;
     91        item->data = malloc(bytes);
     92        if (!item->data) {
    8893                free(item);
    8994                return;
    9095        }
    9196
    92         memcpy(buf, data, sz);
     97        memcpy(item->data, data, bytes);
    9398
    9499        link_initialize(&item->link);
    95         item->length = length;
    96         item->data = buf;
    97100        prodcons_produce(&pc, &item->link);
    98101}
     
    120123                item_t *item = list_get_instance(link, item_t, link);
    121124
    122                 for (size_t i = 0; i < item->length; i++)
    123                         putuchar(item->data[i]);
    124 
    125                 if (log != NULL) {
    126                         for (size_t i = 0; i < item->length; i++)
    127                                 fputuc(item->data[i], log);
    128 
     125                fwrite(item->data, 1, item->bytes, stdout);
     126
     127                if (log) {
     128                        fwrite(item->data, 1, item->bytes, log);
    129129                        fflush(log);
    130130                        vfs_sync(fileno(log));
     
    149149static void kio_notification_handler(ipc_call_t *call, void *arg)
    150150{
     151        size_t kio_written = (size_t) ipc_get_arg1(call);
     152
    151153        /*
    152154         * Make sure we process only a single notification
    153155         * at any time to limit the chance of the consumer
    154156         * starving.
    155          *
    156          * Note: Usually the automatic masking of the kio
    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 kio notifications,
    161          * this possibility cannot be generally avoided.
    162157         */
    163158
    164159        fibril_mutex_lock(&mtx);
    165160
    166         size_t kio_start = (size_t) ipc_get_arg1(call);
    167         size_t kio_len = (size_t) ipc_get_arg2(call);
    168         size_t kio_stored = (size_t) ipc_get_arg3(call);
    169 
    170         size_t offset = (kio_start + kio_len - kio_stored) % kio_length;
    171 
    172         /* Copy data from the ring buffer */
    173         if (offset + kio_stored >= kio_length) {
    174                 size_t split = kio_length - offset;
    175 
    176                 producer(split, kio + offset);
    177                 producer(kio_stored - split, kio);
    178         } else
    179                 producer(kio_stored, kio + offset);
     161        while (current_at != kio_written) {
     162                size_t read = kio_read(read_buffer, READ_BUFFER_SIZE, current_at);
     163                if (read == 0)
     164                        break;
     165
     166                current_at += read;
     167
     168                if (read > READ_BUFFER_SIZE) {
     169                        /* We missed some data. */
     170                        // TODO: Send a message with the number of lost characters to the consumer.
     171                        read = READ_BUFFER_SIZE;
     172                }
     173
     174                producer(read, read_buffer);
     175        }
    180176
    181177        async_event_unmask(EVENT_KIO);
     
    185181int main(int argc, char *argv[])
    186182{
    187         size_t pages;
    188         errno_t rc = sysinfo_get_value("kio.pages", &pages);
    189         if (rc != EOK) {
    190                 fprintf(stderr, "%s: Unable to get number of kio pages\n",
    191                     NAME);
    192                 return rc;
    193         }
    194 
    195         uintptr_t faddr;
    196         rc = sysinfo_get_value("kio.faddr", &faddr);
    197         if (rc != EOK) {
    198                 fprintf(stderr, "%s: Unable to get kio physical address\n",
    199                     NAME);
    200                 return rc;
    201         }
    202 
    203         size_t size = pages * PAGE_SIZE;
    204         kio_length = size / sizeof(char32_t);
    205 
    206         rc = physmem_map(faddr, pages, AS_AREA_READ | AS_AREA_CACHEABLE,
    207             (void *) &kio);
    208         if (rc != EOK) {
    209                 fprintf(stderr, "%s: Unable to map kio\n", NAME);
    210                 return rc;
    211         }
    212 
    213183        prodcons_initialize(&pc);
    214         rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);
     184        errno_t rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);
    215185        if (rc != EOK) {
    216186                fprintf(stderr, "%s: Unable to register kio notifications\n",
Note: See TracChangeset for help on using the changeset viewer.