mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +00:00 
			
		
		
		
	Add some simple write buffering to LibC's stdio.
Plumb it all the way to the VirtualConsole. Also fix /bin/cat to write() the whole chunks we get from read() directly to stdout.
This commit is contained in:
		
							parent
							
								
									e287f8ef3a
								
							
						
					
					
						commit
						da3857b0c2
					
				
					 10 changed files with 42 additions and 22 deletions
				
			
		|  | @ -29,15 +29,19 @@ | ||||||
| #define VALIDATE_USER_READ(b, s) \ | #define VALIDATE_USER_READ(b, s) \ | ||||||
|     do { \ |     do { \ | ||||||
|         LinearAddress laddr((dword)(b)); \ |         LinearAddress laddr((dword)(b)); \ | ||||||
|         if (!validate_user_read(laddr) || !validate_user_read(laddr.offset((s) - 1))) \ |         if (!validate_user_read(laddr) || !validate_user_read(laddr.offset((s) - 1))) { \ | ||||||
|  |             dbgprintf("Bad read address passed to syscall: %p +%u\n", laddr.get(), (s)); \ | ||||||
|             return -EFAULT; \ |             return -EFAULT; \ | ||||||
|  |         } \ | ||||||
|     } while(0) |     } while(0) | ||||||
| 
 | 
 | ||||||
| #define VALIDATE_USER_WRITE(b, s) \ | #define VALIDATE_USER_WRITE(b, s) \ | ||||||
|     do { \ |     do { \ | ||||||
|         LinearAddress laddr((dword)(b)); \ |         LinearAddress laddr((dword)(b)); \ | ||||||
|         if (!validate_user_write(laddr) || !validate_user_write(laddr.offset((s) - 1))) \ |         if (!validate_user_write(laddr) || !validate_user_write(laddr.offset((s) - 1))) { \ | ||||||
|  |             dbgprintf("Bad write address passed to syscall: %p +%u\n", laddr.get(), (s)); \ | ||||||
|             return -EFAULT; \ |             return -EFAULT; \ | ||||||
|  |         } \ | ||||||
|     } while(0) |     } while(0) | ||||||
| 
 | 
 | ||||||
| static const DWORD defaultStackSize = 16384; | static const DWORD defaultStackSize = 16384; | ||||||
|  |  | ||||||
|  | @ -26,8 +26,7 @@ ssize_t TTY::read(byte* buffer, size_t size) | ||||||
| 
 | 
 | ||||||
| ssize_t TTY::write(const byte* buffer, size_t size) | ssize_t TTY::write(const byte* buffer, size_t size) | ||||||
| { | { | ||||||
|     for (size_t i = 0; i < size; ++i) |     onTTYWrite(buffer, size); | ||||||
|         onTTYWrite(buffer[i]); |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ protected: | ||||||
|     TTY(unsigned major, unsigned minor); |     TTY(unsigned major, unsigned minor); | ||||||
|     void emit(byte); |     void emit(byte); | ||||||
| 
 | 
 | ||||||
|     virtual void onTTYWrite(byte) = 0; |     virtual void onTTYWrite(const byte*, size_t) = 0; | ||||||
| 
 | 
 | ||||||
|     void interrupt(); |     void interrupt(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -320,7 +320,6 @@ void VirtualConsole::put_character_at(unsigned row, unsigned column, byte ch) | ||||||
| 
 | 
 | ||||||
| void VirtualConsole::on_char(byte ch, bool shouldEmit) | void VirtualConsole::on_char(byte ch, bool shouldEmit) | ||||||
| { | { | ||||||
|     InterruptDisabler disabler; |  | ||||||
|     if (shouldEmit) |     if (shouldEmit) | ||||||
|         emit(ch); |         emit(ch); | ||||||
| 
 | 
 | ||||||
|  | @ -397,15 +396,18 @@ void VirtualConsole::onKeyPress(Keyboard::Key key) | ||||||
| 
 | 
 | ||||||
| void VirtualConsole::onConsoleReceive(byte ch) | void VirtualConsole::onConsoleReceive(byte ch) | ||||||
| { | { | ||||||
|  |     InterruptDisabler disabler; | ||||||
|     auto old_attribute = m_current_attribute; |     auto old_attribute = m_current_attribute; | ||||||
|     m_current_attribute = 0x03; |     m_current_attribute = 0x03; | ||||||
|     on_char(ch, false); |     on_char(ch, false); | ||||||
|     m_current_attribute = old_attribute; |     m_current_attribute = old_attribute; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void VirtualConsole::onTTYWrite(byte ch) | void VirtualConsole::onTTYWrite(const byte* data, size_t size) | ||||||
| { | { | ||||||
|     on_char(ch, false); |     InterruptDisabler disabler; | ||||||
|  |     for (size_t i = 0; i < size; ++i) | ||||||
|  |         on_char(data[i], false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| String VirtualConsole::ttyName() const | String VirtualConsole::ttyName() const | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ private: | ||||||
|     virtual void onConsoleReceive(byte) override; |     virtual void onConsoleReceive(byte) override; | ||||||
| 
 | 
 | ||||||
|     // ^TTY
 |     // ^TTY
 | ||||||
|     virtual void onTTYWrite(byte) override; |     virtual void onTTYWrite(const byte*, size_t) override; | ||||||
|     virtual String ttyName() const override; |     virtual String ttyName() const override; | ||||||
| 
 | 
 | ||||||
|     void set_active(bool); |     void set_active(bool); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
| #include <Kernel/Syscall.h> | #include <Kernel/Syscall.h> | ||||||
| #include <AK/StringImpl.h> | #include <AK/StringImpl.h> | ||||||
| 
 | 
 | ||||||
|  | @ -20,6 +21,8 @@ extern "C" int _start() | ||||||
| 
 | 
 | ||||||
|     errno = 0; |     errno = 0; | ||||||
| 
 | 
 | ||||||
|  |     memset(__default_streams, 0, sizeof(__default_streams)); | ||||||
|  | 
 | ||||||
|     __default_streams[0].fd = 0; |     __default_streams[0].fd = 0; | ||||||
|     stdin = &__default_streams[0]; |     stdin = &__default_streams[0]; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,7 +28,11 @@ int fflush(FILE* stream) | ||||||
|     // FIXME: Implement buffered streams, duh.
 |     // FIXME: Implement buffered streams, duh.
 | ||||||
|     if (!stream) |     if (!stream) | ||||||
|         return -EBADF; |         return -EBADF; | ||||||
|     return 0; |     if (!stream->write_buffer_index) | ||||||
|  |         return 0; | ||||||
|  |     int rc = write(stream->fd, stream->write_buffer, stream->write_buffer_index); | ||||||
|  |     stream->write_buffer_index = 0; | ||||||
|  |     return rc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char* fgets(char* buffer, int size, FILE* stream) | char* fgets(char* buffer, int size, FILE* stream) | ||||||
|  | @ -71,7 +75,10 @@ int getchar() | ||||||
| int fputc(int ch, FILE* stream) | int fputc(int ch, FILE* stream) | ||||||
| { | { | ||||||
|     assert(stream); |     assert(stream); | ||||||
|     write(stream->fd, &ch, 1); |     assert(stream->write_buffer_index < __STDIO_FILE_BUFFER_SIZE); | ||||||
|  |     stream->write_buffer[stream->write_buffer_index++] = ch; | ||||||
|  |     if (ch == '\n' || stream->write_buffer_index >= __STDIO_FILE_BUFFER_SIZE) | ||||||
|  |         fflush(stream); | ||||||
|     if (stream->eof) |     if (stream->eof) | ||||||
|         return EOF; |         return EOF; | ||||||
|     return (byte)ch; |     return (byte)ch; | ||||||
|  | @ -99,7 +106,7 @@ int fputs(const char* s, FILE* stream) | ||||||
| 
 | 
 | ||||||
| int puts(const char* s) | int puts(const char* s) | ||||||
| { | { | ||||||
|     fputs(s, stdout); |     return fputs(s, stdout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void clearerr(FILE* stream) | void clearerr(FILE* stream) | ||||||
|  | @ -128,6 +135,7 @@ size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) | ||||||
| size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) | size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) | ||||||
| { | { | ||||||
|     assert(stream); |     assert(stream); | ||||||
|  |     fflush(stream); | ||||||
|     ssize_t nwritten = write(stream->fd, ptr, nmemb * size); |     ssize_t nwritten = write(stream->fd, ptr, nmemb * size); | ||||||
|     if (nwritten < 0) |     if (nwritten < 0) | ||||||
|         return 0; |         return 0; | ||||||
|  | @ -162,7 +170,7 @@ static void sys_putch(char*&, char ch) | ||||||
| static FILE* __current_stream = nullptr; | static FILE* __current_stream = nullptr; | ||||||
| static void stream_putch(char*&, char ch) | static void stream_putch(char*&, char ch) | ||||||
| { | { | ||||||
|     write(__current_stream->fd, &ch, 1); |     fputc(ch, __current_stream); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int fprintf(FILE* fp, const char* fmt, ...) | int fprintf(FILE* fp, const char* fmt, ...) | ||||||
|  | @ -211,9 +219,8 @@ FILE* fopen(const char* pathname, const char* mode) | ||||||
|     if (fd < 0) |     if (fd < 0) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     auto* fp = (FILE*)malloc(sizeof(FILE)); |     auto* fp = (FILE*)malloc(sizeof(FILE)); | ||||||
|  |     memset(fp, 0, sizeof(FILE)); | ||||||
|     fp->fd = fd; |     fp->fd = fd; | ||||||
|     fp->eof = false; |  | ||||||
|     fp->error = 0; |  | ||||||
|     return fp; |     return fp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -223,9 +230,8 @@ FILE* fdopen(int fd, const char* mode) | ||||||
|     if (fd < 0) |     if (fd < 0) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     auto* fp = (FILE*)malloc(sizeof(FILE)); |     auto* fp = (FILE*)malloc(sizeof(FILE)); | ||||||
|  |     memset(fp, 0, sizeof(FILE)); | ||||||
|     fp->fd = fd; |     fp->fd = fd; | ||||||
|     fp->eof = false; |  | ||||||
|     fp->error = 0; |  | ||||||
|     return fp; |     return fp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,8 +4,7 @@ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| 
 | 
 | ||||||
| __BEGIN_DECLS | __BEGIN_DECLS | ||||||
| 
 |  #ifndef EOF | ||||||
| #ifndef EOF |  | ||||||
| #define EOF (-1) | #define EOF (-1) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -13,10 +12,16 @@ __BEGIN_DECLS | ||||||
| #define SEEK_CUR 1 | #define SEEK_CUR 1 | ||||||
| #define SEEK_END 2 | #define SEEK_END 2 | ||||||
| 
 | 
 | ||||||
|  | #define __STDIO_FILE_BUFFER_SIZE 128 | ||||||
|  | 
 | ||||||
| struct __STDIO_FILE { | struct __STDIO_FILE { | ||||||
|     int fd; |     int fd; | ||||||
|     int eof; |     int eof; | ||||||
|     int error; |     int error; | ||||||
|  |     char read_buffer[__STDIO_FILE_BUFFER_SIZE]; | ||||||
|  |     size_t read_buffer_index; | ||||||
|  |     char write_buffer[__STDIO_FILE_BUFFER_SIZE]; | ||||||
|  |     size_t write_buffer_index; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct __STDIO_FILE FILE; | typedef struct __STDIO_FILE FILE; | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ int main(int argc, char** argv) | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     for (;;) { |     for (;;) { | ||||||
|         char buf[1024]; |         char buf[4096]; | ||||||
|         ssize_t nread = read(fd, buf, sizeof(buf)); |         ssize_t nread = read(fd, buf, sizeof(buf)); | ||||||
|         if (nread == 0) |         if (nread == 0) | ||||||
|             break; |             break; | ||||||
|  | @ -25,8 +25,7 @@ int main(int argc, char** argv) | ||||||
|             printf("read() error: %s\n", strerror(errno)); |             printf("read() error: %s\n", strerror(errno)); | ||||||
|             return 2; |             return 2; | ||||||
|         } |         } | ||||||
|         for (ssize_t i = 0; i < nread; ++i) |         write(1, buf, nread); | ||||||
|             putchar(buf[i]); |  | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ static void prompt() | ||||||
|         printf("# "); |         printf("# "); | ||||||
|     else |     else | ||||||
|         printf("\033[31;1m%s\033[0m@\033[37;1m%s\033[0m:\033[32;1m%s\033[0m$> ", g->username.characters(), g->hostname, g->cwd.characters()); |         printf("\033[31;1m%s\033[0m@\033[37;1m%s\033[0m:\033[32;1m%s\033[0m$> ", g->username.characters(), g->hostname, g->cwd.characters()); | ||||||
|  |     fflush(stdout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int sh_pwd(int, const char**) | static int sh_pwd(int, const char**) | ||||||
|  | @ -347,6 +348,7 @@ int main(int, char**) | ||||||
|         } |         } | ||||||
|         for (ssize_t i = 0; i < nread; ++i) { |         for (ssize_t i = 0; i < nread; ++i) { | ||||||
|             putchar(keybuf[i]); |             putchar(keybuf[i]); | ||||||
|  |             fflush(stdout); | ||||||
|             if (keybuf[i] != '\n') { |             if (keybuf[i] != '\n') { | ||||||
|                 linebuf[linedx++] = keybuf[i]; |                 linebuf[linedx++] = keybuf[i]; | ||||||
|                 linebuf[linedx] = '\0'; |                 linebuf[linedx] = '\0'; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling