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) \ | ||||
|     do { \ | ||||
|         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; \ | ||||
|         } \ | ||||
|     } while(0) | ||||
| 
 | ||||
| #define VALIDATE_USER_WRITE(b, s) \ | ||||
|     do { \ | ||||
|         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; \ | ||||
|         } \ | ||||
|     } while(0) | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|     for (size_t i = 0; i < size; ++i) | ||||
|         onTTYWrite(buffer[i]); | ||||
|     onTTYWrite(buffer, size); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ protected: | |||
|     TTY(unsigned major, unsigned minor); | ||||
|     void emit(byte); | ||||
| 
 | ||||
|     virtual void onTTYWrite(byte) = 0; | ||||
|     virtual void onTTYWrite(const byte*, size_t) = 0; | ||||
| 
 | ||||
|     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) | ||||
| { | ||||
|     InterruptDisabler disabler; | ||||
|     if (shouldEmit) | ||||
|         emit(ch); | ||||
| 
 | ||||
|  | @ -397,15 +396,18 @@ void VirtualConsole::onKeyPress(Keyboard::Key key) | |||
| 
 | ||||
| void VirtualConsole::onConsoleReceive(byte ch) | ||||
| { | ||||
|     InterruptDisabler disabler; | ||||
|     auto old_attribute = m_current_attribute; | ||||
|     m_current_attribute = 0x03; | ||||
|     on_char(ch, false); | ||||
|     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 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ private: | |||
|     virtual void onConsoleReceive(byte) override; | ||||
| 
 | ||||
|     // ^TTY
 | ||||
|     virtual void onTTYWrite(byte) override; | ||||
|     virtual void onTTYWrite(const byte*, size_t) override; | ||||
|     virtual String ttyName() const override; | ||||
| 
 | ||||
|     void set_active(bool); | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <Kernel/Syscall.h> | ||||
| #include <AK/StringImpl.h> | ||||
| 
 | ||||
|  | @ -20,6 +21,8 @@ extern "C" int _start() | |||
| 
 | ||||
|     errno = 0; | ||||
| 
 | ||||
|     memset(__default_streams, 0, sizeof(__default_streams)); | ||||
| 
 | ||||
|     __default_streams[0].fd = 0; | ||||
|     stdin = &__default_streams[0]; | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,7 +28,11 @@ int fflush(FILE* stream) | |||
|     // FIXME: Implement buffered streams, duh.
 | ||||
|     if (!stream) | ||||
|         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) | ||||
|  | @ -71,7 +75,10 @@ int getchar() | |||
| int fputc(int ch, FILE* 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) | ||||
|         return EOF; | ||||
|     return (byte)ch; | ||||
|  | @ -99,7 +106,7 @@ int fputs(const char* s, FILE* stream) | |||
| 
 | ||||
| int puts(const char* s) | ||||
| { | ||||
|     fputs(s, stdout); | ||||
|     return fputs(s, stdout); | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|     assert(stream); | ||||
|     fflush(stream); | ||||
|     ssize_t nwritten = write(stream->fd, ptr, nmemb * size); | ||||
|     if (nwritten < 0) | ||||
|         return 0; | ||||
|  | @ -162,7 +170,7 @@ static void sys_putch(char*&, char ch) | |||
| static FILE* __current_stream = nullptr; | ||||
| static void stream_putch(char*&, char ch) | ||||
| { | ||||
|     write(__current_stream->fd, &ch, 1); | ||||
|     fputc(ch, __current_stream); | ||||
| } | ||||
| 
 | ||||
| int fprintf(FILE* fp, const char* fmt, ...) | ||||
|  | @ -211,9 +219,8 @@ FILE* fopen(const char* pathname, const char* mode) | |||
|     if (fd < 0) | ||||
|         return nullptr; | ||||
|     auto* fp = (FILE*)malloc(sizeof(FILE)); | ||||
|     memset(fp, 0, sizeof(FILE)); | ||||
|     fp->fd = fd; | ||||
|     fp->eof = false; | ||||
|     fp->error = 0; | ||||
|     return fp; | ||||
| } | ||||
| 
 | ||||
|  | @ -223,9 +230,8 @@ FILE* fdopen(int fd, const char* mode) | |||
|     if (fd < 0) | ||||
|         return nullptr; | ||||
|     auto* fp = (FILE*)malloc(sizeof(FILE)); | ||||
|     memset(fp, 0, sizeof(FILE)); | ||||
|     fp->fd = fd; | ||||
|     fp->eof = false; | ||||
|     fp->error = 0; | ||||
|     return fp; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,8 +4,7 @@ | |||
| #include <sys/types.h> | ||||
| 
 | ||||
| __BEGIN_DECLS | ||||
| 
 | ||||
| #ifndef EOF | ||||
|  #ifndef EOF | ||||
| #define EOF (-1) | ||||
| #endif | ||||
| 
 | ||||
|  | @ -13,10 +12,16 @@ __BEGIN_DECLS | |||
| #define SEEK_CUR 1 | ||||
| #define SEEK_END 2 | ||||
| 
 | ||||
| #define __STDIO_FILE_BUFFER_SIZE 128 | ||||
| 
 | ||||
| struct __STDIO_FILE { | ||||
|     int fd; | ||||
|     int eof; | ||||
|     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; | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ int main(int argc, char** argv) | |||
|         return 1; | ||||
|     } | ||||
|     for (;;) { | ||||
|         char buf[1024]; | ||||
|         char buf[4096]; | ||||
|         ssize_t nread = read(fd, buf, sizeof(buf)); | ||||
|         if (nread == 0) | ||||
|             break; | ||||
|  | @ -25,8 +25,7 @@ int main(int argc, char** argv) | |||
|             printf("read() error: %s\n", strerror(errno)); | ||||
|             return 2; | ||||
|         } | ||||
|         for (ssize_t i = 0; i < nread; ++i) | ||||
|             putchar(buf[i]); | ||||
|         write(1, buf, nread); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ static void prompt() | |||
|         printf("# "); | ||||
|     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()); | ||||
|     fflush(stdout); | ||||
| } | ||||
| 
 | ||||
| static int sh_pwd(int, const char**) | ||||
|  | @ -347,6 +348,7 @@ int main(int, char**) | |||
|         } | ||||
|         for (ssize_t i = 0; i < nread; ++i) { | ||||
|             putchar(keybuf[i]); | ||||
|             fflush(stdout); | ||||
|             if (keybuf[i] != '\n') { | ||||
|                 linebuf[linedx++] = keybuf[i]; | ||||
|                 linebuf[linedx] = '\0'; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling