#include <arch.h>
#include <debug.h>
#include <process.h>
+#include <signal.h>
#include "fd.h"
#include "sched.h"
int p_status;
struct fd p_fds[16];
+
+ sighandler_t p_sighandler[32];
};
struct proc_list {
process_t *proc;
};
+/*
+ * Possible actions:
+ * - TERM: Terminate process
+ * - IGN: Ignore signal
+ * - CORE: TERM + core dump
+ * - STOP: Stop process
+ * - CONT: Continue stopped process
+ */
+
+static void _sig_term(int);
+static void _sig_ign(int);
+static void _sig_core(int);
+static void _sig_stop(int);
+static void _sig_cont(int);
+
+#define TERM _sig_term
+#define IGN _sig_ign
+#define CORE _sig_core
+#define STOP _sig_stop
+#define CONT _sig_cont
+
+/*
+ * Defaults from man 7 signal:
+ * SIGNAL | ACTION
+ * -----------+--------
+ * SIGHUP | TERM
+ * SIGINT | TERM
+ * SIGQUIT | CORE
+ * SIGILL | CORE
+ * SIGABRT | CORE
+ * SIGFPE | CORE
+ * SIGKILL | TERM
+ * SIGSEGV | CORE
+ * SIGPIPE | TERM
+ * SIGALRM | TERM
+ * SIGTERM | TERM
+ * SIGUSR1 | TERM
+ * SIGUSR2 | TERM
+ * SIGCHLD | IGN
+ * SIGCONT | CONT
+ * SIGSTOP | STOP
+ * SIGTSTP | STOP
+ * SIGTTIN | STOP
+ * SIGTTOU | STOP
+ * SIGBUS | CORE
+ * SIGPROF | TERM
+ * SIGSYS | CORE
+ * SIGTRAP | CORE
+ * SIGURG | IGN
+ * SIGVTALRM | TERM
+ * SIGXCPU | CORE
+ * SIGXFSZ | CORE
+ * SIGIOT | CORE
+ * SIGEMT | TERM
+ * SIGSTKFLT | TERM
+ * SIGIO | TERM
+ * SIGCLT | IGN
+ * SIGPWR | TERM
+ * SIGLOST | TERM
+ * SIGWINCH | IGN
+ * SIGUNUSED | CORE
+ */
+
+/* default signal handlers */
+const static sighandler_t _sig_dfl[] = {
+ CORE, /* 0 is not defined in the standards */
+ TERM, TERM, CORE, CORE, CORE, CORE, CORE, CORE,
+ TERM, TERM, CORE, TERM, TERM, TERM, TERM, TERM,
+ IGN, CONT, STOP, STOP, STOP, STOP, IGN, CORE,
+ CORE, TERM, TERM, IGN, TERM, TERM, CORE, CORE
+};
+
static pid_t _next_pid = 100;
static struct proc_list *_procs;
goto cleanup;
}
+ /* set the default signal handlers */
+ memcpy(proc->p_sighandler, _sig_dfl, sizeof(proc->p_sighandler));
+
proc->p_privl = ppl;
proc->p_pid = ppid;
return(ret_val);
}
+
+int process_kill(process_t pid, int signal)
+{
+
+}
+
+int process_signal_deliver(process_t *proc, int signal)
+{
+ int ret_val;
+
+ ret_val = -EINVAL;
+
+ if(proc && signal > 0 && signal <= SIGUNUSED) {
+ stack_frame_t *kstk;
+ u32_t *vesp3;
+ u32_t *pesp3;
+ task_t *task;
+
+ /* FIXME: Need to suspend the process in order to deliver the signal safely */
+
+ /*
+ * Elect a task to handle the signal - right now, this is simple since the
+ * implementation doesn't support more than one task per process, and we
+ * can just pick the first (and only) one.
+ */
+ task = proc->p_tasks;
+ kstk = (stack_frame_t*)task->t_sp;
+
+ /*
+ * Get usable pointers to the task's stacks. The t_sp member holds the
+ * address of the kernel-mode stack that is valid inside of the kernel, so
+ * we can use it without having to perform any translations. The usermode
+ * stack will have to be translated though.
+ */
+ vesp3 = (u32_t*)kstk->prevesp;
+ ret_val = _pg_dir_vpxlate((struct pagedir*)task->t_pgdir,
+ (u32_t)vesp3, (u32_t*)&pesp3);
+
+ if(!ret_val) {
+ u32_t *parg0;
+ u32_t *peip;
+
+ /* push the signal number and the return address on the userspace stack */
+
+ /*
+ * pesp3, pesp3 - 1, and pesp3 - 2 may not be on the same page, which would
+ * be an atrociously hard-to-find bug.
+ */
+#define PAGE_BASE(__addr) ((u32_t)__addr & ~(PAGE_SIZE - 1))
+#define SAME_PAGE(__x,__y) (PAGE_BASE(__x) == PAGE_BASE(__y))
+
+ if(SAME_PAGE(vesp3, (vesp3 - 1))) {
+ parg0 = vesp3 - 1;
+ } else {
+ ret_val = _pg_dir_vpxlate((struct pagedir*)task->t_pgdir,
+ (u32_t)(vesp3 - 1), (u32_t*)&parg0);
+
+ if(ret_val < 0) {
+ goto cleanup;
+ }
+ }
+
+ if(SAME_PAGE(vesp3, (vesp3 - 2))) {
+ peip = vesp3 - 2;
+ } else {
+ ret_val = _pg_dir_vpxlate((struct pagedir*)task->t_pgdir,
+ (u32_t)(vesp3 - 2), (u32_t*)&peip);
+
+ if(ret_val < 0) {
+ goto cleanup;
+ }
+ }
+
+ *parg0 = (u32_t)signal;
+ *peip = (u32_t)kstk->eip;
+
+ /*
+ * Once the task is suspended, it will be somewhere inside the kernel. This
+ * means we can now modify the stack that the task will use to return to
+ * userspace once it is continued.
+ */
+ kstk->eip = (u32_t)proc->p_sighandler[signal];
+ kstk->prevesp -= (sizeof(kstk->prevesp) * 2);
+ }
+
+ /* let the process continue execution */
+
+ ret_val = 0;
+ }
+
+cleanup:
+ return(ret_val);
+}
+
+static void _sig_term(int sig)
+{
+ process_t *cproc;
+
+ cproc = process_get_current();
+
+ /* FIXME: terminate the process */
+
+ return;
+}
+
+static void _sig_ign(int sig)
+{
+ /* do nothing */
+ return;
+}
+
+static void _sig_core(int sig)
+{
+ process_t *cproc;
+
+ cproc = process_get_current();
+
+ /* FIXME: terminate process and generate a core dump */
+
+ return;
+}
+
+static void _sig_stop(int sig)
+{
+ process_t *cproc;
+
+ cproc = process_get_current();
+
+ /*
+ * FIXME: Stop the process
+ * - Change the process state
+ * - Change the state of all of its tasks
+ * - Stop running tasks
+ * - Place all of its tasks on the wait queue
+ *
+ * Or better yet, make it wait on a lock in the stop handler.
+ */
+
+ return;
+}
+
+static void _sig_cont(int sig)
+{
+ process_t *cproc;
+
+ cproc = process_get_current();
+
+ /*
+ * FIXME: Continue the process
+ * - Change its state back to a runnable state
+ * - Change the state of all of its tasks
+ * - Place tasks on the ready queue
+ *
+ * Or better yet, release the lock that they should have been
+ * waiting on in the stop handler.
+ */
+ return;
+}