Messages in this thread Patch in this message | | | From | (Brad Pepers) | Subject | Console speedup patch | Date | Wed, 4 Sep 1996 11:01:39 -0600 (MDT) |
| |
Here is a patch I've made to implement the put_char() and flush_chars() routines for the console device. The result is that con_write is not called for each character and the console output is quite a bit faster. I wrote a test program to output blocks of 'a's to the screen and the result on 8K blocks is that the new console code is 5.9 times faster (423280 chars/sec vrs 71813 chars/sec). Also the speedup seems fairly consistant in that using 4K blocks its also about 6 times faster.
I had noticed when installing Caldera (which uses a text/color/boxes/... kind of install) that even with the Pentium 120 I was installing on I could watch the redrawing of the screen as Caldera was installing the packages. It looked kind of strange and made the system look slow. I hope this patch will fix that kind of thing. Let me know if this patch works well for you!
--- linux/drivers/char/console.c.orig Tue Sep 3 16:25:46 1996 +++ linux/drivers/char/console.c Wed Sep 4 01:25:26 1996 @@ -308,7 +308,7 @@ if (i >= MAX_NR_CONSOLES) return -ENXIO; if (!vc_cons[i].d) { - long p, q; + long p, q, b; /* prevent users from taking too much memory */ if (i >= MAX_NR_USER_CONSOLES && !suser()) @@ -325,10 +325,18 @@ kfree_s((char *) q, video_screen_size); return -ENOMEM; } + b = get_free_page(GFP_KERNEL); + if (!b) { + kfree_s((char *) p, structsize); + kfree_s((char *) q, video_screen_size); + return -ENOMEM; + } vc_cons[i].d = (struct vc_data *) p; p += sizeof(struct vc_data); vt_cons[i] = (struct vt_struct *) p; + vt_cons[i]->xmit_buf = (unsigned char *)b; + vt_cons[i]->xmit_cnt = 0; vc_scrbuf[i] = (unsigned short *) q; vc_cons[i].d->vc_kmalloced = 1; vc_cons[i].d->vc_screenbuf_size = video_screen_size; @@ -1828,16 +1836,51 @@ return n; } +static void con_put_char(struct tty_struct * tty, unsigned char ch) +{ + struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + unsigned long flags; + + if (!tty || !vt || !vt->xmit_buf) + return; + + save_flags(flags); cli(); + vt->xmit_buf[vt->xmit_cnt++] = ch; + if (vt->xmit_cnt >= CON_XMIT_SIZE) { + con_write(tty, 0, vt->xmit_buf, vt->xmit_cnt); + vt->xmit_cnt = 0; + } + + restore_flags(flags); +} + +static void con_flush_chars(struct tty_struct *tty) +{ + struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + unsigned long flags; + + if (vt->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !vt->xmit_buf) + return; + + save_flags(flags); cli(); + con_write(tty, 0, vt->xmit_buf, vt->xmit_cnt); + vt->xmit_cnt = 0; + restore_flags(flags); +} + static int con_write_room(struct tty_struct *tty) { - if (tty->stopped) - return 0; - return 4096; /* No limit, really; we're not buffering */ + struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + + return CON_XMIT_SIZE - vt->xmit_cnt; } static int con_chars_in_buffer(struct tty_struct *tty) { - return 0; /* we're not buffering */ + struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + + return vt->xmit_cnt; } void poke_blanked_console(void) @@ -2013,6 +2056,8 @@ console_driver.open = con_open; console_driver.write = con_write; + console_driver.put_char = con_put_char; + console_driver.flush_chars = con_flush_chars; console_driver.write_room = con_write_room; console_driver.chars_in_buffer = con_chars_in_buffer; console_driver.ioctl = vt_ioctl; @@ -2050,6 +2095,9 @@ kmem_start += sizeof(struct vc_data); vt_cons[currcons] = (struct vt_struct *) kmem_start; kmem_start += sizeof(struct vt_struct); + vt_cons[currcons]->xmit_buf = (unsigned char *) kmem_start; + vt_cons[currcons]->xmit_cnt = 0; + kmem_start += CON_XMIT_SIZE; vc_scrbuf[currcons] = (unsigned short *) kmem_start; kmem_start += video_screen_size; kmalloced = 0; --- linux/drivers/char/vt_kern.h.orig Tue Sep 3 16:25:53 1996 +++ linux/drivers/char/vt_kern.h Wed Sep 4 01:26:13 1996 @@ -18,6 +18,11 @@ */ #define BROKEN_GRAPHICS_PROGRAMS 1 +/* + * The console transmit buffer is set to one page (is this always 4096?) + */ +#define CON_XMIT_SIZE PAGE_SIZE + extern struct vt_struct { int vc_num; /* The console number */ unsigned char vc_mode; /* KD_TEXT, ... */ @@ -28,6 +33,9 @@ int vt_pid; int vt_newvt; struct wait_queue *paste_wait; + + unsigned char *xmit_buf; + int xmit_cnt; } *vt_cons[MAX_NR_CONSOLES]; void (*kd_mksound)(unsigned int hz, unsigned int ticks); ====================================================================== Brad Pepers Proud supporter of Linux and Ramparts Management Group Ltd. Caldera in Canada! ramparts@agt.net http://www.agt.net/public/ramparts Linux rules!
| |