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

View File

@@ -501,7 +501,7 @@ static void *main_loop_thread_func(void *arg)
}
void
sendsig(int sig)
sendsig(int sig, siginfo_t *siginfo, void *context)
{
unsigned long param;
@@ -782,8 +782,9 @@ int main(int argc, char **argv)
struct sigaction act;
sigaction(i, NULL, &act);
act.sa_handler = sendsig;
act.sa_sigaction = sendsig;
act.sa_flags &= ~(SA_RESTART);
act.sa_flags |= SA_SIGINFO;
sigaction(i, &act, NULL);
}

View File

@@ -97,6 +97,7 @@ static int process_msg_prepare_process(unsigned long rphys)
return -ENOMEM;
}
proc->pid = pn->pid;
proc->tid = pn->pid;
proc->vm->region.user_start = pn->user_start;
proc->vm->region.user_end = pn->user_end;
proc->rlimit_stack.rlim_cur = pn->rlimit_stack_cur;
@@ -394,7 +395,7 @@ static void syscall_channel_send(struct ihk_ikc_channel_desc *c,
ihk_ikc_send(c, packet, 0);
}
extern unsigned long do_kill(int, int);
extern unsigned long do_kill(int, int, int);
static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
void *__packet, void *ihk_os)
@@ -433,7 +434,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
//cpu_local_var(next) = (struct process *)packet->arg;
return 0;
case SCD_MSG_SEND_SIGNAL:
rc = do_kill((int)packet->arg, (int)(packet->arg >> 32));
rc = do_kill((int)packet->arg, -1, (int)(packet->arg >> 32));
kprintf("SCD_MSG_SEND_SIGNAL: %lx, rc=%d\n", packet->arg, rc);
return 0;
}

View File

@@ -108,14 +108,16 @@ struct process {
unsigned long tlsblock_base, tlsblock_limit;
} thread;
int signal;
sigset_t sigpend;
int tid;
sigset_t sigmask;
int signal;
// sigset_t sigpend;
struct sig_handler *sighandler;
ihk_mc_kernel_context_t sigctx;
char sigstack[512];
// TODO: backup FR and MMX regs
// ihk_mc_kernel_context_t sigctx;
char sigstack[512]; // TODO: 1. move to user stack
// TODO: 2. backup FR and MMX regs
unsigned long sigrc; // return code of rt_sigreturn (x86_64: rax reg.)
struct rlimit rlimit_stack;
pgio_func_t *pgio_fp;
void *pgio_arg;

View File

@@ -203,9 +203,9 @@ struct syscall_params {
SYSCALL_ARG_##a2(2); SYSCALL_ARG_##a3(3); \
SYSCALL_ARG_##a4(4); SYSCALL_ARG_##a5(5);
#define SYSCALL_FOOTER return do_syscall(&request, ctx)
#define SYSCALL_FOOTER return do_syscall(&request, ctx, ihk_mc_get_processor_id())
extern int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx);
extern int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx, int cpu);
extern int obtain_clone_cpuid();
extern long syscall_generic_forwarding(int n, ihk_mc_user_context_t *ctx);

View File

@@ -164,7 +164,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = {
.priv = NULL,
};
void set_signal(int, unsigned long *);
void set_signal(int, unsigned long *, int);
void check_signal(long, unsigned long *);
static void unhandled_page_fault(struct process *proc, void *fault_addr, void *regs)
@@ -234,10 +234,10 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
reason, regs, error);
unhandled_page_fault(proc, fault_addr, regs);
if (error == -ERANGE) {
set_signal(SIGBUS, regs);
set_signal(SIGBUS, regs, 1);
}
else {
set_signal(SIGSEGV, regs);
set_signal(SIGSEGV, regs, 1);
}
check_signal(0, regs);
goto out;

View File

@@ -1379,7 +1379,8 @@ void sched_init(void)
idle_process->vm = &cpu_local_var(idle_vm);
ihk_mc_init_context(&idle_process->ctx, NULL, idle);
idle_process->pid = ihk_mc_get_processor_id();
idle_process->pid = 0;
idle_process->tid = ihk_mc_get_processor_id();
INIT_LIST_HEAD(&cpu_local_var(runq));
cpu_local_var(runq_len) = 0;
@@ -1443,7 +1444,7 @@ void schedule(void)
if (switch_ctx) {
dkprintf("[%d] schedule: %d => %d \n",
ihk_mc_get_processor_id(),
prev ? prev->pid : 0, next ? next->pid : 0);
prev ? prev->tid : 0, next ? next->tid : 0);
ihk_mc_load_page_table(next->vm->page_table);
@@ -1526,8 +1527,8 @@ void __runq_add_proc(struct process *proc, int cpu_id)
proc->status = PS_RUNNING;
get_cpu_local_var(cpu_id)->status = CPU_STATUS_RUNNING;
dkprintf("runq_add_proc(): pid %d added to CPU[%d]'s runq\n",
proc->pid, cpu_id);
dkprintf("runq_add_proc(): tid %d added to CPU[%d]'s runq\n",
proc->tid, cpu_id);
}
void runq_add_proc(struct process *proc, int cpu_id)

View File

@@ -62,7 +62,7 @@
#define ekprintf(...) kprintf(__VA_ARGS__)
#endif
static ihk_atomic_t pid_cnt = IHK_ATOMIC_INIT(1024);
//static ihk_atomic_t pid_cnt = IHK_ATOMIC_INIT(1024);
/* generate system call handler's prototypes */
#define SYSCALL_HANDLED(number,name) extern long sys_##name(int n, ihk_mc_user_context_t *ctx);
@@ -98,7 +98,7 @@ void check_signal(long rc, unsigned long *regs);
static void do_mod_exit(int status);
#endif
static void send_syscall(struct syscall_request *req)
static void send_syscall(struct syscall_request *req, int cpu)
{
struct ikc_scd_packet packet;
struct syscall_response *res;
@@ -106,7 +106,6 @@ static void send_syscall(struct syscall_request *req)
int w;
struct syscall_params *scp;
struct ihk_ikc_channel_desc *syscall_channel;
int cpu;
if(req->number == __NR_exit_group ||
req->number == __NR_kill){ // interrupt syscall
@@ -117,9 +116,8 @@ static void send_syscall(struct syscall_request *req)
cpu = num_processors;
}
else{
scp = &cpu_local_var(scp);
syscall_channel = cpu_local_var(syscall_channel);
cpu = ihk_mc_get_processor_id();
scp = &get_cpu_local_var(cpu)->scp;
syscall_channel = get_cpu_local_var(cpu)->syscall_channel;
}
res = scp->response_va;
@@ -150,7 +148,7 @@ static void send_syscall(struct syscall_request *req)
}
int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx)
int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx, int cpu)
{
struct syscall_response *res;
struct syscall_request req2 IHK_DMA_ALIGN;
@@ -166,11 +164,11 @@ int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx)
scp = &get_cpu_local_var(0)->scp2;
}
else{
scp = &cpu_local_var(scp);
scp = &get_cpu_local_var(cpu)->scp;
}
res = scp->response_va;
send_syscall(req);
send_syscall(req, cpu);
dkprintf("SC(%d)[%3d] waiting for host.. \n",
ihk_mc_get_processor_id(),
@@ -185,7 +183,7 @@ int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx)
}
if (res->status == STATUS_PAGE_FAULT) {
error = page_fault_process(cpu_local_var(current),
error = page_fault_process(get_cpu_local_var(cpu)->current,
(void *)res->fault_address,
res->fault_reason);
@@ -195,7 +193,7 @@ int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx)
req2.args[0] = PAGER_RESUME_PAGE_FAULT;
req2.args[1] = error;
send_syscall(&req2);
send_syscall(&req2, cpu);
}
}
@@ -239,7 +237,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
/* XXX: send SIGKILL to all threads in this process */
flush_process_memory(proc); /* temporary hack */
do_syscall(&request, ctx);
do_syscall(&request, ctx, ihk_mc_get_processor_id());
#define IS_DETACHED_PROCESS(proc) (1) /* should be implemented in the future */
proc->status = PS_ZOMBIE;
@@ -253,12 +251,12 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
}
void
interrupt_syscall()
interrupt_syscall(int all)
{
ihk_mc_user_context_t ctx;
long lerror;
ihk_mc_syscall_arg0(&ctx) = ihk_mc_get_processor_id();
ihk_mc_syscall_arg0(&ctx) = all? -1: ihk_mc_get_processor_id();
ihk_mc_syscall_arg1(&ctx) = 0;
lerror = syscall_generic_forwarding(__NR_kill, &ctx);
@@ -284,7 +282,7 @@ SYSCALL_DECLARE(exit_group)
/* XXX: send SIGKILL to all threads in this process */
do_syscall(&request, ctx);
do_syscall(&request, ctx, ihk_mc_get_processor_id());
#define IS_DETACHED_PROCESS(proc) (1) /* should be implemented in the future */
proc->status = PS_ZOMBIE;
@@ -874,6 +872,11 @@ SYSCALL_DECLARE(getpid)
return cpu_local_var(current)->pid;
}
SYSCALL_DECLARE(gettid)
{
return cpu_local_var(current)->tid;
}
long do_arch_prctl(unsigned long code, unsigned long address)
{
int err = 0;
@@ -932,6 +935,8 @@ SYSCALL_DECLARE(clone)
int cpuid;
int clone_flags = ihk_mc_syscall_arg0(ctx);
struct process *new;
ihk_mc_user_context_t ctx1;
struct syscall_request request1 IHK_DMA_ALIGN;
if(clone_flags == 0x1200011){
// fork()
@@ -942,7 +947,7 @@ SYSCALL_DECLARE(clone)
ihk_mc_get_processor_id(),
(unsigned long)ihk_mc_syscall_arg1(ctx));
cpuid = obtain_clone_cpuid();
cpuid = obtain_clone_cpuid();
new = clone_process(cpu_local_var(current), ihk_mc_syscall_pc(ctx),
ihk_mc_syscall_arg1(ctx));
@@ -951,9 +956,13 @@ SYSCALL_DECLARE(clone)
return -ENOMEM;
}
/* Allocate new pid */
new->pid = ihk_atomic_inc_return(&pid_cnt);
// /* Allocate new pid */
// new->pid = ihk_atomic_inc_return(&pid_cnt);
new->pid = cpu_local_var(current)->pid;
request1.number = __NR_gettid;
new->tid = do_syscall(&request1, &ctx1, cpuid);
if (clone_flags & CLONE_PARENT_SETTID) {
dkprintf("clone_flags & CLONE_PARENT_SETTID: 0x%lX\n",
(unsigned long)ihk_mc_syscall_arg2(ctx));
@@ -981,11 +990,11 @@ SYSCALL_DECLARE(clone)
}
ihk_mc_syscall_ret(new->uctx) = 0;
dkprintf("clone: kicking scheduler!,cpuid=%d\n", cpuid);
dkprintf("clone: kicking scheduler!,cpuid=%d pid=%d tid=%d\n", cpuid, new->pid, new->tid);
runq_add_proc(new, cpuid);
return new->pid;
return new->tid;
}
SYSCALL_DECLARE(set_tid_address)
@@ -996,31 +1005,24 @@ SYSCALL_DECLARE(set_tid_address)
return cpu_local_var(current)->pid;
}
extern unsigned long do_kill(int pid, int sig);
extern unsigned long do_kill(int pid, int tid, int sig);
SYSCALL_DECLARE(kill)
{
int pid = ihk_mc_syscall_arg0(ctx);
int sig = ihk_mc_syscall_arg1(ctx);
return do_kill(pid, sig);
return do_kill(pid, -1, sig);
}
// see linux-2.6.34.13/kernel/signal.c
SYSCALL_DECLARE(tgkill)
{
int tgid = ihk_mc_syscall_arg0(ctx);
int pid = ihk_mc_syscall_arg1(ctx);
int sig = ihk_mc_syscall_arg2(ctx);
int tgid = ihk_mc_syscall_arg0(ctx);
int pid = ihk_mc_syscall_arg1(ctx);
int sig = ihk_mc_syscall_arg2(ctx);
if(pid <= 0 || tgid <= 0) { return -EINVAL; }
// search pid
// check kill permission
if(sig == 0) {
return 0;
} else {
return -EPERM;
}
return do_kill(tgid, pid, sig);
}
SYSCALL_DECLARE(set_robust_list)
@@ -1072,7 +1074,32 @@ SYSCALL_DECLARE(rt_sigprocmask)
int how = ihk_mc_syscall_arg0(ctx);
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg1(ctx);
sigset_t *oldset = (sigset_t *)ihk_mc_syscall_arg2(ctx);
// kprintf("sys_rt_sigprocmask called. returning zero...\n");
struct process *proc = cpu_local_var(current);
int irqstate;
if(set &&
how != SIG_BLOCK &&
how != SIG_UNBLOCK &&
how != SIG_SETMASK)
return -EINVAL;
irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock);
if(oldset)
oldset->__val[0] = proc->sigmask.__val[0];
if(set){
switch(how){
case SIG_BLOCK:
proc->sigmask.__val[0] |= set->__val[0];
break;
case SIG_UNBLOCK:
proc->sigmask.__val[0] &= ~set->__val[0];
break;
case SIG_SETMASK:
proc->sigmask.__val[0] = set->__val[0];
break;
}
}
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
return 0;
}
@@ -1149,7 +1176,7 @@ SYSCALL_DECLARE(futex)
request.args[0] = __phys;
int r = do_syscall(&request, ctx);
int r = do_syscall(&request, ctx, ihk_mc_get_processor_id());
if (r < 0) {
return -EFAULT;