diff --git a/src/apps/init/src/init.c b/src/apps/init/src/init.c index cb020ba..40705bc 100644 --- a/src/apps/init/src/init.c +++ b/src/apps/init/src/init.c @@ -45,11 +45,14 @@ void init() { int shell_pid = proc_open("shell", 0, 0); // printf("Shell got pid %d\n", shell_pid); - // proc_set_foreground(shell_pid); + proc_set_foreground(shell_pid); - for (;;) { - yield(); - } + proc_wait_pid(shell_pid, 0); + printf("Shell exited\n"); + + // for (;;) { + // yield(); + // } } void __start() { diff --git a/src/apps/shell/src/shell.c b/src/apps/shell/src/shell.c index f898c9d..cf901ee 100644 --- a/src/apps/shell/src/shell.c +++ b/src/apps/shell/src/shell.c @@ -44,12 +44,14 @@ int term_last_ret = 0; void term_run(); static int help_cmd(size_t argc, char ** argv); +static int exit_cmd(size_t argc, char ** argv); static size_t buff_read(const cb_t * cb, uint8_t * data, size_t count); static size_t buff_remove(cb_t * cb, size_t count); static void exec_buff(); int main(size_t argc, char ** argv) { term_command_add("help", help_cmd); + term_command_add("exit", exit_cmd); init_commands(); if (cb_create(&keybuff, MAX_CHARS, 1)) { @@ -68,40 +70,7 @@ static void dump_buff() { } } -static void key_cb(uint8_t code, char c, keyboard_event_t event, keyboard_mod_t mod) { - if ((event == KEY_EVENT_PRESS || event == KEY_EVENT_REPEAT) && c) { - if (cb_len(&keybuff) >= MAX_CHARS) { - ERROR("key buffer overflow"); - printf("(%u out of %u)", cb_len(&keybuff), MAX_CHARS); - PANIC("key buffer overflow"); - return; - } - - if (code == KEY_BACKSPACE) { - if (cb_len(&keybuff) > 0) { - putc(c); - cb_rpop(&keybuff, 0); - } - return; - } - - if (cb_push(&keybuff, &c)) { - ERROR("key buffer write error"); - return; - } - - // kprintf("Circbuff char %x at len %d / %d\n", c, circbuff_len(&keybuff), circbuff_buff_size(&keybuff)); - // dump_buff(); - - if (code == KEY_ENTER) { - command_ready++; - } - - putc(c); - } -} - -static void key_char_cb(char c) { +static void char_cb(char c) { if (cb_len(&keybuff) >= MAX_CHARS) { ERROR("key buffer overflow"); printf("(%u out of %u)", cb_len(&keybuff), MAX_CHARS); @@ -109,7 +78,7 @@ static void key_char_cb(char c) { return; } - if (c == KEY_BACKSPACE) { + if (c == '\b') { if (cb_len(&keybuff) > 0) { putc(c); cb_rpop(&keybuff, 0); @@ -122,17 +91,13 @@ static void key_char_cb(char c) { return; } - if (c == KEY_ENTER) { + if (c == '\n') { command_ready++; } putc(c); } -static void key_event_handler(const ebus_event_t * event) { - key_cb(event->key.keycode, event->key.c, event->key.event, event->key.mods); -} - static int help_cmd(size_t argc, char ** argv) { for (size_t i = 0; i < n_commands; i++) { puts(commands[i].command); @@ -141,6 +106,14 @@ static int help_cmd(size_t argc, char ** argv) { return 0; } +static int exit_cmd(size_t argc, char ** argv) { + if (argc > 1) { + int status = katoi(argv[1]); + proc_exit(status); + } + proc_exit(0); +} + void term_update() { if (!command_ready) { return; @@ -197,19 +170,9 @@ void term_run() { puts("$ "); for (;;) { - ebus_event_t event; - if (!pull_event(EBUS_EVENT_KEY, &event)) { - // printf("Got event type 0x%04x located at %p\n", event.event_id, &event); - key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); - // printf("Got key %c keycode 0x%x scancode 0x%x location %p\n", event.key.c, event.key.keycode, event.key.scancode, &event); - // if (event.key.event == 0) { - // putc(event.key.c); - // } - - // char c = getc(); - // if (c) { - // key_char_cb(c); - // } + char c; + if (file_read(stdin, 1, 1, &c) == 1) { + char_cb(c); } term_update(); } @@ -335,11 +298,13 @@ static void exec_buff() { printf("Unknown command '%s'\n", argv[0]); term_last_ret = 1; } + proc_set_foreground(pid); int exit_status = 0; if (!proc_wait_pid(pid, &exit_status) && exit_status) { printf("Process exited with status %d\n", exit_status); } + proc_set_foreground(getpid()); } // Free parsed args diff --git a/src/ebus/include/ebus.h b/src/ebus/include/ebus.h index da05201..b87e8f4 100644 --- a/src/ebus/include/ebus.h +++ b/src/ebus/include/ebus.h @@ -27,6 +27,7 @@ enum EBUS_EVENT { EBUS_EVENT_EXEC, EBUS_EVENT_PROC_MADE, EBUS_EVENT_PROC_CLOSE, + EBUS_EVENT_STDIN_READY, EBUS_EVENT_CUSTOM, }; diff --git a/src/kernel/src/kernel/io_buffer.c b/src/kernel/src/kernel/io_buffer.c index 8a5de38..7a6ead3 100644 --- a/src/kernel/src/kernel/io_buffer.c +++ b/src/kernel/src/kernel/io_buffer.c @@ -57,7 +57,7 @@ int io_buffer_pop(io_buffer_t * buff, char * c_out) { return -1; } - return 0; + return cb_pop(cb, c_out); } size_t io_buffer_size(const io_buffer_t * buff) { diff --git a/src/kernel/src/kernel/system_call_event.c b/src/kernel/src/kernel/system_call_event.c index b5695b8..e015226 100644 --- a/src/kernel/src/kernel/system_call_event.c +++ b/src/kernel/src/kernel/system_call_event.c @@ -100,6 +100,9 @@ int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs) { kernel_switch_task(); KLOG_TRACE("Back from timer %u", timer_id); } while (proc->next_event.timer.id != timer_id); + + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; } break; } diff --git a/src/kernel/src/kernel/system_call_io.c b/src/kernel/src/kernel/system_call_io.c index c6d3ba6..a0aee7f 100644 --- a/src/kernel/src/kernel/system_call_io.c +++ b/src/kernel/src/kernel/system_call_io.c @@ -67,7 +67,16 @@ int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs) { size_t pos; } * args = (struct _args *)args_data; - if (args->handle < 0 || !args->buff || !args->count) { + if (args->handle < 0) { + KLOG_WARNING("Process %u tried to read from invalid handle", proc->pid); + return 0; + } + if (!args->buff) { + KLOG_WARNING("Process %u tried to read into null buffer", proc->pid); + return 0; + } + if (!args->count) { + KLOG_WARNING("Process %u read with 0 count", proc->pid); return 0; } @@ -75,32 +84,47 @@ int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs) { // TODO add buffer to handle_t if (args->handle == 0) { - size_t available = io_buffer_length(proc->io_buffer); - size_t count = args->count; // idk if this needs to be copied or can be edited in place - if (count > available) { - count = available; - } + KLOG_TRACE("Process %u reading %u characters from stdin", proc->pid, args->count); + + size_t written = 0; + size_t count = args->count; // idk if this needs to be copied or can be edited in place - if (count > 0) { - for (size_t i = 0; i < count; i++) { - if (io_buffer_pop(proc->io_buffer, &args->buff[i])) { - break; + while (count) { + size_t available = io_buffer_length(proc->io_buffer); + // Use available as the number to read, limit to count if greater than + if (available > count) { + available = count; + } + + for (size_t i = 0; i < available; i++) { + if (io_buffer_pop(proc->io_buffer, &args->buff[written++])) { + KLOG_WARNING("Failed to pop from io buffer for process %u", proc->pid); + // TODO should this be -1? + return written; } } + count -= available; + + if (count) { + // yield + proc->next_event.event_id = 0; + proc->filter_event.event_id = EBUS_EVENT_STDIN_READY; + proc->state = PROCESS_STATE_WAITING; + + enable_interrupts(); + kernel_switch_task(); + } } - return count; - } + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; - handle_t * h = process_get_handle(proc, args->handle); - if (!h) { - KPANIC("Failed to find handle"); + return written; + } + else { + KLOG_WARNING("Process %u trying to read from unsupported handle %d", proc->pid, args->handle); return 0; } - - // io_device_t * d = h->device; - - // return d->read_fn(d->data, args->buff, args->count, args->pos); } break; case SYS_CALL_IO_WRITE: { diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index 45638fc..da35069 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -146,6 +146,9 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { enable_interrupts(); kernel_switch_task(); + + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; } break; case SYS_CALL_PROC_EXEC: { @@ -190,11 +193,15 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { proc->filter_event.proc_close.pid = args->pid; proc->state = PROCESS_STATE_WAITING; - do { + for (;;) { enable_interrupts(); kernel_switch_task(); - KLOG_TRACE("Back from timer %u", timer_id); - } while (proc->next_event.proc_close.pid != args->pid); + if (proc->next_event.proc_close.pid == args->pid) { + KLOG_DEBUG("Waited process %u has closed, waiting process is %u", args->pid, proc->pid); + break; + } + proc->next_event.event_id = 0; + } if (!(proc->next_event.event_id == proc->filter_event.event_id)) { KPANIC("Tried to resume process but the event does not match filter"); diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 4f4be40..4ab8513 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -203,36 +203,34 @@ process_t * pm_get_next(proc_man_t * pm) { process_t * proc = pm->current_task->next; - KLOG_TRACE("Start looking for next process after %u", pm->current_task->pid); - - do { - KLOG_TRACE("Looking at pid %u in state %u to see if it's ready", proc->pid, proc->state); - - if (proc->state > PROCESS_STATE_LOADED && proc->state < PROCESS_STATE_DEAD) { - if (!proc->filter_event.event_id) { - KLOG_TRACE("Process %u has no filter event, so it's ready", proc->pid); - return proc; + for (;;) { + KLOG_TRACE("Start looking for next process after %u", pm->current_task->pid); + + do { + KLOG_TRACE("Looking at pid %u in state %u to see if it's ready", proc->pid, proc->state); + + if (proc->state > PROCESS_STATE_LOADED && proc->state < PROCESS_STATE_DEAD) { + if (!proc->filter_event.event_id) { + KLOG_TRACE("Process %u has no filter event, so it's ready", proc->pid); + return proc; + } + // This handles the above case but is split for trace log + if (proc->filter_event.event_id == proc->next_event.event_id) { + KLOG_DEBUG("Process %u has ready event %u", proc->pid, proc->next_event.event_id); + return proc; + } + KLOG_TRACE("Process %u is not ready, waiting for %u", proc->pid, proc->filter_event.event_id); } - // This handles the above case but is split for trace log - if (proc->filter_event.event_id == proc->next_event.event_id) { - KLOG_TRACE("Process %u has ready event %u", proc->pid, proc->next_event.event_id); - return proc; + else { + KLOG_TRACE("Process with pid %u is not alive", proc->pid); } - KLOG_TRACE("Process %u is not ready, waiting for %u", proc->pid, proc->filter_event.event_id); - } - else { - KLOG_TRACE("Process with pid %u is not alive", proc->pid); - } - - KLOG_TRACE("Going to next process %u, fg is %u", proc->next->pid, pm->current_task->pid); - proc = proc->next; - } while (proc != pm->current_task->next); - KLOG_TRACE("Finish looking for next process"); + KLOG_TRACE("Going to next process %u, fg is %u", proc->next->pid, pm->current_task->pid); + proc = proc->next; + } while (proc != pm->current_task->next); - if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { - KLOG_TRACE("Next process is the foreground process with pid %u", proc->pid); - return proc; + KLOG_TRACE("No process ready to resume. Halting until next event"); + asm("hlt"); } KPANIC("Could not find process to resume"); @@ -282,5 +280,23 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { KLOG_TRACE("Finish push event %u", event->event_id); + // TODO this is a temp hack to get keyboard to process until better stdin is created + if (event->event_id == EBUS_EVENT_KEY && (event->key.event == KEY_EVENT_PRESS || event->key.event == KEY_EVENT_REPEAT) && event->key.c) { + process_t * fg = pm->foreground_task; + if (io_buffer_push(fg->io_buffer, event->key.c)) { + KLOG_WARNING("Failed to push keyboard char %c to process %u io buffer", event->key.c, fg->pid); + } + else { + KLOG_TRACE("Process %u currently waiting on %u", fg->pid, fg->filter_event.event_id); + if (fg->filter_event.event_id == EBUS_EVENT_STDIN_READY) { + KLOG_TRACE("Process %u was waiting for stdin, setting next_event to stdin ready", fg->pid); + fg->next_event.event_id = EBUS_EVENT_STDIN_READY; + } + KLOG_TRACE("Pushed char '%c' (0x%02X) to process %u io buffer resulting in length %u", event->key.c, event->key.c, fg->pid, io_buffer_length(fg->io_buffer)); + } + } + + KLOG_TRACE("Finish stdio %u", event->event_id); + return 0; }