Changes in uspace/app/kio/kio.c [690ad20:28a5ebd] in mainline


Ignore:
File:
1 edited

Legend:

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

    r690ad20 r28a5ebd  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
    3  * Copyright (c) 2025 Jiří Zárevúcky
    43 * All rights reserved.
    54 *
     
    3534 */
    3635
    37 #include <_bits/decls.h>
    38 #include <libarch/config.h>
    3936#include <stdio.h>
    4037#include <async.h>
     
    5047#include <adt/prodcons.h>
    5148#include <tinput.h>
    52 #include <uchar.h>
    5349#include <vfs/vfs.h>
    5450
     
    5955typedef struct {
    6056        link_t link;
    61         size_t bytes;
    62         char *data;
     57        size_t length;
     58        char32_t *data;
    6359} item_t;
    6460
    6561static prodcons_t pc;
     62
     63/* Pointer to kio area */
     64static char32_t *kio = (char32_t *) AS_AREA_ANY;
     65static size_t kio_length;
    6666
    6767/* Notification mutex */
    6868static FIBRIL_MUTEX_INITIALIZE(mtx);
    6969
    70 #define READ_BUFFER_SIZE PAGE_SIZE
    71 
    72 static size_t current_at;
    73 static char read_buffer[READ_BUFFER_SIZE];
    74 
    7570/** Klog producer
    7671 *
     
    8277 *
    8378 */
    84 static void producer(size_t bytes, char *data)
    85 {
    86         item_t *item = malloc(sizeof(item_t));
     79static void producer(size_t length, char32_t *data)
     80{
     81        item_t *item = (item_t *) malloc(sizeof(item_t));
    8782        if (item == NULL)
    8883                return;
    8984
    90         item->bytes = bytes;
    91         item->data = malloc(bytes);
    92         if (!item->data) {
     85        size_t sz = sizeof(char32_t) * length;
     86        char32_t *buf = (char32_t *) malloc(sz);
     87        if (buf == NULL) {
    9388                free(item);
    9489                return;
    9590        }
    9691
    97         memcpy(item->data, data, bytes);
     92        memcpy(buf, data, sz);
    9893
    9994        link_initialize(&item->link);
     95        item->length = length;
     96        item->data = buf;
    10097        prodcons_produce(&pc, &item->link);
    10198}
     
    123120                item_t *item = list_get_instance(link, item_t, link);
    124121
    125                 fwrite(item->data, 1, item->bytes, stdout);
    126 
    127                 if (log) {
    128                         fwrite(item->data, 1, item->bytes, log);
     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
    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 
    153151        /*
    154152         * Make sure we process only a single notification
    155153         * at any time to limit the chance of the consumer
    156154         * 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.
    157162         */
    158163
    159164        fibril_mutex_lock(&mtx);
    160165
    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         }
     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);
    176180
    177181        async_event_unmask(EVENT_KIO);
     
    181185int main(int argc, char *argv[])
    182186{
     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
    183213        prodcons_initialize(&pc);
    184         errno_t rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);
     214        rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);
    185215        if (rc != EOK) {
    186216                fprintf(stderr, "%s: Unable to register kio notifications\n",
Note: See TracChangeset for help on using the changeset viewer.