signal (part 1)

This commit is contained in:
Tomoki Shirasawa
2014-01-07 11:57:57 +09:00
parent 9e00275120
commit a8c249ddaf
11 changed files with 224 additions and 72 deletions

View File

@ -368,7 +368,7 @@ void setup_x86_ap(void (*next_func)(void))
}
void arch_show_interrupt_context(const void *reg);
void set_signal(int, void *);
void set_signal(int, void *, int);
void check_signal(long, void *);
void handle_interrupt(int vector, struct x86_regs *regs)
@ -409,7 +409,7 @@ void gpe_handler(struct x86_regs *regs)
kprintf("General protection fault (err: %lx, %lx:%lx)\n",
regs->error, regs->cs, regs->rip);
arch_show_interrupt_context(regs);
set_signal(SIGILL, regs);
set_signal(SIGILL, regs, 1);
check_signal(0, regs);
// panic("GPF");
}

View File

@ -15,10 +15,19 @@
#define _NSIG_BPW 64
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef unsigned long int __sigset_t;
#define __sigmask(sig) (((__sigset_t) 1) << ((sig) - 1))
# define _SIGSET_NWORDS (1024 / (8 * sizeof (__sigset_t)))
typedef struct {
unsigned long sig[_NSIG_WORDS];
__sigset_t __val[_SIGSET_NWORDS];
} sigset_t;
#define SIG_BLOCK 0
#define SIG_UNBLOCK 1
#define SIG_SETMASK 2
struct sigaction {
void (*sa_handler)(int);
unsigned long sa_flags;
@ -30,6 +39,76 @@ struct k_sigaction {
struct sigaction sa;
};
struct sigstack {
void *ss_sp;
int ss_onstack;
};
typedef struct sigaltstack {
void *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
typedef union sigval {
int sival_int;
void *sival_ptr;
} sigval_t;
#define __SI_MAX_SIZE 128
#define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4)
typedef struct siginfo {
int si_signo; /* Signal number. */
int si_errno; /* If non-zero, an errno value associated with
this signal, as defined in <errno.h>. */
int si_code; /* Signal code. */
union {
int _pad[__SI_PAD_SIZE];
/* kill(). */
struct {
int si_pid;/* Sending process ID. */
int si_uid;/* Real user ID of sending process. */
} _kill;
/* POSIX.1b timers. */
struct {
int si_tid; /* Timer ID. */
int si_overrun; /* Overrun count. */
sigval_t si_sigval; /* Signal value. */
} _timer;
/* POSIX.1b signals. */
struct {
int si_pid; /* Sending process ID. */
int si_uid; /* Real user ID of sending process. */
sigval_t si_sigval; /* Signal value. */
} _rt;
/* SIGCHLD. */
struct {
int si_pid; /* Which child. */
int si_uid; /* Real user ID of sending process. */
int si_status; /* Exit value or signal. */
long si_utime;
long si_stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
struct {
void *si_addr; /* Faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL. */
struct {
long int si_band; /* Band event for SIGPOLL. */
int si_fd;
} _sigpoll;
} _sifields;
} siginfo_t;
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3

View File

@ -64,6 +64,7 @@ SYSCALL_HANDLED(129, rt_sigqueueinfo)
SYSCALL_HANDLED(130, rt_sigsuspend)
SYSCALL_HANDLED(131, sigaltstack)
SYSCALL_HANDLED(158, arch_prctl)
SYSCALL_HANDLED(186, gettid)
SYSCALL_DELEGATED(201, time)
SYSCALL_HANDLED(202, futex)
SYSCALL_HANDLED(203, sched_setaffinity)

View File

@ -98,8 +98,9 @@ SYSCALL_DECLARE(rt_sigreturn)
}
extern struct cpu_local_var *clv;
extern unsigned long do_kill(int pid, int sig);
extern void interrupt_syscall();
extern unsigned long do_kill(int pid, int tid, int sig);
extern void interrupt_syscall(int all);
extern int num_processors;
void
check_signal(unsigned long rc, unsigned long *regs)
@ -136,7 +137,6 @@ check_signal(unsigned long rc, unsigned long *regs)
if(regs[14] & 0x8000000000000000){ // kernel addr
proc->signal = sig;
interrupt_syscall();
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
return;
}
@ -162,36 +162,76 @@ check_signal(unsigned long rc, unsigned long *regs)
}
unsigned long
do_kill(int pid, int sig)
do_kill(int pid, int tid, int sig)
{
struct process *proc = cpu_local_var(current);
struct process *tproc = NULL;
int i;
if(proc == NULL || proc->pid == 0){
return -ESRCH;
}
if(proc->pid == pid){
proc->signal = sig;
return 0;
}
if(pid <= 0){
if(sig > 64 || sig < 0)
return -EINVAL;
if(tid == -1){
if(pid == proc->pid || pid <= 0){
tproc = proc;
}
}
if(sig == 0){
return 0;
else if(pid == -1){
for(i = 0; i < num_processors; i++)
if(get_cpu_local_var(i)->current &&
get_cpu_local_var(i)->current->pid > 0 &&
get_cpu_local_var(i)->current->tid == tid){
tproc = get_cpu_local_var(i)->current;
break;
}
}
else{
return -EPERM;
if(pid == 0)
return -ESRCH;
for(i = 0; i < num_processors; i++)
if(get_cpu_local_var(i)->current &&
get_cpu_local_var(i)->current->pid == pid &&
get_cpu_local_var(i)->current->tid == tid){
tproc = get_cpu_local_var(i)->current;
break;
}
}
if(!tproc)
return -ESRCH;
if(sig == 0)
return 0;
if(__sigmask(sig) & proc->sigmask.__val[0]){
// TODO: masked signal: ignore -> pending
return 0;
}
proc->signal = sig;
interrupt_syscall(1);
return 0;
}
void
set_signal(int sig, unsigned long *regs)
set_signal(int sig, unsigned long *regs, int nonmaskable)
{
struct process *proc = cpu_local_var(current);
if(proc == NULL || proc->pid == 0)
return;
if(__sigmask(sig) & proc->sigmask.__val[0]){
if(nonmaskable){
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
}
else{
// TODO: masked signal: ignore -> pending
return;
}
}
proc->signal = sig;
interrupt_syscall();
interrupt_syscall(1);
}