Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d2cc7e1 in mainline


Ignore:
Timestamp:
2009-03-21T11:26:31Z (12 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master
Children:
0a5116db
Parents:
5b8c75a
Message:

Buffer console output with line granularity. Makes esp. msim/ski console faster. EGA-fb needs fixing.

Location:
uspace
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/tetris/screen.c

    r5b8c75a rd2cc7e1  
    116116{
    117117        console_goto(r, c);
    118 }
    119 
    120 static void fflush(void)
    121 {
    122         console_flush();
    123118}
    124119
     
    275270        if (cur_so)
    276271                resume_normal();
    277         fflush();
     272        fflush(stdout);
    278273}
    279274
  • uspace/app/tetris/tetris.c

    r5b8c75a rd2cc7e1  
    391391                                        scr_msg(key_msg, 0);
    392392                                        scr_msg(msg, 1);
    393         //                              (void) fflush(stdout);
     393                                        (void) fflush(stdout);
    394394                                } while (rwait((struct timeval *)NULL) == -1);
    395395                                scr_msg(msg, 0);
  • uspace/lib/libc/generic/console.c

    r5b8c75a rd2cc7e1  
    3939#include <ipc/console.h>
    4040#include <ipc/services.h>
     41#include <errno.h>
     42#include <string.h>
    4143#include <console.h>
    4244
    4345static int console_phone = -1;
     46
     47/** Size of cbuffer. */
     48#define CBUFFER_SIZE 256
     49
     50/** Buffer for writing characters to the console. */
     51static char cbuffer[CBUFFER_SIZE];
     52
     53/** Pointer to end of cbuffer. */
     54static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
     55
     56/** Pointer to first available field in cbuffer. */
     57static char *cbp = cbuffer;
     58
     59static ssize_t cons_write(const char *buf, size_t nbyte);
     60static void cons_putchar(int c);
     61
     62static void cbuffer_flush(void);
     63static void cbuffer_drain(void);
     64static void cbuffer_putc(int c);
     65
    4466
    4567void console_open(bool blocking)
     
    85107{
    86108        int cons_phone = console_phone_get(true);
     109
     110        cbuffer_drain();
    87111        async_msg_0(cons_phone, CONSOLE_CLEAR);
    88112}
     
    91115{
    92116        int cons_phone = console_phone_get(true);
     117
     118        cbuffer_flush();
    93119        async_msg_2(cons_phone, CONSOLE_GOTO, row, col);
    94120}
     
    96122void console_putchar(int c)
    97123{
     124        cbuffer_putc(c);
     125}
     126
     127/** Write all data from output buffer to the console. */
     128static void cbuffer_flush(void)
     129{
     130        int rc;
     131        int len;
     132
     133        len = cbp - cbuffer;
     134
     135        while (len > 0) {
     136                rc = cons_write(cbuffer, cbp - cbuffer);
     137                if (rc < 0)
     138                        return;
     139
     140                len -= rc;
     141        }
     142
     143        cbp = cbuffer;
     144}
     145
     146/** Drop all data in console output buffer. */
     147static void cbuffer_drain(void)
     148{
     149        cbp = cbuffer;
     150}
     151
     152/** Write one character to the output buffer. */
     153static inline void cbuffer_putc(int c)
     154{
     155        if (cbp == cbuffer_end)
     156                cbuffer_flush();
     157
     158        *cbp++ = c;
     159
     160        if (c == '\n')
     161                cbuffer_flush();
     162}
     163
     164/** Write one character to the console via IPC. */
     165static void cons_putchar(int c)
     166{
    98167        int cons_phone = console_phone_get(true);
    99168        async_msg_1(cons_phone, CONSOLE_PUTCHAR, c);
    100169}
    101170
     171/** Write characters to the console via IPC. */
     172static ssize_t cons_write(const char *buf, size_t nbyte)
     173{
     174        int cons_phone = console_phone_get(true);
     175        ipcarg_t rc;
     176        ipc_call_t answer;
     177        aid_t req;
     178
     179        async_serialize_start();
     180       
     181        req = async_send_0(cons_phone, CONSOLE_WRITE, &answer);
     182        rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte);
     183
     184        if (rc != EOK) {
     185                async_wait_for(req, NULL);
     186                async_serialize_end();
     187                return (ssize_t) rc;
     188        }
     189
     190        async_wait_for(req, &rc);
     191        async_serialize_end();
     192
     193        if (rc == EOK)
     194                return (ssize_t) IPC_GET_ARG1(answer);
     195        else
     196                return -1;
     197}
     198
     199/** Write characters to the console. */
     200ssize_t console_write(const char *buf, size_t nbyte)
     201{
     202        size_t left;
     203
     204        left = nbyte;
     205
     206        while (left > 0) {
     207                cbuffer_putc(*buf++);
     208                --left;
     209        }
     210
     211        return nbyte;
     212}
     213
     214/** Write a NULL-terminated string to the console. */
     215void console_putstr(const char *s)
     216{
     217        size_t len;
     218        ssize_t rc;
     219
     220        len = strlen(s);
     221        while (len > 0) {
     222                rc = console_write(s, len);
     223                if (rc < 0)
     224                        return; /* Error */
     225                s += rc;
     226                len -= rc;
     227        }
     228}
     229
     230/** Flush all output to the console. */
    102231void console_flush(void)
    103232{
    104         int cons_phone = console_phone_get(true);
     233        int cons_phone = console_phone_get(false);
     234
     235        cbuffer_flush();
    105236        async_msg_0(cons_phone, CONSOLE_FLUSH);
    106237}
     
    123254{
    124255        int cons_phone = console_phone_get(true);
     256
     257        cbuffer_flush();
    125258        async_msg_1(cons_phone, CONSOLE_SET_STYLE, style);
    126259}
     
    129262{
    130263        int cons_phone = console_phone_get(true);
     264
     265        cbuffer_flush();
    131266        async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
    132267}
     
    135270{
    136271        int cons_phone = console_phone_get(true);
     272
     273        cbuffer_flush();
    137274        async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
    138275}
     
    141278{
    142279        int cons_phone = console_phone_get(true);
     280
     281        cbuffer_flush();
    143282        async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
    144283}
  • uspace/lib/libc/generic/io/io.c

    r5b8c75a rd2cc7e1  
    9898{
    9999        unsigned char c;
     100
     101        flush_stdout();
    100102        if (read_stdin((void *) &c, 1) == 1)
    101103                return c;
     
    104106}
    105107
     108int fflush(FILE *f)
     109{
     110        (void) f;
     111        return flush_stdout();
     112}
     113
    106114/** @}
    107115 */
  • uspace/lib/libc/generic/io/stream.c

    r5b8c75a rd2cc7e1  
    8181{
    8282        int cons_phone = console_phone_get(false);
     83        int left, rc;
    8384
    8485        if (cons_phone >= 0) {
    8586                int i;
    8687
    87                 for (i = 0; i < count; i++)
    88                         console_putchar(((const char *) buf)[i]);
     88                left = count;
     89                while (left > 0) {
     90                        rc = console_write(buf, left);
     91                        if (rc < 0)
     92                                break;
     93                        buf += rc;
     94                        left -= rc;
     95                }
    8996
    9097                return count;
    9198        } else
    9299                return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count);
     100}
     101
     102int flush_stdout(void)
     103{
     104        console_flush();
     105        return 0;
    93106}
    94107
  • uspace/lib/libc/include/console.h

    r5b8c75a rd2cc7e1  
    4949extern void console_goto(int, int);
    5050extern void console_putchar(int);
     51extern ssize_t console_write(const char *buf, size_t nbyte);
     52extern void console_putstr(const char *s);
    5153extern void console_flush(void);
    5254
  • uspace/lib/libc/include/io/stream.h

    r5b8c75a rd2cc7e1  
    4545extern ssize_t write_stdout(const void *, size_t);
    4646extern ssize_t write_stderr(const void *, size_t);
     47extern int flush_stdout(void);
    4748
    4849#endif
  • uspace/lib/libc/include/ipc/console.h

    r5b8c75a rd2cc7e1  
    4141        CONSOLE_GETKEY = IPC_FIRST_USER_METHOD,
    4242        CONSOLE_PUTCHAR,
     43        CONSOLE_WRITE,
    4344        CONSOLE_CLEAR,
    4445        CONSOLE_GOTO,
  • uspace/lib/libc/include/ipc/fb.h

    r5b8c75a rd2cc7e1  
    4040typedef enum {
    4141        FB_PUTCHAR = IPC_FIRST_USER_METHOD,
     42        FB_WRITE,
    4243        FB_CLEAR,
    4344        FB_GET_CSIZE,
  • uspace/lib/libc/include/stdio.h

    r5b8c75a rd2cc7e1  
    7070extern int puts(const char *);
    7171extern int putchar(int);
     72extern int fflush(FILE *);
    7273
    7374extern int printf(const char *, ...);
  • uspace/srv/console/console.c

    r5b8c75a rd2cc7e1  
    9090                                                 * faster virtual console
    9191                                                 * switching */
     92/** Size of fb_buf. */
     93#define FB_BUF_SIZE 256
     94
     95/** Buffer for sending characters to FB driver. */
     96static char fb_buf[FB_BUF_SIZE];
     97
     98/* Properties of fb_buf data. */
     99static int fb_buf_row;          /**< Row where fb_buf data belong. */
     100static int fb_buf_col;          /**< Column where fb_buf data start. */
     101static int fb_console;          /**< VC to which fb_buf data belong. */
     102int fb_bi = 0;                  /**< Number of valid chars in fb_buf. */
     103
     104/** Size of cwrite_buf. */
     105#define CWRITE_BUF_SIZE 256
     106
     107/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
     108static char cwrite_buf[CWRITE_BUF_SIZE];
    92109
    93110
     
    159176}
    160177
     178/** Write a character vector to FB driver via IPC. */
     179static ssize_t fb_write(const char *buf, size_t nbyte, int row, int col)
     180{
     181        ipcarg_t rc;
     182        ipc_call_t answer;
     183        aid_t req;
     184
     185        async_serialize_start();
     186       
     187        req = async_send_2(fb_info.phone, FB_WRITE, row, col, &answer);
     188        rc = ipc_data_write_start(fb_info.phone, (void *) buf, nbyte);
     189
     190        if (rc != EOK) {
     191                async_wait_for(req, NULL);
     192                async_serialize_end();
     193                return (ssize_t) rc;
     194        }
     195
     196        async_wait_for(req, &rc);
     197        async_serialize_end();
     198
     199        if (rc == EOK)
     200                return (ssize_t) IPC_GET_ARG1(answer);
     201        else
     202                return -1;
     203}
     204
     205/** Flush buffered characters to FB. */
     206static void fb_buf_flush(void)
     207{
     208        screenbuffer_t *scr;
     209        int i;
     210
     211        scr = &(connections[fb_console].screenbuffer);
     212
     213        if (fb_bi > 0) {
     214                if (fb_write(fb_buf, fb_bi, fb_buf_row, fb_buf_col) < 0) {
     215                        /* Try falling back to char-by-char. */
     216                        for (i = 0; i < fb_bi; i++) {
     217                                async_msg_3(fb_info.phone, FB_PUTCHAR, fb_buf[i],
     218                                    fb_buf_row, fb_buf_col + i);
     219                        }
     220                }
     221                fb_bi = 0;
     222        }
     223}
     224
     225/** Print a character to the active VC with buffering. */
    161226static void prtchr(char c, int row, int col)
    162227{
    163         async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
     228        if (fb_bi >= FB_BUF_SIZE)
     229                fb_buf_flush();
     230
     231        if (fb_bi == 0) {
     232                fb_buf_row = row;
     233                fb_buf_col = col;
     234                fb_console = active_console;
     235        }
     236
     237        fb_buf[fb_bi++] = c;
    164238}
    165239
     
    170244static void write_char(int console, char key)
    171245{
     246        bool flush_cursor = false;
    172247        screenbuffer_t *scr = &(connections[console].screenbuffer);
    173        
     248
    174249        switch (key) {
    175250        case '\n':
     251                fb_buf_flush();
     252                flush_cursor = true;
    176253                scr->position_y++;
    177254                scr->position_x = 0;
    178255                break;
    179256        case '\r':
     257                fb_buf_flush();
    180258                break;
    181259        case '\t':
     260                fb_buf_flush();
    182261                scr->position_x += 8;
    183262                scr->position_x -= scr->position_x % 8;
    184263                break;
    185264        case '\b':
     265                fb_buf_flush();
    186266                if (scr->position_x == 0)
    187267                        break;
     
    198278                scr->position_x++;
    199279        }
    200        
    201         scr->position_y += (scr->position_x >= scr->size_x);
     280
     281        if (scr->position_x >= scr->size_x) {
     282                fb_buf_flush();
     283                flush_cursor = true;
     284                scr->position_y++;
     285        }
    202286       
    203287        if (scr->position_y >= scr->size_y) {
     
    208292                        async_msg_1(fb_info.phone, FB_SCROLL, 1);
    209293        }
    210        
     294
    211295        scr->position_x = scr->position_x % scr->size_x;
    212        
    213         if (console == active_console)
     296
     297        if (console == active_console && flush_cursor)
    214298                curs_goto(scr->position_y, scr->position_x);
    215        
    216299}
    217300
     
    226309        if (newcons == active_console)
    227310                return;
    228        
     311
     312        fb_buf_flush();
     313
    229314        if (newcons == KERNEL_CONSOLE) {
    230315                async_serialize_start();
     
    361446}
    362447
     448/** Handle CONSOLE_WRITE call. */
     449static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request)
     450{
     451        ipc_callid_t callid;
     452        size_t len;
     453        size_t i;
     454
     455        if (!ipc_data_write_receive(&callid, &len)) {
     456                ipc_answer_0(callid, EINVAL);
     457                ipc_answer_0(rid, EINVAL);
     458        }
     459
     460        if (len > CWRITE_BUF_SIZE)
     461                len = CWRITE_BUF_SIZE;
     462
     463        (void) ipc_data_write_finalize(callid, cwrite_buf, len);
     464
     465        for (i = 0; i < len; i++) {
     466                write_char(consnum, cwrite_buf[i]);
     467        }
     468
     469        gcons_notify_char(consnum);
     470        ipc_answer_1(rid, EOK, len);
     471}
     472
    363473/** Default thread for new connections */
    364474static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
     
    412522                        gcons_notify_char(consnum);
    413523                        break;
     524                case CONSOLE_WRITE:
     525                        cons_write(consnum, callid, &call);
     526                        continue;
    414527                case CONSOLE_CLEAR:
    415528                        /* Send message to fb */
     
    422535                        break;
    423536                case CONSOLE_GOTO:
     537                        fb_buf_flush();
    424538                        screenbuffer_goto(&conn->screenbuffer,
    425539                            IPC_GET_ARG2(call), IPC_GET_ARG1(call));
     
    433547                        break;
    434548                case CONSOLE_FLUSH:
     549                        fb_buf_flush();
    435550                        if (consnum == active_console)
    436551                                async_req_0_0(fb_info.phone, FB_FLUSH);
    437552                        break;
    438553                case CONSOLE_SET_STYLE:
     554                        fb_buf_flush();
    439555                        arg1 = IPC_GET_ARG1(call);
    440556                        screenbuffer_set_style(&conn->screenbuffer, arg1);
     
    443559                        break;
    444560                case CONSOLE_SET_COLOR:
     561                        fb_buf_flush();
    445562                        arg1 = IPC_GET_ARG1(call);
    446563                        arg2 = IPC_GET_ARG2(call);
     
    452569                        break;
    453570                case CONSOLE_SET_RGB_COLOR:
     571                        fb_buf_flush();
    454572                        arg1 = IPC_GET_ARG1(call);
    455573                        arg2 = IPC_GET_ARG2(call);
     
    460578                        break;
    461579                case CONSOLE_CURSOR_VISIBILITY:
     580                        fb_buf_flush();
    462581                        arg1 = IPC_GET_ARG1(call);
    463582                        conn->screenbuffer.is_cursor_visible = arg1;
  • uspace/srv/fb/ega.c

    r5b8c75a rd2cc7e1  
    360360
    361361                default:
    362                         retval = ENOENT;
     362                        retval = EINVAL;
    363363                }
    364364                ipc_answer_0(callid, retval);
  • uspace/srv/fb/fb.c

    r5b8c75a rd2cc7e1  
    14721472        return rgb_from_idx(&vport->attr, fg_color, bg_color, flags);
    14731473}
     1474
     1475#define FB_WRITE_BUF_SIZE 256
     1476static char fb_write_buf[FB_WRITE_BUF_SIZE];
     1477
     1478static void fb_write(viewport_t *vport, ipc_callid_t rid, ipc_call_t *request)
     1479{
     1480        int row, col;
     1481        ipc_callid_t callid;
     1482        size_t len;
     1483        size_t i;
     1484
     1485        row = IPC_GET_ARG1(*request);
     1486        col = IPC_GET_ARG2(*request);
     1487
     1488        if ((col >= vport->cols) || (row >= vport->rows)) {
     1489                ipc_answer_0(callid, EINVAL);
     1490                ipc_answer_0(rid, EINVAL);
     1491                return;
     1492        }
     1493
     1494        if (!ipc_data_write_receive(&callid, &len)) {
     1495                ipc_answer_0(callid, EINVAL);
     1496                ipc_answer_0(rid, EINVAL);
     1497                return;
     1498        }
     1499
     1500        if (len > FB_WRITE_BUF_SIZE)
     1501                len = FB_WRITE_BUF_SIZE;
     1502        if (len >= vport->cols - col)
     1503                len = vport->cols - col;
     1504
     1505        (void) ipc_data_write_finalize(callid, fb_write_buf, len);
     1506
     1507        for (i = 0; i < len; i++) {
     1508                draw_char(vport, fb_write_buf[i], col++, row);
     1509        }
     1510
     1511        ipc_answer_1(rid, EOK, len);
     1512}
     1513
    14741514
    14751515/** Function for handling connections to FB
     
    15471587                        /* Message already answered */
    15481588                        continue;
     1589                case FB_WRITE:
     1590                        fb_write(vport, callid, &call);
     1591                       
     1592                        /* Message already answered */
     1593                        continue;
    15491594                case FB_CLEAR:
    15501595                        vport_clear(vport);
  • uspace/srv/fb/serial_console.c

    r5b8c75a rd2cc7e1  
    244244}
    245245
     246int lastcol = 0;
     247int lastrow = 0;
     248
     249#define FB_WRITE_BUF_SIZE 256
     250static char fb_write_buf[FB_WRITE_BUF_SIZE];
     251
     252static void fb_write(ipc_callid_t rid, ipc_call_t *request)
     253{
     254        int row, col;
     255        ipc_callid_t callid;
     256        size_t len;
     257        size_t i;
     258
     259        row = IPC_GET_ARG1(*request);
     260        col = IPC_GET_ARG2(*request);
     261
     262        if ((col >= scr_width) || (row >= scr_height)) {
     263                ipc_answer_0(callid, EINVAL);
     264                ipc_answer_0(rid, EINVAL);
     265                return;
     266        }
     267
     268        if (!ipc_data_write_receive(&callid, &len)) {
     269                ipc_answer_0(callid, EINVAL);
     270                ipc_answer_0(rid, EINVAL);
     271                return;
     272        }
     273
     274        if (len > FB_WRITE_BUF_SIZE)
     275                len = FB_WRITE_BUF_SIZE;
     276        if (len >= scr_width - col)
     277                len = scr_width - col;
     278
     279        (void) ipc_data_write_finalize(callid, fb_write_buf, len);
     280
     281        if ((lastcol != col) || (lastrow != row))
     282                serial_goto(row, col);
     283
     284        for (i = 0; i < len; i++) {
     285                (*putc_function)(fb_write_buf[i]);
     286        }
     287
     288        lastcol = col + len;
     289        lastrow = row;
     290
     291        ipc_answer_1(rid, EOK, len);
     292}
     293
    246294/**
    247295 * Main function of the thread serving client connections.
     
    256304
    257305        char c;
    258         int lastcol = 0;
    259         int lastrow = 0;
    260306        int newcol;
    261307        int newrow;
     
    318364                        retval = 0;
    319365                        break;
     366                case FB_WRITE:
     367                        fb_write(callid, &call);
     368                       
     369                        /* Message already answered */
     370                        continue;
    320371                case FB_CURSOR_GOTO:
    321372                        newrow = IPC_GET_ARG1(call);
Note: See TracChangeset for help on using the changeset viewer.