Changeset 39e1b9a in mainline


Ignore:
Timestamp:
2025-04-17T15:37:05Z (5 days ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
250a435
Parents:
690ad20
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-04-14 16:54:54)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-04-17 15:37:05)
Message:

Convert console output devices to batch printing

Location:
kernel
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/drivers/ega/ega.c

    r690ad20 r39e1b9a  
    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

    r690ad20 r39e1b9a  
    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

    r690ad20 r39e1b9a  
    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

    r690ad20 r39e1b9a  
    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

    r690ad20 r39e1b9a  
    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/src/console/console.c

    r690ad20 r39e1b9a  
    8080IRQ_SPINLOCK_INITIALIZE(kio_lock);
    8181
     82static IRQ_SPINLOCK_INITIALIZE(flush_lock);
     83
    8284static IRQ_SPINLOCK_INITIALIZE(early_mbstate_lock);
    8385static mbstate_t early_mbstate;
     
    9395};
    9496
    95 static void stdout_write(outdev_t *, char32_t);
     97static void stdout_write(outdev_t *, const char *, size_t);
    9698static void stdout_redraw(outdev_t *);
    9799static void stdout_scroll_up(outdev_t *);
     
    146148}
    147149
    148 static void stdout_write(outdev_t *dev, char32_t ch)
     150static void stdout_write(outdev_t *dev, const char *s, size_t n)
    149151{
    150152        list_foreach(dev->list, link, outdev_t, sink) {
    151153                if ((sink) && (sink->op->write))
    152                         sink->op->write(sink, ch);
     154                        sink->op->write(sink, s, n);
    153155        }
    154156}
     
    249251        irq_spinlock_lock(&kio_lock, true);
    250252
    251         static mbstate_t mbstate;
     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];
    252261
    253262        /* Print characters that weren't printed earlier */
     
    255264                size_t offset = kio_processed % KIO_LENGTH;
    256265                size_t len = min(kio_written - kio_processed, KIO_LENGTH - offset);
    257                 size_t bytes = 0;
    258 
    259                 char32_t ch = str_decode_r(&kio[offset], &bytes, len, U'�', &mbstate);
    260                 assert(bytes <= 4);
    261                 kio_processed += bytes;
     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;
    262271
    263272                /*
    264                  * We need to give up the spinlock for
    265                  * the physical operation of writing out
    266                  * the character.
     273                 * We need to give up the spinlock for the physical operation of writing
     274                 * out the buffer.
    267275                 */
    268276                irq_spinlock_unlock(&kio_lock, true);
    269                 stdout->op->write(stdout, ch);
     277                stdout->op->write(stdout, buffer, len);
    270278                irq_spinlock_lock(&kio_lock, true);
    271279        }
    272280
     281        irq_spinlock_unlock(&flush_lock, false);
    273282        irq_spinlock_unlock(&kio_lock, true);
    274283}
Note: See TracChangeset for help on using the changeset viewer.