From 7140bb1631393ad8847f1af4074a70bf56116087 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Tue, 21 Apr 2020 20:56:27 +0200 Subject: [PATCH] Add TTY's signals request + update shell process waiting --- include/kernel/devices/tty.h | 12 +- include/lib/signal.h | 1 + include/lib/sys/wait.h | 14 +-- include/user/shell/builtin.h | 18 +-- include/user/shell/util.h | 2 + src/kernel/devices/tty/operations/read.c | 136 ++++++++++++++++------- src/kernel/memory/page/free.c | 2 +- src/kernel/scheduler/process/create.c | 1 + src/kernel/scheduler/process/terminate.c | 19 ++-- src/kernel/scheduler/schedule.c | 2 +- src/kernel/scheduler/syscall/sys_exit.c | 1 + src/kernel/signal/deliver.c | 17 ++- src/kernel/signal/raise.c | 1 + src/user/shell/builtin/proc.c | 15 +-- src/user/shell/main.c | 8 ++ src/user/shell/util/manual_proc_call.c | 9 +- src/user/shell/util/wait_child.c | 72 ++++++++++++ src/user/test/test.c | 44 ++------ 18 files changed, 245 insertions(+), 129 deletions(-) create mode 100644 src/user/shell/util/wait_child.c diff --git a/include/kernel/devices/tty.h b/include/kernel/devices/tty.h index 8290d12..a687bbe 100644 --- a/include/kernel/devices/tty.h +++ b/include/kernel/devices/tty.h @@ -57,7 +57,13 @@ struct keyboard_obj_s size_t clen; off_t cursor; } buffer; - uint8_t mode; + struct { + uint8_t enter : 1; + uint8_t maj : 1; + uint8_t special : 1; + uint8_t ctrl : 1; + uint8_t const : 4; + } mode; uint8_t cvisible; struct { struct { @@ -66,6 +72,10 @@ struct keyboard_obj_s int16_t y; } cursor; } tty; + struct { + uint8_t keycode; + off_t cursor; + } signal; } saved; // FIXME Dirty place, remove / move me ! diff --git a/include/lib/signal.h b/include/lib/signal.h index 3cb0af5..68cd38b 100644 --- a/include/lib/signal.h +++ b/include/lib/signal.h @@ -11,5 +11,6 @@ typedef __sighandler_t sighandler_t; // Prototype extern int kill(pid_t pid, int sig); +extern sighandler_t signal(int signum, sighandler_t handler); #endif /*__LIB_SIGNAL_H__*/ diff --git a/include/lib/sys/wait.h b/include/lib/sys/wait.h index c8c639d..ee59af5 100644 --- a/include/lib/sys/wait.h +++ b/include/lib/sys/wait.h @@ -8,13 +8,13 @@ #include /* Macros for the `waitpid`'s wstatus argument. */ -#define WEXITSTATUS(status) __WEXITSTATUS (status) -#define WTERMSIG(status) __WTERMSIG (status) -#define WSTOPSIG(status) __WSTOPSIG (status) -#define WIFEXITED(status) __WIFEXITED (status) -#define WIFSIGNALED(status) __WIFSIGNALED (status) -#define WIFSTOPPED(status) __WIFSTOPPED (status) -#define WIFCONTINUED(status) __WIFCONTINUED (status) +#define WEXITSTATUS(status) __WEXITSTATUS(status) +#define WTERMSIG(status) __WTERMSIG(status) +#define WSTOPSIG(status) __WSTOPSIG(status) +#define WIFEXITED(status) __WIFEXITED(status) +#define WIFSIGNALED(status) __WIFSIGNALED(status) +#define WIFSTOPPED(status) __WIFSTOPPED(status) +#define WIFCONTINUED(status) __WIFCONTINUED(status) #define WCOREDUMP(status) __WCOREDUMP(status) // Wait process diff --git a/include/user/shell/builtin.h b/include/user/shell/builtin.h index c4a0f95..02b2e25 100644 --- a/include/user/shell/builtin.h +++ b/include/user/shell/builtin.h @@ -4,22 +4,6 @@ #include #include -// CMDBLOCK() -// Generate a "command block" stored in ".cmd.cahce" section. -// We need to "hide" the block, so we generate anonyme name using -// __COUNTER__ macros. -/*#define gen_name(n) _##n -#define anonym_name(n) gen_name(n) -#define VHEX_BUILTIN(builtin) \ - static int builtin(int argc, char **argv); \ - __attribute__((section(".builtin.cache"))) \ - static const struct builtin_s anonym_name(__COUNTER__) = { \ - .name = #builtin, \ - .entry = builtin \ - }; \ - static int builtin(int argc, char **argv) -*/ - // Define builtin struct. struct builtin_s { @@ -28,7 +12,7 @@ struct builtin_s }; // Builtin list -extern int builtin_proc(void); +extern int builtin_proc(int argc, char **argv); extern int builtin_ram(void); extern int builtin_fxdb(int argc, char **argv); diff --git a/include/user/shell/util.h b/include/user/shell/util.h index 166247d..0e0f8b8 100644 --- a/include/user/shell/util.h +++ b/include/user/shell/util.h @@ -3,10 +3,12 @@ #include #include +#include extern int manual_proc_call(char **argv); extern int check_builtin(int argc, char **argv); extern int strtotab(int *argc, char ***argv, char const *str); extern void strtotab_quit(int *argc, char ***argv); +extern void wait_child(pid_t pid); #endif /*__USER_UTIL_H__*/ diff --git a/src/kernel/devices/tty/operations/read.c b/src/kernel/devices/tty/operations/read.c index 2cbe5e2..ead47ec 100644 --- a/src/kernel/devices/tty/operations/read.c +++ b/src/kernel/devices/tty/operations/read.c @@ -6,10 +6,12 @@ #include #include #include +#include #include +#include // Intenral functions -static int check_signal(struct keyboard_obj_s *keyboard, key_t key); +static void check_signal(struct keyboard_obj_s *keyboard); static int check_special(struct keyboard_obj_s *keyboard, key_t key); static int update_buffer(struct keyboard_obj_s *keyboard, key_t key); static int buffer_insert(struct keyboard_obj_s *keyboard, char n); @@ -17,13 +19,14 @@ static void tty_buffer_display(struct keyboard_obj_s *keyboard); static void cursor_callback(struct keyboard_obj_s *keyboard); //FIXME: this function is device-specifique !! +//FIXME: shared device error !!! ssize_t tty_read(void *inode, void *buffer, size_t count) { extern struct keycache_s *keylist; struct keyboard_obj_s keyboard; struct keycache_s *keynode; int first_key; - int timer_fd; + //int timer_fd; // Check potential error. if (count < 2) @@ -35,7 +38,9 @@ ssize_t tty_read(void *inode, void *buffer, size_t count) keyboard.buffer.size = count; keyboard.buffer.cursor = 0; keyboard.buffer.clen = 0; - keyboard.mode = 0x00; + keyboard.mode.enter = 0; + keyboard.mode.maj = 0; + keyboard.mode.special = 0; keyboard.cvisible = 0; keyboard.tty = inode; @@ -45,12 +50,12 @@ ssize_t tty_read(void *inode, void *buffer, size_t count) // Initialize timer for cursor. // FIXME: find real ticks value !! - timer_fd = timer_install(&cursor_callback, &keyboard, 500 * 500 * 2, TIMER_START); - if (timer_fd == -1) - return (0); + //timer_fd = timer_install(&cursor_callback, &keyboard, 500 * 500 * 2, TIMER_START); + //if (timer_fd == -1) + // return (0); // Main Loop, wait [EXE] key. - while ((keyboard.mode & 0x04) == 0) + while (keyboard.mode.enter == 0) { // Wait user interruption. keyboard_wait_event(); @@ -61,22 +66,30 @@ ssize_t tty_read(void *inode, void *buffer, size_t count) atomic_start(); keynode = keylist; first_key = 0; + keyboard.mode.ctrl = 0; + keyboard.saved.signal.keycode = KEY_UNUSED; while (keynode != NULL && - (keynode->counter == 1 || + (keynode->counter == 1 || keynode->keycode == KEY_OPTN || (first_key == 0 && keynode->counter > 10 && (keynode->counter & 1) == 0))) { - // Repeat key flags. - first_key = 1; - // Handle current key - if (check_signal(&keyboard, keynode->keycode) == 0 && - check_special(&keyboard, keynode->keycode) == 0) + if (check_special(&keyboard, keynode->keycode) == 0) update_buffer(&keyboard, keynode->keycode); + // Dump the the fist pressed key + if (first_key == 0) { + keyboard.saved.signal.keycode = keynode->keycode; + keyboard.saved.signal.cursor = keyboard.buffer.cursor; + } + first_key = 1; + // Get next key. keynode = keynode->next; } + // Check signal + check_signal(&keyboard); + // Stop atomic operations atomic_stop(); @@ -85,19 +98,56 @@ ssize_t tty_read(void *inode, void *buffer, size_t count) } // uninstall cursor timer. - timer_uninstall(timer_fd); + //timer_uninstall(timer_fd); // Return the number of input char. return (keyboard.buffer.clen); } //TODO: move me -static int check_signal(struct keyboard_obj_s *keyboard, key_t key) +static void check_signal(struct keyboard_obj_s *keyboard) { - //TODO - (void)key; - (void)keyboard; - return (0); + extern struct process *process_current; + struct { uint8_t keycode; int signal; } echapment[3] = { + {.keycode = KEY_LN, .signal = SIGINT}, + {.keycode = KEY_DIV, .signal = SIGQUIT}, + {.keycode = KEY_0, .signal = SIGTSTP} + }; + int signal; + + // Check signal sending request + if (keyboard->mode.ctrl == 0) + return; + + // Try to find the signal to send + signal = -1; + for (int i = 0 ; i < 3 ; ++i) { + if (echapment[i].keycode != keyboard->saved.signal.keycode) + continue; + signal = echapment[i].signal; + break; + } + if (signal == -1) + return; + + // Remove the cheracter + if (keyboard->saved.signal.cursor > 0) + { + // Move seconde part. + memcpy( + &keyboard->buffer.addr[keyboard->buffer.cursor - 1], + &keyboard->buffer.addr[keyboard->buffer.cursor], + keyboard->buffer.clen - keyboard->buffer.cursor + ); + + // Add null char and update clen. + keyboard->buffer.clen = keyboard->buffer.clen - 1; + keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; + keyboard->buffer.cursor = keyboard->buffer.cursor - 1; + } + + // Send signal + signal_raise(process_current, signal); } // TODO: move me @@ -107,20 +157,26 @@ static int check_special(struct keyboard_obj_s *keyboard, key_t key) extern fx9860_context_t casio_context; extern fx9860_context_t vhex_context; - // Check MAJ. + // Check CTRL key (KEY_OPT) + if (key == KEY_OPTN) { + keyboard->mode.ctrl = 1; + return (1); + } + + // Check MAJ. if (key == KEY_ALPHA) { - keyboard->mode = keyboard->mode ^ 0x02; + keyboard->mode.maj ^= 1; return (1); } - // Check Alpha / num mode. + // Check Alpha / num mode. (special) if (key == KEY_SHIFT) { - keyboard->mode = keyboard->mode ^ 0x01; + keyboard->mode.special ^= 0x01; return (1); } - // Check space key - if (key == KEY_DOT && (keyboard->mode & 1) == 0) { + // Check space key (workaround) + if (key == KEY_DOT && keyboard->mode.special == 0) { buffer_insert(keyboard, ' '); return (1); } @@ -177,7 +233,7 @@ static int check_special(struct keyboard_obj_s *keyboard, key_t key) keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; // indicate that the EXE has been pressed. - keyboard->mode = keyboard->mode | 0x04; + keyboard->mode.enter = 1; return (1); } @@ -216,10 +272,9 @@ static void tty_buffer_display(struct keyboard_obj_s *keyboard) keyboard->tty->cursor.y = keyboard->saved.tty.cursor.y; // Workaround for [EXE] key. - size = - ((keyboard->mode & 0x04) == 0) - ? keyboard->buffer.clen + 1 - : keyboard->buffer.clen; + size = keyboard->buffer.clen; + if (keyboard->mode.enter == 0) + size = keyboard->buffer.clen + 1; // Write buffer. tty_write(keyboard->tty, keyboard->buffer.addr, size); @@ -248,10 +303,9 @@ static int update_buffer(struct keyboard_obj_s *keyboard, key_t key) int i; // Get the appropriate key list. - keycode_list = - ((keyboard->mode & 1) == 0) - ? keylist_alpha - : keylist_num; + keycode_list = keylist_alpha; + if (keyboard->mode.special == 1) + keycode_list = keylist_num; // Try to find the pressed key. i = -1; @@ -259,12 +313,14 @@ static int update_buffer(struct keyboard_obj_s *keyboard, key_t key) if (keycode_list[i] != key) return (0); - // If the key match, update buffer. - // Get the char to be written - if ((keyboard->mode & 1) == 0) - character = (keyboard->mode & 2) ? 'A' + i : 'a' + i; - else - character = keylist_num_char[i]; + // If the key match, update buffer and get the + // character to be written + character = keylist_num_char[i]; + if (keyboard->mode.special == 0) { + character = 'a' + i; + if (keyboard->mode.maj == 1) + character = 'A' + i;; + } // Insert new character if possible. buffer_insert(keyboard, character); diff --git a/src/kernel/memory/page/free.c b/src/kernel/memory/page/free.c index d9df400..dc5463e 100644 --- a/src/kernel/memory/page/free.c +++ b/src/kernel/memory/page/free.c @@ -54,7 +54,7 @@ void pm_pages_free(void *ptr) // No block found, display error. earlyterm_write( "pm_free: Warning, you try to free unused" - "allocated memory (%p)", sptr + "/ allocated memory (%p)\n", sptr ); DBG_WAIT; diff --git a/src/kernel/scheduler/process/create.c b/src/kernel/scheduler/process/create.c index 0741f7d..f5d8e74 100644 --- a/src/kernel/scheduler/process/create.c +++ b/src/kernel/scheduler/process/create.c @@ -104,6 +104,7 @@ static void proc_signal_init(struct process *proc) proc->signal[SIGTERM] = SIG_DFL; proc->signal[SIGKILL] = SIG_DFL; proc->signal[SIGSEGV] = SIG_DFL; + proc->signal[SIGINT] = SIG_DFL; proc->signal[SIGHUP] = SIG_IGN; proc->signal[SIGFPE] = SIG_DFL; } diff --git a/src/kernel/scheduler/process/terminate.c b/src/kernel/scheduler/process/terminate.c index 243b4bd..b6b7ad3 100644 --- a/src/kernel/scheduler/process/terminate.c +++ b/src/kernel/scheduler/process/terminate.c @@ -6,7 +6,7 @@ void process_terminate(struct process *proc, int __stat_lock) { - struct pm_heap_page *page; + struct pm_heap_page **page; void *tmp; // Start atomic operation @@ -19,17 +19,22 @@ void process_terminate(struct process *proc, int __stat_lock) vfs_close(&proc->opfile[i].file); } - // Frre'd all allocated space + // Free'd all allocated space pm_pages_free(proc->memory.stack.user); pm_pages_free(proc->memory.stack.kernel); pm_pages_free(proc->memory.program.start); - page = proc->memory.heap; - while (page != NULL) { - tmp = page->next; - pm_pages_free(page); - page = tmp; + page = &proc->memory.heap; + while (*page != NULL) { + tmp = (*page)->next; + pm_pages_free(*page); + *page = tmp; } + // Secure error + proc->memory.stack.user = NULL; + proc->memory.stack.kernel = NULL; + proc->memory.program.start = NULL; + // Change scheduler task state proc->sched_task->status = SCHED_TASK_ZOMBIE; diff --git a/src/kernel/scheduler/schedule.c b/src/kernel/scheduler/schedule.c index 8222af0..ad52dbf 100644 --- a/src/kernel/scheduler/schedule.c +++ b/src/kernel/scheduler/schedule.c @@ -20,7 +20,7 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex { // Check process validity if (task_next->status == SCHED_TASK_RUNNING - && signal_deliver_pending((void*)process_current) == 0) + && signal_deliver_pending(task_next->process) == 0) break; // Get next task diff --git a/src/kernel/scheduler/syscall/sys_exit.c b/src/kernel/scheduler/syscall/sys_exit.c index 09f60fe..6a20e3b 100644 --- a/src/kernel/scheduler/syscall/sys_exit.c +++ b/src/kernel/scheduler/syscall/sys_exit.c @@ -1,4 +1,5 @@ #include +#include #include void sys_exit(int status) diff --git a/src/kernel/signal/deliver.c b/src/kernel/signal/deliver.c index ee4bf73..2078414 100644 --- a/src/kernel/signal/deliver.c +++ b/src/kernel/signal/deliver.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -29,6 +31,7 @@ static int sig_deliver(struct process *proc, int sig) /* Process terination (default) */ case SIGTERM: // termination + case SIGINT: // interruption case SIGHUP: // hang up case SIGKILL: // kill case SIGBUS: // bus error @@ -52,6 +55,13 @@ int signal_deliver_pending(struct process *proc) int need_schedule; uint32_t sig; + // Check process valitidy + if (proc->sched_task->status != SCHED_TASK_RUNNING) + return (-1); + + // Start atomic operation + atomic_start(); + // Get all pending signals sig = proc->sig_pending & (~proc->sig_blocked); @@ -65,11 +75,14 @@ int signal_deliver_pending(struct process *proc) // Check signal validity and try to // deliver the signal - if (proc->signal[i] != __SIGUNDEF) - sig_deliver(proc, i); + if (proc->signal[i + 1] != __SIGUNDEF) + need_schedule = sig_deliver(proc, i + 1); // Clear the signal mask proc->sig_pending = proc->sig_pending & (~i); } + + // Stop atomic operation + atomic_stop(); return (need_schedule); } diff --git a/src/kernel/signal/raise.c b/src/kernel/signal/raise.c index 0e355b0..0cda449 100644 --- a/src/kernel/signal/raise.c +++ b/src/kernel/signal/raise.c @@ -2,6 +2,7 @@ #include #include #include +#include #include int signal_raise(struct process *proc, int sig) diff --git a/src/user/shell/builtin/proc.c b/src/user/shell/builtin/proc.c index c084075..5ca005d 100644 --- a/src/user/shell/builtin/proc.c +++ b/src/user/shell/builtin/proc.c @@ -2,18 +2,14 @@ #include #include #include "builtin.h" +#include "util.h" -int builtin_proc(void) +int builtin_proc(int argc, char **argv) { - char *argv[2] = {"test", NULL}; pid_t child; - int wstatus; - - //puts("proc test entry :)\n"); - //printf(" PPID PID PGID\n"); - //printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid()); // Try to create first child + (void)argc; child = fexecve("/mnt/casio/VHEX/test.elf", argv, NULL); if (child == -1) { @@ -21,8 +17,7 @@ int builtin_proc(void) return (0); } - // Wait child death - waitpid(child, &wstatus, 0); - printf("+++ exited with %d +++\n", WEXITSTATUS(wstatus)); + // Wait child process + wait_child(child); return (0); } diff --git a/src/user/shell/main.c b/src/user/shell/main.c index 79b1d3c..b14f04b 100644 --- a/src/user/shell/main.c +++ b/src/user/shell/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "util.h" @@ -13,6 +14,13 @@ int main(void) // Shell main loop. write(STDOUT_FILENO, "Boot Complete !\n", 16); + + // Ignore internal signals (keyboard) + //signal(SIGINT, SIG_IGN); + //signal(SIGQUIT, SIG_IGN); + //signal(SIGTSTP, SIG_IGN); + + // Main loop while (1) { // Get user command. diff --git a/src/user/shell/util/manual_proc_call.c b/src/user/shell/util/manual_proc_call.c index 9cd0c7d..d14831d 100644 --- a/src/user/shell/util/manual_proc_call.c +++ b/src/user/shell/util/manual_proc_call.c @@ -8,12 +8,8 @@ int manual_proc_call(char **argv) { char pathname[32]; - int wstatus; pid_t child; - printf("try to call '%s'\n", argv[0]); - for(int i = 0 ; i < 30000000 ; ++i); - // Generate pathname // TODO: handle PATH strcpy(pathname, "/mnt/casio/VHEX/"); @@ -21,11 +17,12 @@ int manual_proc_call(char **argv) // Try to call binary from eeprom printf("try to call '%s'\n", pathname); - for(int i = 0 ; i < 30000000 ; ++i); + for(int i = 0 ; i < 3000000 ; ++i); child = fexecve(pathname, argv, NULL); if (child != 0) return (-1); - waitpid(child, &wstatus, 0); + // Wait child process + wait_child(child); return (0); } diff --git a/src/user/shell/util/wait_child.c b/src/user/shell/util/wait_child.c new file mode 100644 index 0000000..66e3847 --- /dev/null +++ b/src/user/shell/util/wait_child.c @@ -0,0 +1,72 @@ +#include "util.h" +#include +#include +#include +#include + +// TODO: libc +const char *signal_str[NSIG] = { + "SIGHUP", + "SIGINT", + "SIGQUIT", + "SIGILL", + "SIGTRAP", + "SIGABRT", + NULL, + "SIGFPE", + "SIGKILL", + "SIGBUS", + "SIGSEGV", + "SIGSYS", + "SIGPIPE", + "SIGALARM", + "SIGURG", + "SIGSTOP", + "SIGTSTP", + "SIGCONT", + "SIGCHLD", + "SIGTTIN", + "SIGTTOU", + "SIGPOLL", + "SIGXCPU", + "SIGXFSZ", + "SIGVTALRM", + "SIGPROF", + "SIGUSR1", + "SIGUSR2" +}; + +void wait_child(pid_t pid) +{ + int wstatus; + + // Wait child death + waitpid(pid, &wstatus, 0); + + // FIXME: workaround dto display + printf("\n"); + + // Check exit() return + if (WIFEXITED(wstatus)) + { + wstatus = WEXITSTATUS(wstatus); + if (wstatus != 0) + printf("[%d]", wstatus); + return; + } + + // Check sigals + if (WIFSTOPPED(wstatus)) + { + wstatus = WSTOPSIG(wstatus) - 1; + if (wstatus < 0 || wstatus >= NSIG) { + printf("+++ unknown signal %d +++\n", wstatus); + return; + } + printf("[%s]", signal_str[wstatus]); + return; + } + + // Error, unknown + printf("+++ unknown value %d +++\n", wstatus); +} diff --git a/src/user/test/test.c b/src/user/test/test.c index e7dd657..3c97830 100644 --- a/src/user/test/test.c +++ b/src/user/test/test.c @@ -2,33 +2,6 @@ #include #include -/*static int tree(const char *pathname) -{ - struct dirent dir; - int ret; - int fd; - - // Open directory - fd = open(pathname, O_RDONLY | O_DIRECTORY); - if (fd < 0) { - dprintf(STDERR_FILENO, "tree: Cannot open directory '%s'\n", pathname); - return (2); - } - - ret = 0; - while (1) - { - // Get dirent - read = sys_getdents(fd, &dir, sizeof(struct dirent)); - if (read <= 0) - return ((read == 0) ? 0 : 84); - - - } - - return (0); -}*/ - int main(int argc, char **argv) { char c[1024]; @@ -38,7 +11,7 @@ int main(int argc, char **argv) // Check parameters for (int i = 0 ; i < argc ; i++) printf("argv[%d]: %s\n", i, argv[i]); - for(int i = 0 ; i < 3000000 ; ++i); + for(int i = 0 ; i < 1000000 ; ++i); // Read test fd = open("/mnt/casio/VHEX/text.txt", O_RDONLY); @@ -47,6 +20,7 @@ int main(int argc, char **argv) return (84); } + // DIsplay file while (1) { ret = read(fd, c, 1024); @@ -54,14 +28,10 @@ int main(int argc, char **argv) break; write(STDOUT_FILENO, c, ret); } + + // Wait signal + // TODO: better signal management (kernel) + printf("wait signal....\n"); + while (read(STDIN_FILENO, c, 3) != 4); return (0); } - - - -// setpgid(0, 12); -// printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid()); -// printf("child proc fini...try to exit\n"); -// for(int i = 0 ; i < 3000000 ; ++i); -// return (84); -//}