Add TTY's signals request + update shell process waiting

This commit is contained in:
Yann MAGNIN 2020-04-21 20:56:27 +02:00
parent 8cf62fc496
commit 7140bb1631
18 changed files with 245 additions and 129 deletions

View File

@ -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 !

View File

@ -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__*/

View File

@ -8,13 +8,13 @@
#include <bits/waitstatus.h>
/* 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

View File

@ -4,22 +4,6 @@
#include <stddef.h>
#include <stdint.h>
// 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);

View File

@ -3,10 +3,12 @@
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
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__*/

View File

@ -6,10 +6,12 @@
#include <kernel/util/casio.h>
#include <kernel/context.h>
#include <kernel/syscall.h>
#include <kernel/signal.h>
#include <lib/string.h>
#include <sys/signal.h>
// 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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -1,4 +1,5 @@
#include <kernel/scheduler.h>
#include <kernel/devices/earlyterm.h>
#include <bits/waitstatus.h>
void sys_exit(int status)

View File

@ -1,5 +1,7 @@
#include <kernel/signal.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
#include <bits/waitstatus.h>
#include <sys/signal.h>
@ -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);
}

View File

@ -2,6 +2,7 @@
#include <kernel/process.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
#include <sys/signal.h>
int signal_raise(struct process *proc, int sig)

View File

@ -2,18 +2,14 @@
#include <stdio.h>
#include <sys/wait.h>
#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);
}

View File

@ -1,5 +1,6 @@
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#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.

View File

@ -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);
}

View File

@ -0,0 +1,72 @@
#include "util.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
// 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);
}

View File

@ -2,33 +2,6 @@
#include <unistd.h>
#include <fcntl.h>
/*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);
//}