From 143156f63e2448733f1a35a74e629fe0ae9bb567 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 13 Sep 2020 19:51:09 -0400 Subject: have command shell block while commands are running --- doc/ints.txt | 6 ++++-- src/kernel/elf.c | 12 ++++++------ src/kernel/elf.h | 2 +- src/kernel/idt.c | 14 ++++++++++---- src/kernel/isrs.asm | 2 +- src/kernel/kbd.c | 2 -- src/kernel/task.c | 22 +++++++++++++++++----- src/kernel/task.h | 10 +++++++++- src/user/highway/highway.c | 4 +--- src/user/include/knob/task.h | 4 +++- src/user/include/pland/syscall.h | 12 +++++++++--- src/user/init/init.c | 2 +- src/user/knob/task.c | 11 ++++++++++- 13 files changed, 72 insertions(+), 31 deletions(-) diff --git a/doc/ints.txt b/doc/ints.txt index dd47d81..191d719 100644 --- a/doc/ints.txt +++ b/doc/ints.txt @@ -15,7 +15,6 @@ see table 1 file system calls have units of bytes unless otherwise specified functions returning handles or pointers use 0 to indicate error -functions returning "success" use 1 for success and 0 for failure see keys.txt for the return type of the "get key" system call the edx register of "start task" is a pointer to a null-terminated string. a pointer to a readonly copy of this string is put into the new task's edx. @@ -31,11 +30,14 @@ table 1: close file | 0x1 | | handle | | | | file read | 0x2 | read | handle | file offset | count | buffer | get file size | 0x3 | size | handle | | | | - start task | 0x4 | success | drive number | path | passed sz | | + start task | 0x4 | handle | drive number | path | passed sz | | log string | 0x5 | | sz string | | | | get key | 0x6 | keycode | | | | | allocate ram | 0x7 | start pointer | pages | | | | memory info | 0x8 | see table 2 | see table 2 | | | | + wait for task | 0x9 | | handle | | | | + + table 2: diff --git a/src/kernel/elf.c b/src/kernel/elf.c index 8113c14..60fa3a9 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -73,10 +73,10 @@ struct ph_entry { uint32_t align; } __attribute__ ((packed)); -bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma) { +uint32_t try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma) { file_id_t h = d->get_file(d, path); if (!h) - return false; + return 0; struct elf_header ehead; @@ -87,7 +87,7 @@ bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_v (ehead.endianness != LITTLE_ENDIAN) || ehead.os_abi_version) { d->free_file(d, h); - return false; + return 0; } uint32_t phtable_size = ehead.phentry_size * ehead.phtable_count; @@ -104,7 +104,7 @@ bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_v continue; void *pma = pd_user_allocate(pd, entry->vma, (entry->vms - 1) / 4096 + 1, entry->flags & PH_WRITABLE); fmcpy(pma, d, h, entry->fa, entry->fs); - for (uint8_t *pma_i = pma + entry->fs; pma_i < pma + entry->vms; ++pma_i) + for (uint8_t *pma_i = pma + entry->fs; pma_i < (uint8_t *)pma + entry->vms; ++pma_i) *pma_i = 0; } @@ -128,6 +128,7 @@ bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_v tstate.page_directory = pd; tstate.ret_addr = ehead.entry_vma; tstate.edx = (uint32_t)pass_vma; + tstate.wait_mode = NONE; const char *path_end_start = path; for (const char *i = path; *i; ++i) @@ -142,6 +143,5 @@ bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_v } tstate.name[i] = '\0'; - new_task(tstate); - return true; + return new_task(tstate); } \ No newline at end of file diff --git a/src/kernel/elf.h b/src/kernel/elf.h index 98489f2..89726c9 100644 --- a/src/kernel/elf.h +++ b/src/kernel/elf.h @@ -4,6 +4,6 @@ #include #include "drive.h" -bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma); +uint32_t try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma); #endif \ No newline at end of file diff --git a/src/kernel/idt.c b/src/kernel/idt.c index b789d42..4ffa1e2 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -54,11 +54,11 @@ static uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t cou return count; } -static bool sc_start_task(uint32_t drive_number, char *path, const char *pass) { +static uint32_t sc_start_task(uint32_t drive_number, char *path, const char *pass) { switch_to_kernel_cr3(); - bool result = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass); + uint32_t process_id = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass); switch_to_task_cr3(); - return result; + return process_id; } static void *sc_allocate_ram(uint32_t pages) { @@ -91,6 +91,11 @@ static uint32_t sc_memory_info(enum mi_arg arg) { } } +static void sc_wait_for_task(uint32_t handle) { + active_task->wait_mode = PROCESS_END; + active_task->wait_arg = handle; +} + void const *syscall_table[] = { &sc_open_file, &sc_close_file, @@ -100,7 +105,8 @@ void const *syscall_table[] = { &logsz, &get_key_code, &sc_allocate_ram, - &sc_memory_info + &sc_memory_info, + &sc_wait_for_task }; //these aren't really void ()'s, but gcc complains if we take an address of a void, so we give it a type diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index 4f2d4e2..8a27d57 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -23,7 +23,7 @@ extern on_kbd_isr extern make_sure_tasks extern exception_halt -n_syscalls equ 0x9 +n_syscalls equ 0xa ;section .bss ;_debug_is_start_task resb 1 diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c index 73a5ec6..f3eb323 100644 --- a/src/kernel/kbd.c +++ b/src/kernel/kbd.c @@ -1,7 +1,5 @@ #include -#include #include "panic.h" -#include "log.h" #include "util.h" static uint32_t *kbd_in_pointer; diff --git a/src/kernel/task.c b/src/kernel/task.c index 6c53510..942d1c4 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -64,11 +64,11 @@ void init_tasks() { : : : "ax"); } -void new_task(struct task_state state) { +uint32_t new_task(struct task_state state) { for (uint8_t n = 0; n < MAX_TASKS; ++n) if (!tasks[n].page_directory) { tasks[n] = state; - return; + return n + 1; } PANIC("Maximum number of tasks reached."); } @@ -77,15 +77,20 @@ void advance_active_task() { do if (++active_task == tasks + MAX_TASKS) active_task = tasks; - while (!active_task->page_directory); + while (!active_task->page_directory || active_task->wait_mode); } void make_sure_tasks() { for (uint8_t n = 0; n < MAX_TASKS; ++n) if (tasks[n].page_directory) - return; + while (1) { + for (uint8_t n = 0; n < MAX_TASKS; ++n) + if (tasks[n].page_directory && !tasks[n].wait_mode) + return; + asm ("hlt"); + } set_log_mode(LOG_SYSTEM); - logsz("No active tasks, halting."); + logsz("No tasks, halting."); while (1) asm ("hlt"); } @@ -95,4 +100,11 @@ void delete_task(struct task_state *state) { free_task_pd(state->page_directory); switch_to_task_cr3(); state->page_directory = 0; + + uint32_t handle = state - tasks + 1; + for (uint8_t n = 0; n < MAX_TASKS; ++n) + if (tasks[n].page_directory && + (tasks[n].wait_mode == PROCESS_END) && + (tasks[n].wait_arg == handle)) + tasks[n].wait_mode = NONE; } \ No newline at end of file diff --git a/src/kernel/task.h b/src/kernel/task.h index 0fa9688..50be93a 100644 --- a/src/kernel/task.h +++ b/src/kernel/task.h @@ -6,6 +6,11 @@ #define TASK_NAME_LEN 15 +enum wait_mode { + NONE, + PROCESS_END, +}; + struct task_state { uint32_t ret_addr; void *page_directory; @@ -18,6 +23,9 @@ struct task_state { uint32_t ebp; uint32_t esp; + enum wait_mode wait_mode; + uint32_t wait_arg; + char name[TASK_NAME_LEN + 1]; } __attribute__ ((packed)); @@ -25,7 +33,7 @@ extern struct task_state *active_task; void init_tasks(); -void new_task(struct task_state state); +uint32_t new_task(struct task_state state); void advance_active_task(); void delete_task(struct task_state *state); diff --git a/src/user/highway/highway.c b/src/user/highway/highway.c index 8dc0080..7e78472 100644 --- a/src/user/highway/highway.c +++ b/src/user/highway/highway.c @@ -18,9 +18,7 @@ void main() { ask_user_line_sz(line_buf, 1023); if (blockequ(line_buf, "exit", 5)) return; - if (try_run_command(path_buf)) - yield_task(); - else + if (!try_run_command_blocking(path_buf)) tell_user_sz("An error occured trying to run that command.\n"); } } \ No newline at end of file diff --git a/src/user/include/knob/task.h b/src/user/include/knob/task.h index ea5df62..6539a00 100644 --- a/src/user/include/knob/task.h +++ b/src/user/include/knob/task.h @@ -1,9 +1,11 @@ #ifndef KNOB_TASK_H #define KNOB_TASK_H +#include #include -bool try_run_command(const char *path); +uint32_t run_command(const char *path); +bool try_run_command_blocking(const char *path); void yield_task(); #endif \ No newline at end of file diff --git a/src/user/include/pland/syscall.h b/src/user/include/pland/syscall.h index c597e2b..75383fc 100644 --- a/src/user/include/pland/syscall.h +++ b/src/user/include/pland/syscall.h @@ -8,6 +8,7 @@ typedef uint32_t _file_handle_t; typedef uint32_t _task_handle_t; typedef uint32_t _drive_number_t; typedef uint32_t _pages_t; +typedef uint32_t _process_handle_t; typedef enum { _KEY_BACKSPACE = '\b', @@ -43,7 +44,8 @@ enum _scn { _SCN_LOG_STRING, _SCN_GET_KEY, _SCN_ALLOCATE_RAM, - _SCN_MEMORY_INFO + _SCN_MEMORY_INFO, + _SCN_WAIT_FOR_TASK }; static inline uint32_t _sc0(enum _scn eax) { @@ -124,8 +126,8 @@ static inline uint32_t _file_size(_file_handle_t handle) { return _sc1(_SCN_FILE_SIZE, handle); } -static inline bool _start_task(_drive_number_t drive_number, const char *path, const char *pass) { - return (bool)_sc3(_SCN_START_TASK, drive_number, (uint32_t)path, (uint32_t)pass); +static inline _process_handle_t _start_task(_drive_number_t drive_number, const char *path, const char *pass) { + return _sc3(_SCN_START_TASK, drive_number, (uint32_t)path, (uint32_t)pass); } static inline void _log_string(const char *sz) { @@ -160,4 +162,8 @@ static inline _pages_t _this_process_memory_left() { return _sc1(_SCN_MEMORY_INFO, 0x4); } +static inline void _wait_for_task(_process_handle_t handle) { + _sc1(_SCN_WAIT_FOR_TASK, handle); +} + #endif \ No newline at end of file diff --git a/src/user/init/init.c b/src/user/init/init.c index 390b731..e878603 100644 --- a/src/user/init/init.c +++ b/src/user/init/init.c @@ -7,7 +7,7 @@ void start(const char *cmd) { tell_user_sz(cmd); tell_user_sz(": "); tell_user_sz( - try_run_command(cmd) + run_command(cmd) ? "Succeded.\n" : "Failed.\n" ); diff --git a/src/user/knob/task.c b/src/user/knob/task.c index 598bee2..df5d38f 100644 --- a/src/user/knob/task.c +++ b/src/user/knob/task.c @@ -4,7 +4,7 @@ #include #include -bool try_run_command(const char *path) { +_task_handle_t run_command(const char *path) { uint8_t dn; path = remove_prefix(path, &dn); @@ -22,6 +22,15 @@ bool try_run_command(const char *path) { return _start_task(dn, path, ""); } +bool try_run_command_blocking(const char *path) { + _task_handle_t handle = run_command(path); + if (!handle) + return false; + _wait_for_task(handle); + _yield_task(); + return true; +} + void yield_task() { _yield_task(); } \ No newline at end of file -- cgit v1.2.3