2012-02-08 12:40:44 +04:00
|
|
|
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
|
|
*
|
|
|
|
* Signal Handling
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <system.h>
|
|
|
|
#include <signal.h>
|
2013-03-21 08:24:55 +04:00
|
|
|
#include <logging.h>
|
2012-02-08 12:40:44 +04:00
|
|
|
|
|
|
|
void enter_signal_handler(uintptr_t location, int signum, uintptr_t stack) {
|
2012-02-09 05:30:35 +04:00
|
|
|
IRQ_OFF;
|
2012-02-08 12:40:44 +04:00
|
|
|
asm volatile(
|
|
|
|
"mov %2, %%esp\n"
|
|
|
|
"pushl %1\n" /* argument count */
|
2012-02-16 06:50:31 +04:00
|
|
|
"pushl $" STRSTR(SIGNAL_RETURN) "\n"
|
2012-02-08 12:40:44 +04:00
|
|
|
"mov $0x23, %%ax\n" /* Segment selector */
|
|
|
|
"mov %%ax, %%ds\n"
|
|
|
|
"mov %%ax, %%es\n"
|
|
|
|
"mov %%ax, %%fs\n"
|
|
|
|
"mov %%ax, %%gs\n"
|
|
|
|
"mov %%esp, %%eax\n" /* Stack -> EAX */
|
|
|
|
"pushl $0x23\n" /* Segment selector again */
|
|
|
|
"pushl %%eax\n"
|
|
|
|
"pushf\n" /* Push flags */
|
|
|
|
"popl %%eax\n" /* Fix the Interrupt flag */
|
|
|
|
"orl $0x200, %%eax\n"
|
|
|
|
"pushl %%eax\n"
|
|
|
|
"pushl $0x1B\n"
|
|
|
|
"pushl %0\n" /* Push the entry point */
|
|
|
|
"iret\n"
|
|
|
|
: : "m"(location), "m"(signum), "r"(stack) : "%ax", "%esp", "%eax");
|
2012-02-17 08:43:41 +04:00
|
|
|
|
2014-04-06 02:23:17 +04:00
|
|
|
debug_print(CRITICAL, "Failed to jump to signal handler!");
|
2012-02-08 12:40:44 +04:00
|
|
|
}
|
|
|
|
|
2014-03-16 07:05:07 +04:00
|
|
|
static uint8_t volatile sig_lock;
|
|
|
|
static uint8_t volatile sig_lock_b;
|
2012-02-17 11:21:11 +04:00
|
|
|
|
2013-05-06 02:00:24 +04:00
|
|
|
char isdeadly[] = {
|
|
|
|
0, /* 0? */
|
|
|
|
1, /* SIGHUP */
|
|
|
|
1, /* SIGINT */
|
|
|
|
2, /* SIGQUIT */
|
|
|
|
2, /* SIGILL */
|
|
|
|
2, /* SIGTRAP */
|
|
|
|
2, /* SIGABRT */
|
|
|
|
2, /* SIGEMT */
|
|
|
|
2, /* SIGFPE */
|
|
|
|
1, /* SIGKILL */
|
|
|
|
2, /* SIGBUS */
|
|
|
|
2, /* SIGSEGV */
|
|
|
|
2, /* SIGSYS */
|
|
|
|
1, /* SIGPIPE */
|
|
|
|
1, /* SIGALRM */
|
|
|
|
1, /* SIGTERM */
|
|
|
|
1, /* SIGUSR1 */
|
|
|
|
1, /* SIGUSR2 */
|
|
|
|
0, /* SIGCHLD */
|
|
|
|
0, /* SIGPWR */
|
|
|
|
0, /* SIGWINCH */
|
|
|
|
0, /* SIGURG */
|
|
|
|
0, /* SIGPOLL */
|
|
|
|
3, /* SIGSTOP */
|
|
|
|
3, /* SIGTSTP */
|
|
|
|
0, /* SIGCONT */
|
|
|
|
3, /* SIGTTIN */
|
|
|
|
3, /* SIGTTOUT */
|
|
|
|
1, /* SIGVTALRM */
|
|
|
|
1, /* SIGPROF */
|
|
|
|
2, /* SIGXCPU */
|
|
|
|
2, /* SIGXFSZ */
|
|
|
|
0, /* SIGWAITING */
|
|
|
|
1, /* SIGDIAF */
|
|
|
|
0, /* SIGHATE */
|
|
|
|
0, /* SIGWINEVENT*/
|
|
|
|
0, /* SIGCAT */
|
|
|
|
};
|
|
|
|
|
2012-02-08 12:40:44 +04:00
|
|
|
void handle_signal(process_t * proc, signal_t * sig) {
|
2012-03-10 23:36:16 +04:00
|
|
|
uintptr_t handler = sig->handler;
|
|
|
|
uintptr_t signum = sig->signum;
|
|
|
|
free(sig);
|
|
|
|
|
2012-02-09 06:09:28 +04:00
|
|
|
if (proc->finished) {
|
|
|
|
return;
|
|
|
|
}
|
2012-02-08 12:40:44 +04:00
|
|
|
|
2013-05-06 02:00:24 +04:00
|
|
|
if (signum == 0 || signum >= NUMSIGNALS) {
|
2012-02-12 04:27:28 +04:00
|
|
|
/* Ignore */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-10 23:36:16 +04:00
|
|
|
if (!handler) {
|
2013-05-06 02:00:24 +04:00
|
|
|
char dowhat = isdeadly[signum];
|
|
|
|
if (dowhat == 1 || dowhat == 2) {
|
|
|
|
debug_print(WARNING, "Process %d killed by unhandled signal (%d)", proc->id, signum);
|
|
|
|
kexit(128 + signum);
|
|
|
|
__builtin_unreachable();
|
|
|
|
} else {
|
|
|
|
debug_print(WARNING, "Ignoring signal %d by default in pid %d", signum, proc->id);
|
|
|
|
}
|
|
|
|
/* XXX dowhat == 2: should dump core */
|
|
|
|
/* XXX dowhat == 3: stop */
|
2012-02-08 12:40:44 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-10 23:36:16 +04:00
|
|
|
if (handler == 1) /* Ignore */ {
|
2012-02-08 12:40:44 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-21 08:24:55 +04:00
|
|
|
debug_print(NOTICE, "handling signal in process %d (%d)", proc->id, signum);
|
|
|
|
|
2012-02-13 04:47:01 +04:00
|
|
|
uintptr_t stack = 0xFFFF0000;
|
|
|
|
if (proc->syscall_registers->useresp < 0x10000100) {
|
|
|
|
stack = proc->image.user_stack;
|
|
|
|
} else {
|
|
|
|
stack = proc->syscall_registers->useresp;
|
|
|
|
}
|
2012-02-08 12:40:44 +04:00
|
|
|
|
|
|
|
/* Not marked as ignored, must call signal */
|
2012-03-10 22:47:33 +04:00
|
|
|
enter_signal_handler(handler, signum, stack);
|
2012-02-08 12:40:44 +04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
list_t * rets_from_sig;
|
|
|
|
|
2013-06-06 10:10:36 +04:00
|
|
|
void return_from_signal_handler(void) {
|
2012-02-17 08:43:41 +04:00
|
|
|
#if 0
|
2014-04-06 02:23:17 +04:00
|
|
|
debug_print(INFO, "Return From Signal for process %d", current_process->id);
|
2012-02-17 08:43:41 +04:00
|
|
|
#endif
|
2012-02-08 12:40:44 +04:00
|
|
|
|
|
|
|
if (__builtin_expect(!rets_from_sig, 0)) {
|
|
|
|
rets_from_sig = list_create();
|
|
|
|
}
|
|
|
|
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_lock(&sig_lock);
|
2012-02-09 02:07:54 +04:00
|
|
|
list_insert(rets_from_sig, (process_t *)current_process);
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_unlock(&sig_lock);
|
2012-02-08 12:40:44 +04:00
|
|
|
|
|
|
|
switch_next();
|
|
|
|
}
|
|
|
|
|
2013-06-06 10:10:36 +04:00
|
|
|
void fix_signal_stacks(void) {
|
2012-02-09 06:09:28 +04:00
|
|
|
uint8_t redo_me = 0;
|
2012-02-08 12:40:44 +04:00
|
|
|
if (rets_from_sig) {
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_lock(&sig_lock_b);
|
2012-02-08 12:40:44 +04:00
|
|
|
while (rets_from_sig->head) {
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_lock(&sig_lock);
|
2012-02-08 12:40:44 +04:00
|
|
|
node_t * n = list_dequeue(rets_from_sig);
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_unlock(&sig_lock);
|
2012-02-17 11:21:11 +04:00
|
|
|
if (!n) {
|
|
|
|
continue;
|
|
|
|
}
|
2012-02-08 12:40:44 +04:00
|
|
|
process_t * p = n->value;
|
2012-02-09 06:09:28 +04:00
|
|
|
free(n);
|
|
|
|
if (p == current_process) {
|
|
|
|
redo_me = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2012-02-08 12:40:44 +04:00
|
|
|
p->thread.esp = p->signal_state.esp;
|
|
|
|
p->thread.eip = p->signal_state.eip;
|
|
|
|
p->thread.ebp = p->signal_state.ebp;
|
2012-02-09 02:07:54 +04:00
|
|
|
memcpy((void *)(p->image.stack - KERNEL_STACK_SIZE), p->signal_kstack, KERNEL_STACK_SIZE);
|
2012-02-08 12:40:44 +04:00
|
|
|
free(p->signal_kstack);
|
2012-02-21 09:31:00 +04:00
|
|
|
p->signal_kstack = NULL;
|
2012-02-08 12:40:44 +04:00
|
|
|
make_process_ready(p);
|
|
|
|
}
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_unlock(&sig_lock_b);
|
2012-02-08 12:40:44 +04:00
|
|
|
}
|
2012-02-09 06:09:28 +04:00
|
|
|
if (redo_me) {
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_lock(&sig_lock);
|
2012-02-09 06:09:28 +04:00
|
|
|
list_insert(rets_from_sig, (process_t *)current_process);
|
2014-03-16 07:05:07 +04:00
|
|
|
spin_unlock(&sig_lock);
|
2012-02-17 11:21:11 +04:00
|
|
|
switch_next();
|
2012-02-09 06:09:28 +04:00
|
|
|
}
|
2012-02-08 12:40:44 +04:00
|
|
|
}
|