From 5aa59394dc172b205a0cc80315bc666a254507c0 Mon Sep 17 00:00:00 2001 From: Minep Date: Mon, 8 Aug 2022 17:15:45 +0100 Subject: [PATCH] feat: hook up the keyboard input into our vfs feat: general fifo buffer (based on ring buffer) implementation fix: make read/write syscall interruptible refactor: remove the need of using loop for finding the suitable segregated list --- .gitignore | 2 +- lunaix-os/includes/lunaix/ds/fifo.h | 35 +++++++ lunaix-os/includes/lunaix/ds/fifobuf.h | 18 ---- lunaix-os/includes/lunaix/tty/console.h | 3 +- lunaix-os/kernel/demos/iotest.c | 10 +- lunaix-os/kernel/ds/fifo.c | 119 ++++++++++++++++++++++++ lunaix-os/kernel/fs/vfs.c | 4 + lunaix-os/kernel/lxconsole.c | 103 ++++++++++++-------- lunaix-os/kernel/mm/valloc.c | 36 +++---- lunaix-os/kernel/service/pconsole.c | 4 +- 10 files changed, 254 insertions(+), 80 deletions(-) create mode 100644 lunaix-os/includes/lunaix/ds/fifo.h delete mode 100644 lunaix-os/includes/lunaix/ds/fifobuf.h create mode 100644 lunaix-os/kernel/ds/fifo.c diff --git a/.gitignore b/.gitignore index 7aaf609..cd7d5b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ **/.~lock* workspace/ **.odp - +drafts/ diff --git a/lunaix-os/includes/lunaix/ds/fifo.h b/lunaix-os/includes/lunaix/ds/fifo.h new file mode 100644 index 0000000..3a21824 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/fifo.h @@ -0,0 +1,35 @@ +#ifndef __LUNAIX_FIFO_BUF_H +#define __LUNAIX_FIFO_BUF_H + +#include +#include + +#define FIFO_DIRTY 1 + +struct fifo_buf +{ + void* data; + size_t wr_pos; + size_t rd_pos; + size_t size; + size_t free_len; + size_t flags; + mutex_t lock; +}; + +int +fifo_backone(struct fifo_buf* fbuf); + +size_t +fifo_putone(struct fifo_buf* fbuf, uint8_t data); + +void +fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags); + +size_t +fifo_write(struct fifo_buf* fbuf, void* data, size_t count); + +size_t +fifo_read(struct fifo_buf* fbuf, void* buf, size_t count); + +#endif /* __LUNAIX_FIFO_BUF_H */ diff --git a/lunaix-os/includes/lunaix/ds/fifobuf.h b/lunaix-os/includes/lunaix/ds/fifobuf.h deleted file mode 100644 index f5f08c1..0000000 --- a/lunaix-os/includes/lunaix/ds/fifobuf.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __LUNAIX_FIFO_BUF_H -#define __LUNAIX_FIFO_BUF_H - -#include - -#define FIFO_DIRTY 1 - -struct fifo_buffer -{ - void* data; - unsigned int wr_pos; - unsigned int rd_pos; - unsigned int size; - unsigned int flags; - mutex_t lock; -}; - -#endif /* __LUNAIX_FIFO_BUF_H */ diff --git a/lunaix-os/includes/lunaix/tty/console.h b/lunaix-os/includes/lunaix/tty/console.h index dee64a2..e5eaa34 100644 --- a/lunaix-os/includes/lunaix/tty/console.h +++ b/lunaix-os/includes/lunaix/tty/console.h @@ -7,7 +7,8 @@ struct console { struct lx_timer* flush_timer; - struct fifo_buffer buffer; + struct fifo_buf output; + struct fifo_buf input; unsigned int erd_pos; unsigned int lines; }; diff --git a/lunaix-os/kernel/demos/iotest.c b/lunaix-os/kernel/demos/iotest.c index 99300bd..f41c9a8 100644 --- a/lunaix-os/kernel/demos/iotest.c +++ b/lunaix-os/kernel/demos/iotest.c @@ -39,8 +39,16 @@ _iotest_main() lseek(fd, 521, FSEEK_SET); write(fd, test_sequence, sizeof(test_sequence)); - // 读出我们写的内容 char read_out[256]; + write(tty, "input: ", 8); + int size = read(tty, read_out, 256); + + write(tty, "your input: ", 13); + write(tty, read_out, size); + write(fd, read_out, size); + write(tty, "\n", 1); + + // 读出我们写的内容 lseek(fd, 512, FSEEK_SET); read(fd, read_out, sizeof(read_out)); diff --git a/lunaix-os/kernel/ds/fifo.c b/lunaix-os/kernel/ds/fifo.c new file mode 100644 index 0000000..1e72e8d --- /dev/null +++ b/lunaix-os/kernel/ds/fifo.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include + +void +fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags) +{ + *buf = (struct fifo_buf){ .data = data_buffer, + .rd_pos = 0, + .wr_pos = 0, + .size = buf_size, + .flags = flags, + .free_len = buf_size }; + mutex_init(&buf->lock); +} + +int +fifo_backone(struct fifo_buf* fbuf) +{ + mutex_lock(&fbuf->lock); + + if (fbuf->free_len == fbuf->size) { + mutex_unlock(&fbuf->lock); + return 0; + } + + fbuf->wr_pos = (fbuf->wr_pos ? fbuf->wr_pos : fbuf->size) - 1; + fbuf->free_len++; + + mutex_unlock(&fbuf->lock); + + return 1; +} + +size_t +fifo_putone(struct fifo_buf* fbuf, uint8_t data) +{ + mutex_lock(&fbuf->lock); + + if (!fbuf->free_len) { + mutex_unlock(&fbuf->lock); + return 0; + } + + uint8_t* dest = fbuf->data; + dest[fbuf->wr_pos] = data; + fbuf->wr_pos = (fbuf->wr_pos + 1) % fbuf->size; + fbuf->free_len--; + + mutex_unlock(&fbuf->lock); + + return 1; +} + +size_t +fifo_write(struct fifo_buf* fbuf, void* data, size_t count) +{ + size_t wr_count = 0, wr_pos = fbuf->wr_pos; + + mutex_lock(&fbuf->lock); + + if (!fbuf->free_len) { + mutex_unlock(&fbuf->lock); + return 0; + } + + if (wr_pos >= fbuf->rd_pos) { + // case 1 + size_t cplen_tail = MIN(fbuf->size - wr_pos, count); + size_t cplen_head = MIN(fbuf->rd_pos, count - cplen_tail); + memcpy(fbuf->data + wr_pos, data, cplen_tail); + memcpy(fbuf->data, data + cplen_tail, cplen_head); + + wr_count = cplen_head + cplen_tail; + } else { + // case 2 + wr_count = MIN(fbuf->rd_pos - wr_pos, count); + memcpy(fbuf->data + wr_pos, data, wr_count); + } + + fbuf->wr_pos = (wr_pos + wr_count) % fbuf->size; + fbuf->free_len -= wr_count; + + mutex_unlock(&fbuf->lock); + + return wr_count; +} + +size_t +fifo_read(struct fifo_buf* fbuf, void* buf, size_t count) +{ + size_t rd_count = 0, rd_pos = fbuf->rd_pos; + mutex_lock(&fbuf->lock); + + if (fbuf->free_len == fbuf->size) { + mutex_unlock(&fbuf->lock); + return 0; + } + + if (rd_pos >= fbuf->wr_pos) { + size_t cplen_tail = MIN(fbuf->size - rd_pos, count); + size_t cplen_head = MIN(fbuf->wr_pos, count - cplen_tail); + memcpy(buf, fbuf->data + rd_pos, cplen_tail); + memcpy(buf + cplen_tail, fbuf->data, cplen_head); + + rd_count = cplen_head + cplen_tail; + } else { + rd_count = MIN(fbuf->wr_pos - rd_pos, count); + memcpy(buf, fbuf->data + rd_pos, rd_count); + } + + fbuf->rd_pos = (rd_pos + rd_count) % fbuf->size; + fbuf->free_len += rd_count; + + mutex_unlock(&fbuf->lock); + + return rd_count; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 53d21d8..1104d9b 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -657,7 +657,9 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) goto done; } + cpu_enable_interrupt(); errno = file->ops.read(file, buf, count, file->f_pos); + cpu_disable_interrupt(); if (errno > 0) { file->f_pos += errno; @@ -683,7 +685,9 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) goto done; } + cpu_enable_interrupt(); errno = file->ops.write(file, buf, count, file->f_pos); + cpu_disable_interrupt(); if (errno > 0) { file->f_pos += errno; diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/lxconsole.c index e43ebc5..2b20970 100644 --- a/lunaix-os/kernel/lxconsole.c +++ b/lunaix-os/kernel/lxconsole.c @@ -1,7 +1,9 @@ #include #include +#include #include #include +#include #include #include #include @@ -9,47 +11,70 @@ static struct console lx_console; int -__tty_write(struct device* dev, - void* buf, - unsigned int offset, - unsigned int len); +__tty_write(struct device* dev, void* buf, size_t offset, size_t len); + +int +__tty_read(struct device* dev, void* buf, size_t offset, size_t len); void lxconsole_init() { memset(&lx_console, 0, sizeof(lx_console)); - lx_console.buffer.data = VGA_BUFFER_VADDR + 0x1000; - lx_console.buffer.size = 8192; - mutex_init(&lx_console.buffer.lock); + fifo_init(&lx_console.output, VGA_BUFFER_VADDR + 0x1000, 8192, 0); + fifo_init(&lx_console.input, valloc(4096), 4096, 0); + + // FIXME use valloc to allocate console buffer. + // In doing this, the console buffer can only be accessed from kernel mode + // any direct write to this buffer from user land should be purged! // 分配控制台缓存 - for (size_t i = 0; i < PG_ALIGN(lx_console.buffer.size); i += PG_SIZE) { + for (size_t i = 0; i < PG_ALIGN(lx_console.output.size); i += PG_SIZE) { uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0); vmm_set_mapping(PD_REFERENCED, - (uintptr_t)lx_console.buffer.data + i, + (uintptr_t)lx_console.output.data + i, pa, PG_PREM_URW, 0); } - memset(lx_console.buffer.data, 0, lx_console.buffer.size); - lx_console.flush_timer = NULL; struct device* tty_dev = device_addseq(NULL, &lx_console, "tty"); tty_dev->write = __tty_write; + tty_dev->read = __tty_read; } int -__tty_write(struct device* dev, - void* buf, - unsigned int offset, - unsigned int len) +__tty_write(struct device* dev, void* buf, size_t offset, size_t len) { struct console* console = (struct console*)dev->underlay; console_write(console, buf, len); } +int +__tty_read(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct kdb_keyinfo_pkt keyevent; + struct console* console = (struct console*)dev->underlay; + while (1) { + // FIXME keyboard is duplicating the key that user typed + if (!kbd_recv_key(&keyevent)) { + continue; + } + if ((keyevent.keycode & 0xff00) <= KEYPAD) { + char c = (char)(keyevent.keycode & 0x00ff); + if (c == 0x08 && !fifo_backone(&console->input)) { + continue; + } + // console_write_char(c); + if (!fifo_putone(&console->input, c) || c == '\n') { + break; + } + } + } + return fifo_read(&console->input, buf, len); +} + void console_schedule_flush() { @@ -59,7 +84,7 @@ console_schedule_flush() void console_view_up() { - struct fifo_buffer* buffer = &lx_console.buffer; + struct fifo_buf* buffer = &lx_console.output; mutex_lock(&buffer->lock); size_t p = lx_console.erd_pos - 2; while (p < lx_console.erd_pos && p != buffer->wr_pos && @@ -81,9 +106,9 @@ size_t __find_next_line(size_t start) { size_t p = start; - while (p != lx_console.buffer.wr_pos && - ((char*)lx_console.buffer.data)[p] != '\n') { - p = (p + 1) % lx_console.buffer.size; + while (p != lx_console.output.wr_pos && + ((char*)lx_console.output.data)[p] != '\n') { + p = (p + 1) % lx_console.output.size; } return p + 1; } @@ -91,7 +116,7 @@ __find_next_line(size_t start) void console_view_down() { - struct fifo_buffer* buffer = &lx_console.buffer; + struct fifo_buf* buffer = &lx_console.output; mutex_lock(&buffer->lock); lx_console.erd_pos = __find_next_line(lx_console.erd_pos); @@ -102,27 +127,27 @@ console_view_down() void console_flush() { - if (mutex_on_hold(&lx_console.buffer.lock)) { + if (mutex_on_hold(&lx_console.output.lock)) { return; } - if (!(lx_console.buffer.flags & FIFO_DIRTY)) { + if (!(lx_console.output.flags & FIFO_DIRTY)) { return; } - tty_flush_buffer(lx_console.buffer.data, + tty_flush_buffer(lx_console.output.data, lx_console.erd_pos, - lx_console.buffer.wr_pos, - lx_console.buffer.size); - lx_console.buffer.flags &= ~FIFO_DIRTY; + lx_console.output.wr_pos, + lx_console.output.size); + lx_console.output.flags &= ~FIFO_DIRTY; } void console_write(struct console* console, uint8_t* data, size_t size) { - mutex_lock(&console->buffer.lock); - uint8_t* buffer = console->buffer.data; - uintptr_t ptr = console->buffer.wr_pos; - uintptr_t rd_ptr = console->buffer.rd_pos; + mutex_lock(&console->output.lock); + uint8_t* buffer = console->output.data; + uintptr_t ptr = console->output.wr_pos; + uintptr_t rd_ptr = console->output.rd_pos; char c; int lines = 0; @@ -132,29 +157,29 @@ console_write(struct console* console, uint8_t* data, size_t size) if (!c) { continue; } - buffer[(ptr + j) % console->buffer.size] = c; + buffer[(ptr + j) % console->output.size] = c; lines += (c == '\n'); j++; } size = j; - uintptr_t new_ptr = (ptr + size) % console->buffer.size; - console->buffer.wr_pos = new_ptr; + uintptr_t new_ptr = (ptr + size) % console->output.size; + console->output.wr_pos = new_ptr; if (console->lines > TTY_HEIGHT && lines > 0) { - console->buffer.rd_pos = - __find_next_line((size + rd_ptr) % console->buffer.size); + console->output.rd_pos = + __find_next_line((size + rd_ptr) % console->output.size); } if (new_ptr < ptr + size && new_ptr > rd_ptr) { - console->buffer.rd_pos = new_ptr; + console->output.rd_pos = new_ptr; } console->lines += lines; - console->erd_pos = console->buffer.rd_pos; - console->buffer.flags |= FIFO_DIRTY; - mutex_unlock(&console->buffer.lock); + console->erd_pos = console->output.rd_pos; + console->output.flags |= FIFO_DIRTY; + mutex_unlock(&console->output.lock); } void diff --git a/lunaix-os/kernel/mm/valloc.c b/lunaix-os/kernel/mm/valloc.c index 5191a1a..04379e1 100644 --- a/lunaix-os/kernel/mm/valloc.c +++ b/lunaix-os/kernel/mm/valloc.c @@ -1,12 +1,14 @@ #include #include #include +#include #define CLASS_LEN(class) (sizeof(class) / sizeof(class[0])) static char piles_names[][PILE_NAME_MAXLEN] = { - "valloc_8", "valloc_16", "valloc_32", "valloc_64", "valloc_128", - "valloc_256", "valloc_512", "valloc_1k", "valloc_2k", "valloc_4k" + "valloc_8", "valloc_16", "valloc_32", "valloc_64", + "valloc_128", "valloc_256", "valloc_512", "valloc_1k", + "valloc_2k", "valloc_4k", "valloc_8k" }; static char piles_names_dma[][PILE_NAME_MAXLEN] = { @@ -22,7 +24,7 @@ valloc_init() { for (size_t i = 0; i < CLASS_LEN(piles_names); i++) { int size = 1 << (i + 3); - piles[i] = cake_new_pile(&piles_names[i], size, size > 1024 ? 4 : 1, 0); + piles[i] = cake_new_pile(&piles_names[i], size, size > 1024 ? 8 : 1, 0); } // DMA 内存保证128字节对齐 @@ -34,18 +36,18 @@ valloc_init() } void* -__valloc(unsigned int size, struct cake_pile** segregate_list, size_t len) +__valloc(unsigned int size, + struct cake_pile** segregate_list, + size_t len, + size_t boffset) { - size_t i = 0; - for (; i < len; i++) { - if (segregate_list[i]->piece_size >= size) { - goto found_class; - } - } + size_t i = ILOG2(size); + i += (size - (1 << i) != 0); + i -= boffset; - return NULL; + if (i >= len) + return NULL; -found_class: return cake_grab(segregate_list[i]); } @@ -63,13 +65,13 @@ __vfree(void* ptr, struct cake_pile** segregate_list, size_t len) void* valloc(unsigned int size) { - return __valloc(size, &piles, CLASS_LEN(piles_names)); + return __valloc(size, &piles, CLASS_LEN(piles_names), 3); } void* vzalloc(unsigned int size) { - void* ptr = __valloc(size, &piles, CLASS_LEN(piles_names)); + void* ptr = __valloc(size, &piles, CLASS_LEN(piles_names), 3); memset(ptr, 0, size); return ptr; } @@ -82,7 +84,7 @@ vcalloc(unsigned int size, unsigned int count) return 0; } - void* ptr = __valloc(alloc_size, &piles, CLASS_LEN(piles_names)); + void* ptr = __valloc(alloc_size, &piles, CLASS_LEN(piles_names), 3); memset(ptr, 0, alloc_size); return ptr; } @@ -96,13 +98,13 @@ vfree(void* ptr) void* valloc_dma(unsigned int size) { - return __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma)); + return __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma), 7); } void* vzalloc_dma(unsigned int size) { - void* ptr = __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma)); + void* ptr = __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma), 7); memset(ptr, 0, size); return ptr; } diff --git a/lunaix-os/kernel/service/pconsole.c b/lunaix-os/kernel/service/pconsole.c index be59c18..200303d 100644 --- a/lunaix-os/kernel/service/pconsole.c +++ b/lunaix-os/kernel/service/pconsole.c @@ -12,9 +12,7 @@ _pconsole_main() continue; } if ((keyevent.state & KBD_KEY_FPRESSED)) { - if ((keyevent.keycode & 0xff00) <= KEYPAD) { - console_write_char((char)(keyevent.keycode & 0x00ff)); - } else if (keyevent.keycode == KEY_UP) { + if (keyevent.keycode == KEY_UP) { console_view_up(); } else if (keyevent.keycode == KEY_DOWN) { console_view_down(); -- 2.27.0