Changeset c4cfe4c in mainline


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.

Files:
1 deleted
18 edited

Legend:

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

    r1db4e2ae rc4cfe4c  
    110110        SYS_DEBUG_CONSOLE,
    111111
    112         SYS_KLOG
     112        SYS_KLOG,
     113        SYS_KIO_READ,
    113114} syscall_t;
    114115
  • kernel/genarch/src/drivers/ega/ega.c

    r1db4e2ae rc4cfe4c  
    6969        uint8_t *backbuf;
    7070        ioport8_t *base;
     71        mbstate_t mbstate;
    7172} ega_instance_t;
    7273
    73 static void ega_putuchar(outdev_t *, char32_t);
     74static void ega_write(outdev_t *, const char *, size_t);
    7475static void ega_redraw(outdev_t *);
    7576
    7677static outdev_operations_t egadev_ops = {
    77         .write = ega_putuchar,
     78        .write = ega_write,
    7879        .redraw = ega_redraw,
    7980        .scroll_up = NULL,
     
    538539}
    539540
    540 static void ega_putuchar(outdev_t *dev, char32_t ch)
    541 {
    542         ega_instance_t *instance = (ega_instance_t *) dev->data;
    543 
    544         irq_spinlock_lock(&instance->lock, true);
    545 
     541static void _putuchar(ega_instance_t *instance, char32_t ch)
     542{
    546543        switch (ch) {
    547544        case '\n':
     
    564561        ega_check_cursor(instance);
    565562        ega_move_cursor(instance);
     563}
     564
     565static void ega_write(outdev_t *dev, const char *s, size_t n)
     566{
     567        ega_instance_t *instance = (ega_instance_t *) dev->data;
     568
     569        irq_spinlock_lock(&instance->lock, true);
     570
     571        size_t offset = 0;
     572        char32_t ch;
     573
     574        while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))
     575                _putuchar(instance, ch);
    566576
    567577        irq_spinlock_unlock(&instance->lock, true);
  • kernel/genarch/src/drivers/ns16550/ns16550.c

    r1db4e2ae rc4cfe4c  
    112112}
    113113
    114 static void ns16550_putuchar(outdev_t *dev, char32_t ch)
     114static void ns16550_write(outdev_t *dev, const char *s, size_t n)
    115115{
    116116        ns16550_instance_t *instance = (ns16550_instance_t *) dev->data;
    117117
    118         if ((!instance->parea.mapped) || (console_override)) {
    119                 if (ch == '\n')
     118        if (instance->parea.mapped && !console_override)
     119                return;
     120
     121        const char *top = s + n;
     122        assert(top >= s);
     123
     124        for (; s < top; s++) {
     125                if (*s == '\n')
    120126                        ns16550_sendb(instance, '\r');
    121127
    122                 if (ascii_check(ch))
    123                         ns16550_sendb(instance, (uint8_t) ch);
    124                 else
    125                         ns16550_sendb(instance, U_SPECIAL);
     128                ns16550_sendb(instance, (uint8_t) *s);
    126129        }
    127130}
    128131
    129132static outdev_operations_t ns16550_ops = {
    130         .write = ns16550_putuchar,
     133        .write = ns16550_write,
    131134        .redraw = NULL
    132135};
  • kernel/genarch/src/drivers/pl011/pl011.c

    r1db4e2ae rc4cfe4c  
    5656}
    5757
    58 static void pl011_uart_putuchar(outdev_t *dev, char32_t ch)
     58static void pl011_uart_write(outdev_t *dev, const char *s, size_t n)
    5959{
    6060        pl011_uart_t *uart = dev->data;
     
    6464                return;
    6565
    66         if (!ascii_check(ch))
    67                 pl011_uart_sendb(uart, U_SPECIAL);
    68         else {
    69                 if (ch == '\n')
    70                         pl011_uart_sendb(uart, (uint8_t) '\r');
    71                 pl011_uart_sendb(uart, (uint8_t) ch);
     66        const char *top = s + n;
     67        assert(top >= s);
     68
     69        for (; s < top; s++) {
     70                if (*s == '\n')
     71                        pl011_uart_sendb(uart, '\r');
     72
     73                pl011_uart_sendb(uart, (uint8_t) *s);
    7274        }
    7375}
    7476
    7577static outdev_operations_t pl011_uart_ops = {
    76         .write = pl011_uart_putuchar,
     78        .write = pl011_uart_write,
    7779        .redraw = NULL,
    7880        .scroll_up = NULL,
  • kernel/genarch/src/fb/fb.c

    r1db4e2ae rc4cfe4c  
    121121        /** Current backbuffer position */
    122122        unsigned int position;
     123
     124        /** Partial character between writes */
     125        mbstate_t mbstate;
    123126} fb_instance_t;
    124127
    125 static void fb_putuchar(outdev_t *, char32_t);
     128static void fb_write(outdev_t *, const char *, size_t);
    126129static void fb_redraw(outdev_t *);
    127130static void fb_scroll_up(outdev_t *);
     
    129132
    130133static outdev_operations_t fbdev_ops = {
    131         .write = fb_putuchar,
     134        .write = fb_write,
    132135        .redraw = fb_redraw,
    133136        .scroll_up = fb_scroll_up,
     
    418421 *
    419422 */
    420 static void fb_putuchar(outdev_t *dev, char32_t ch)
    421 {
    422         fb_instance_t *instance = (fb_instance_t *) dev->data;
    423         spinlock_lock(&instance->lock);
    424 
     423static void _putuchar(fb_instance_t *instance, char32_t ch)
     424{
    425425        switch (ch) {
    426426        case '\n':
    427                 cursor_remove(instance);
    428427                instance->position += instance->cols;
    429428                instance->position -= instance->position % instance->cols;
    430429                break;
    431430        case '\r':
    432                 cursor_remove(instance);
    433431                instance->position -= instance->position % instance->cols;
    434432                break;
    435433        case '\b':
    436                 cursor_remove(instance);
    437434                if (instance->position % instance->cols)
    438435                        instance->position--;
    439436                break;
    440437        case '\t':
    441                 cursor_remove(instance);
    442438                do {
    443439                        glyph_draw(instance, fb_font_glyph(' '),
     
    459455                screen_scroll(instance);
    460456        }
     457}
     458
     459static void fb_write(outdev_t *dev, const char *s, size_t n)
     460{
     461        fb_instance_t *instance = (fb_instance_t *) dev->data;
     462
     463        spinlock_lock(&instance->lock);
     464        cursor_remove(instance);
     465
     466        size_t offset = 0;
     467        char32_t ch;
     468
     469        while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))
     470                _putuchar(instance, ch);
    461471
    462472        cursor_put(instance);
    463 
    464473        spinlock_unlock(&instance->lock);
    465474}
  • kernel/generic/include/console/chardev.h

    r1db4e2ae rc4cfe4c  
    8181/** Output character device operations interface. */
    8282typedef struct {
    83         /** Write character to output. */
    84         void (*write)(struct outdev *, char32_t);
     83        /** Write string to output. */
     84        void (*write)(struct outdev *, const char *, size_t);
    8585
    8686        /** Redraw any previously cached characters. */
  • kernel/generic/include/console/console.h

    r1db4e2ae rc4cfe4c  
    3636#define KERN_CONSOLE_H_
    3737
    38 #include <typedefs.h>
    39 #include <print.h>
    4038#include <console/chardev.h>
    4139#include <synch/spinlock.h>
     
    6664extern void kio_update(void *);
    6765extern void kio_flush(void);
    68 extern void kio_push_char(const char32_t);
    69 SPINLOCK_EXTERN(kio_lock);
     66extern void kio_push_bytes(const char *, size_t);
     67extern 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
     
    7978extern void console_unlock(void);
    8079
     80extern void putstr(const char *s, size_t n);
     81
    8182#endif /* KERN_CONSOLE_H_ */
    8283
  • kernel/generic/include/stdio.h

    r1db4e2ae rc4cfe4c  
    3737
    3838#include <print.h>
    39 #include <putchar.h>
    4039
    4140#endif
  • kernel/generic/src/console/console.c

    r1db4e2ae rc4cfe4c  
    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 */
     42#include <log.h>
    4843#include <panic.h>
    4944#include <preemption.h>
    50 #include <proc/thread.h>
    51 #include <putchar.h>
     45#include <proc/task.h>
    5246#include <stdatomic.h>
    5347#include <stdio.h>
     
    5650#include <synch/mutex.h>
    5751#include <synch/spinlock.h>
    58 #include <synch/waitq.h>
    5952#include <syscall/copy.h>
    6053#include <sysinfo/sysinfo.h>
    61 #include <typedefs.h>
    6254
    6355#define KIO_PAGES    8
    64 #define KIO_LENGTH   (KIO_PAGES * PAGE_SIZE / sizeof(char32_t))
     56#define KIO_LENGTH   (KIO_PAGES * PAGE_SIZE)
    6557
    6658/** Kernel log cyclic buffer */
    67 char32_t kio[KIO_LENGTH] __attribute__((aligned(PAGE_SIZE)));
     59static char kio[KIO_LENGTH];
    6860
    6961/** Kernel log initialized */
     
    7668static MUTEX_INITIALIZE(console_mutex, MUTEX_RECURSIVE);
    7769
    78 /** First kernel log characters */
    79 static size_t kio_start = 0;
    80 
    81 /** Number of valid kernel log characters */
    82 static size_t kio_len = 0;
    83 
    84 /** Number of stored (not printed) kernel log characters */
    85 static size_t kio_stored = 0;
    86 
    87 /** Number of stored kernel log characters for uspace */
    88 static size_t kio_uspace = 0;
     70/** Number of characters written to buffer. Periodically overflows. */
     71static size_t kio_written = 0;
     72
     73/** Number of characters written to output devices. Periodically overflows. */
     74static size_t kio_processed = 0;
     75
     76/** Last notification sent to uspace. */
     77static size_t kio_notified = 0;
    8978
    9079/** Kernel log spinlock */
    91 SPINLOCK_INITIALIZE_NAME(kio_lock, "kio_lock");
    92 
    93 /** Physical memory area used for kio buffer */
    94 static parea_t kio_parea;
     80IRQ_SPINLOCK_INITIALIZE(kio_lock);
     81
     82static IRQ_SPINLOCK_INITIALIZE(flush_lock);
     83
     84static IRQ_SPINLOCK_INITIALIZE(early_mbstate_lock);
     85static mbstate_t early_mbstate;
    9586
    9687static indev_t stdin_sink;
     
    10495};
    10596
    106 static void stdout_write(outdev_t *, char32_t);
     97static void stdout_write(outdev_t *, const char *, size_t);
    10798static void stdout_redraw(outdev_t *);
    10899static void stdout_scroll_up(outdev_t *);
     
    157148}
    158149
    159 static void stdout_write(outdev_t *dev, char32_t ch)
     150static void stdout_write(outdev_t *dev, const char *s, size_t n)
    160151{
    161152        list_foreach(dev->list, link, outdev_t, sink) {
    162153                if ((sink) && (sink->op->write))
    163                         sink->op->write(sink, ch);
     154                        sink->op->write(sink, s, n);
    164155        }
    165156}
     
    190181
    191182/** Initialize kernel logging facility
    192  *
    193  * The shared area contains kernel cyclic buffer. Userspace application may
    194  * be notified on new data with indication of position and size
    195  * of the data within the circular buffer.
    196  *
    197183 */
    198184void kio_init(void)
    199185{
    200         void *faddr = (void *) KA2PA(kio);
    201 
    202         assert((uintptr_t) faddr % FRAME_SIZE == 0);
    203 
    204         ddi_parea_init(&kio_parea);
    205         kio_parea.pbase = (uintptr_t) faddr;
    206         kio_parea.frames = SIZE2FRAMES(sizeof(kio));
    207         kio_parea.unpriv = false;
    208         kio_parea.mapped = false;
    209         ddi_parea_register(&kio_parea);
    210 
    211         sysinfo_set_item_val("kio.faddr", NULL, (sysarg_t) faddr);
    212         sysinfo_set_item_val("kio.pages", NULL, KIO_PAGES);
    213 
    214186        event_set_unmask_callback(EVENT_KIO, kio_update);
    215187        atomic_store(&kio_inited, true);
     
    257229                return;
    258230
    259         spinlock_lock(&kio_lock);
    260 
    261         if (kio_uspace > 0) {
    262                 if (event_notify_3(EVENT_KIO, true, kio_start, kio_len,
    263                     kio_uspace) == EOK)
    264                         kio_uspace = 0;
    265         }
    266 
    267         spinlock_unlock(&kio_lock);
     231        irq_spinlock_lock(&kio_lock, true);
     232
     233        if (kio_notified != kio_written) {
     234                if (event_notify_1(EVENT_KIO, true, kio_written) == EOK)
     235                        kio_notified = kio_written;
     236        }
     237
     238        irq_spinlock_unlock(&kio_lock, true);
    268239}
    269240
     
    278249                return;
    279250
    280         spinlock_lock(&kio_lock);
     251        irq_spinlock_lock(&kio_lock, true);
     252
     253        if (!irq_spinlock_trylock(&flush_lock)) {
     254                /* Someone is currently flushing. */
     255                irq_spinlock_unlock(&kio_lock, true);
     256                return;
     257        }
     258
     259        /* A small-ish local buffer so that we can write to output in chunks. */
     260        char buffer[256];
    281261
    282262        /* Print characters that weren't printed earlier */
    283         while (kio_stored > 0) {
    284                 char32_t tmp = kio[(kio_start + kio_len - kio_stored) % KIO_LENGTH];
    285                 kio_stored--;
     263        while (kio_written != kio_processed) {
     264                size_t offset = kio_processed % KIO_LENGTH;
     265                size_t len = min(kio_written - kio_processed, KIO_LENGTH - offset);
     266                len = min(len, sizeof(buffer));
     267
     268                /* Take out a chunk of the big buffer. */
     269                memcpy(buffer, &kio[offset], len);
     270                kio_processed += len;
    286271
    287272                /*
    288                  * We need to give up the spinlock for
    289                  * the physical operation of writing out
    290                  * the character.
     273                 * We need to give up the spinlock for the physical operation of writing
     274                 * out the buffer.
    291275                 */
    292                 spinlock_unlock(&kio_lock);
    293                 stdout->op->write(stdout, tmp);
    294                 spinlock_lock(&kio_lock);
    295         }
    296 
    297         spinlock_unlock(&kio_lock);
    298 }
    299 
    300 /** Put a character into the output buffer.
    301  *
    302  * The caller is required to hold kio_lock
    303  */
    304 void kio_push_char(const char32_t ch)
    305 {
    306         kio[(kio_start + kio_len) % KIO_LENGTH] = ch;
    307         if (kio_len < KIO_LENGTH)
    308                 kio_len++;
    309         else
    310                 kio_start = (kio_start + 1) % KIO_LENGTH;
    311 
    312         if (kio_stored < kio_len)
    313                 kio_stored++;
    314 
    315         /* The character is stored for uspace */
    316         if (kio_uspace < kio_len)
    317                 kio_uspace++;
    318 }
    319 
    320 void putuchar(const char32_t ch)
     276                irq_spinlock_unlock(&kio_lock, true);
     277                stdout->op->write(stdout, buffer, len);
     278                irq_spinlock_lock(&kio_lock, true);
     279        }
     280
     281        irq_spinlock_unlock(&flush_lock, false);
     282        irq_spinlock_unlock(&kio_lock, true);
     283}
     284
     285void kio_push_bytes(const char *s, size_t n)
     286{
     287        /* Skip the section we know we can't keep. */
     288        if (n > KIO_LENGTH) {
     289                size_t lost = n - KIO_LENGTH;
     290                kio_written += lost;
     291                s += lost;
     292                n -= lost;
     293        }
     294
     295        size_t offset = kio_written % KIO_LENGTH;
     296        if (offset + n > KIO_LENGTH) {
     297                size_t first = KIO_LENGTH - offset;
     298                size_t last = n - first;
     299                memcpy(kio + offset, s, first);
     300                memcpy(kio, s + first, last);
     301        } else {
     302                memcpy(kio + offset, s, n);
     303        }
     304
     305        kio_written += n;
     306}
     307
     308static void early_putstr(const char *s, size_t n)
     309{
     310        irq_spinlock_lock(&early_mbstate_lock, true);
     311
     312        size_t offset = 0;
     313        char32_t c;
     314
     315        while ((c = str_decode_r(s, &offset, n, U_SPECIAL, &early_mbstate)))
     316                early_putuchar(c);
     317
     318        irq_spinlock_unlock(&early_mbstate_lock, true);
     319}
     320
     321void putstr(const char *s, size_t n)
    321322{
    322323        bool ordy = ((stdout) && (stdout->op->write));
    323324
    324         spinlock_lock(&kio_lock);
    325         kio_push_char(ch);
    326         spinlock_unlock(&kio_lock);
     325        irq_spinlock_lock(&kio_lock, true);
     326        kio_push_bytes(s, n);
     327        irq_spinlock_unlock(&kio_lock, true);
    327328
    328329        /* Output stored characters */
     
    340341                 * a no-op on certain hardware configurations.
    341342                 */
    342                 early_putuchar(ch);
    343         }
    344 
    345         /* Force notification on newline */
    346         if (ch == '\n')
     343                early_putstr(s, n);
     344        }
     345
     346        /* Force notification when containing a newline */
     347        if (memchr(s, '\n', n) != NULL)
    347348                kio_update(NULL);
     349}
     350
     351/** Reads up to `size` characters from kio buffer starting at character `at`.
     352 *
     353 * @param size  Maximum number of characters that can be stored in buffer.
     354 *              Values greater than KIO_LENGTH are silently treated as KIO_LENGTH
     355 *              for the purposes of calculating the return value.
     356 * @return Number of characters read. Can be more than `size`.
     357 *         In that case, `size` characters are written to user buffer
     358 *         and the extra amount is the number of characters missed.
     359 */
     360sysarg_t sys_kio_read(uspace_addr_t buf, size_t size, size_t at)
     361{
     362        errno_t rc;
     363        size_t missed = 0;
     364
     365        irq_spinlock_lock(&kio_lock, true);
     366
     367        if (at == kio_written) {
     368                irq_spinlock_unlock(&kio_lock, true);
     369                return 0;
     370        }
     371
     372        size_t readable_chars = kio_written - at;
     373        if (readable_chars > KIO_LENGTH) {
     374                missed = readable_chars - KIO_LENGTH;
     375                readable_chars = KIO_LENGTH;
     376        }
     377
     378        size_t actual_read = min(readable_chars, size);
     379        size_t offset = (kio_written - readable_chars) % KIO_LENGTH;
     380
     381        if (offset + actual_read > KIO_LENGTH) {
     382                size_t first = KIO_LENGTH - offset;
     383                size_t last = actual_read - first;
     384
     385                rc = copy_to_uspace(buf, &kio[offset], first);
     386                if (rc == EOK)
     387                        rc = copy_to_uspace(buf + first, &kio[0], last);
     388        } else {
     389                rc = copy_to_uspace(buf, &kio[offset], actual_read);
     390        }
     391
     392        irq_spinlock_unlock(&kio_lock, true);
     393
     394        if (rc != EOK) {
     395                log(LF_OTHER, LVL_WARN,
     396                    "[%s(%" PRIu64 ")] Terminating due to invalid memory buffer"
     397                    " in SYS_KIO_READ.\n", TASK->name, TASK->taskid);
     398                task_kill_self(true);
     399        }
     400
     401        return actual_read + missed;
    348402}
    349403
  • kernel/generic/src/console/kconsole.c

    r1db4e2ae rc4cfe4c  
    3939 */
    4040
     41#include <adt/list.h>
     42#include <arch.h>
    4143#include <assert.h>
    42 #include <console/kconsole.h>
    43 #include <console/console.h>
    4444#include <console/chardev.h>
    4545#include <console/cmd.h>
     46#include <console/console.h>
     47#include <console/kconsole.h>
    4648#include <console/prompt.h>
     49#include <debug.h>
     50#include <errno.h>
     51#include <halt.h>
     52#include <macros.h>
     53#include <panic.h>
    4754#include <stdio.h>
    48 #include <panic.h>
     55#include <stdlib.h>
     56#include <str.h>
     57#include <symtab.h>
     58#include <sysinfo/sysinfo.h>
    4959#include <typedefs.h>
    50 #include <adt/list.h>
    51 #include <arch.h>
    52 #include <macros.h>
    53 #include <debug.h>
    54 #include <halt.h>
    55 #include <str.h>
    56 #include <sysinfo/sysinfo.h>
    57 #include <symtab.h>
    58 #include <errno.h>
    59 #include <putchar.h>
    60 #include <stdlib.h>
    6160
    6261/** Simple kernel console.
     
    158157
    159158/** Print count times a character */
    160 _NO_TRACE static void print_cc(char32_t ch, size_t count)
    161 {
    162         size_t i;
    163         for (i = 0; i < count; i++)
    164                 putuchar(ch);
     159_NO_TRACE static void print_cc(char ch, size_t count)
     160{
     161        // FIXME: only lock once
     162
     163        for (size_t i = 0; i < count; i++)
     164                putstr(&ch, 1);
    165165}
    166166
     
    347347                if (ch == '\n') {
    348348                        /* Enter */
    349                         putuchar(ch);
     349                        putstr("\n", 1);
    350350                        break;
    351351                }
     
    358358                        if (wstr_remove(current, position - 1)) {
    359359                                position--;
    360                                 putuchar('\b');
     360                                putstr("\b", 1);
    361361                                printf("%ls ", current + position);
    362362                                print_cc('\b', wstr_length(current) - position + 1);
     
    368368                        /* Tab completion */
    369369
    370                         /* Move to the end of the word */
    371                         for (; (current[position] != 0) && (!isspace(current[position]));
    372                             position++)
    373                                 putuchar(current[position]);
     370                        size_t i = position;
     371                        while (current[i] && !isspace(current[i]))
     372                                i++;
     373
     374                        char32_t stash = current[i];
     375                        current[i] = 0;
     376                        printf("%ls", &current[position]);
     377                        current[i] = stash;
     378                        position = i;
    374379
    375380                        /*
     
    430435                         */
    431436                        size_t off = 0;
    432                         size_t i = 0;
    433                         while ((ch = str_decode(tmp, &off, STR_NO_LIMIT)) != 0) {
     437                        for (size_t i = 0; (ch = str_decode(tmp, &off, STR_NO_LIMIT)); i++)
    434438                                if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE))
    435439                                        break;
    436 
    437                                 i++;
    438                         }
    439440
    440441                        if (found > 1) {
     
    466467                        /* Left */
    467468                        if (position > 0) {
    468                                 putuchar('\b');
     469                                putstr("\b", 1);
    469470                                position--;
    470471                        }
     
    475476                        /* Right */
    476477                        if (position < wstr_length(current)) {
    477                                 putuchar(current[position]);
     478                                printf("%lc", current[position]);
    478479                                position++;
    479480                        }
  • kernel/generic/src/log/log.c

    r1db4e2ae rc4cfe4c  
    4646#include <print.h>
    4747#include <printf_core.h>
    48 #include <putchar.h>
    4948#include <stdarg.h>
    5049#include <stdlib.h>
     
    6059
    6160/** Cyclic buffer holding the data for kernel log */
    62 uint8_t log_buffer[LOG_LENGTH] __attribute__((aligned(PAGE_SIZE)));
     61static uint8_t log_buffer[LOG_LENGTH] __attribute__((aligned(PAGE_SIZE)));
    6362
    6463/** Kernel log initialized */
     
    6665
    6766/** Position in the cyclic buffer where the first log entry starts */
    68 size_t log_start = 0;
     67static size_t log_start = 0;
    6968
    7069/** Sum of length of all log entries currently stored in the cyclic buffer */
    71 size_t log_used = 0;
     70static size_t log_used = 0;
    7271
    7372/** Log spinlock */
    74 SPINLOCK_STATIC_INITIALIZE_NAME(log_lock, "log_lock");
     73static IRQ_SPINLOCK_INITIALIZE(log_lock);
    7574
    7675/** Overall count of logged messages, which may overflow as needed */
     
    152151{
    153152        console_lock();
    154         spinlock_lock(&log_lock);
    155         spinlock_lock(&kio_lock);
     153        irq_spinlock_lock(&log_lock, true);
     154        irq_spinlock_lock(&kio_lock, true);
    156155
    157156        log_current_start = (log_start + log_used) % LOG_LENGTH;
     
    179178        log_used += log_current_len;
    180179
    181         kio_push_char('\n');
    182         spinlock_unlock(&kio_lock);
    183         spinlock_unlock(&log_lock);
     180        kio_push_bytes("\n", 1);
     181        irq_spinlock_unlock(&kio_lock, true);
     182        irq_spinlock_unlock(&log_lock, true);
    184183
    185184        /* This has to be called after we released the locks above */
     
    195194                return;
    196195
    197         spinlock_lock(&log_lock);
     196        irq_spinlock_lock(&log_lock, true);
    198197        if (next_for_uspace < log_used)
    199198                event_notify_0(EVENT_KLOG, true);
    200         spinlock_unlock(&log_lock);
     199        irq_spinlock_unlock(&log_lock, true);
    201200}
    202201
    203202static int log_printf_str_write(const char *str, size_t size, void *data)
    204203{
    205         size_t offset = 0;
    206 
    207         while (offset < size)
    208                 kio_push_char(str_decode(str, &offset, size));
    209 
     204        kio_push_bytes(str, size);
    210205        log_append((const uint8_t *)str, size);
    211 
    212206        return EOK;
    213207}
     
    307301                rc = EOK;
    308302
    309                 spinlock_lock(&log_lock);
     303                irq_spinlock_lock(&log_lock, true);
    310304
    311305                while (next_for_uspace < log_used) {
     
    337331                }
    338332
    339                 spinlock_unlock(&log_lock);
     333                irq_spinlock_unlock(&log_lock, true);
    340334
    341335                if (rc != EOK) {
  • kernel/generic/src/printf/vprintf.c

    r1db4e2ae rc4cfe4c  
    3737#include <print.h>
    3838#include <printf_core.h>
    39 #include <putchar.h>
    4039#include <str.h>
    4140#include <synch/spinlock.h>
     
    4443static errno_t vprintf_str_write(const char *str, size_t size, void *data)
    4544{
    46         size_t offset = 0;
    47 
    48         while (offset < size)
    49                 putuchar(str_decode(str, &offset, size));
    50 
     45        putstr(str, size);
    5146        return EOK;
    5247}
     
    5449int puts(const char *str)
    5550{
    56         size_t offset = 0;
    57         size_t chars = 0;
    58         char32_t uc;
    59 
    60         console_lock();
    61 
    62         while ((uc = str_decode(str, &offset, STR_NO_LIMIT)) != 0) {
    63                 putuchar(uc);
    64                 chars++;
    65         }
    66 
    67         putuchar('\n');
    68 
    69         console_unlock();
    70         return chars;
     51        size_t n = str_size(str);
     52        putstr(str, n);
     53        return n;
    7154}
    7255
  • kernel/generic/src/syscall/syscall.c

    r1db4e2ae rc4cfe4c  
    137137
    138138        [SYS_KLOG] = (syshandler_t) sys_klog,
     139        [SYS_KIO_READ] = (syshandler_t) sys_kio_read,
    139140};
    140141
  • kernel/test/print/print4.c

    r1db4e2ae rc4cfe4c  
    5050        }
    5151
    52         TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n");
     52        TPRINTF("\nExtended ASCII characters (160 - 255) using printf(\"%%lc\"):\n");
    5353
    54         for (group = 4; group < 8; group++) {
     54        for (group = 5; group < 8; group++) {
    5555                TPRINTF("%#x: ", group << 5);
    5656
  • 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",
  • uspace/app/trace/syscalls.c

    r1db4e2ae rc4cfe4c  
    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

    r1db4e2ae rc4cfe4c  
    3434 */
    3535
     36#include <abi/syscall.h>
    3637#include <stddef.h>
    3738#include <libc.h>
     
    112113}
    113114
     115size_t kio_read(char *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

    r1db4e2ae rc4cfe4c  
    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(char *buf, size_t n, size_t at);
    5255
    5356/*
Note: See TracChangeset for help on using the changeset viewer.