From f5d935b7038f78a8df3ecb1149cb785ce4efa229 Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 18 Mar 2015 17:35:43 +0900 Subject: [PATCH] support signalfd4 step1 --- arch/x86/kernel/include/syscall_list.h | 2 +- executer/user/mcexec.c | 71 ++++++++++++++++++++++ kernel/include/process.h | 9 +++ kernel/syscall.c | 83 +++++++++++++++++++++++++- 4 files changed, 162 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/include/syscall_list.h b/arch/x86/kernel/include/syscall_list.h index 5b88646e..acd966f4 100644 --- a/arch/x86/kernel/include/syscall_list.h +++ b/arch/x86/kernel/include/syscall_list.h @@ -23,7 +23,7 @@ SYSCALL_DELEGATED(0, read) SYSCALL_DELEGATED(1, write) SYSCALL_DELEGATED(2, open) -SYSCALL_DELEGATED(3, close) +SYSCALL_HANDLED(3, close) SYSCALL_DELEGATED(4, stat) SYSCALL_DELEGATED(5, fstat) SYSCALL_DELEGATED(8, lseek) diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index cce5e4ab..459970bf 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -57,6 +57,7 @@ #include #include #include +#include #include "../include/uprotocol.h" //#define DEBUG @@ -98,6 +99,13 @@ typedef unsigned char cc_t; typedef unsigned int speed_t; typedef unsigned int tcflag_t; +struct sigfd { + struct sigfd *next; + int sigpipe[2]; +}; + +struct sigfd *sigfdtop; + #ifdef NCCS #undef NCCS #endif @@ -887,6 +895,64 @@ sendsig(int sig, siginfo_t *siginfo, void *context) } } +long +act_signalfd4(struct syscall_wait_desc *w) +{ + struct sigfd *sfd; + struct sigfd *sb; + int mode = w->sr.args[0]; + int flags; + int tmp; + int rc = 0; + struct signalfd_siginfo *info; + + switch(mode){ + case 0: /* new signalfd */ + sfd = malloc(sizeof(struct sigfd)); + tmp = w->sr.args[1]; + flags = 0; + if(tmp & SFD_NONBLOCK) + flags |= O_NONBLOCK; + if(tmp & SFD_CLOEXEC) + flags |= O_CLOEXEC; + pipe2(sfd->sigpipe, flags); + sfd->next = sigfdtop; + sigfdtop = sfd; + rc = sfd->sigpipe[0]; + break; + case 1: /* close signalfd */ + tmp = w->sr.args[1]; + for(sfd = sigfdtop, sb = NULL; sfd; sb = sfd, sfd = sfd->next) + if(sfd->sigpipe[0] == tmp) + break; + if(!sfd) + rc = -EBADF; + else{ + if(sb) + sb->next = sfd->next; + else + sigfdtop = sfd->next; + close(sfd->sigpipe[0]); + close(sfd->sigpipe[1]); + free(sfd); + } + break; + case 2: /* push signal */ + tmp = w->sr.args[1]; + for(sfd = sigfdtop; sfd; sfd = sfd->next) + if(sfd->sigpipe[0] == tmp) + break; + if(!sfd) + rc = -EBADF; + else{ + info = (struct signalfd_siginfo *)w->sr.args[2]; + write(sfd->sigpipe[1], info, sizeof(struct signalfd_siginfo)); + } + break; + } + return rc; +} + void act_sigaction(struct syscall_wait_desc *w) { @@ -1955,6 +2021,11 @@ return_execve2: break; } + case __NR_signalfd4: + ret = act_signalfd4(&w); + do_syscall_return(fd, cpu, ret, 0, 0, 0, 0); + break; + case __NR_rt_sigaction: act_sigaction(&w); do_syscall_return(fd, cpu, 0, 0, 0, 0, 0); diff --git a/kernel/include/process.h b/kernel/include/process.h index a0377975..ed4c24b2 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -244,9 +244,18 @@ struct vm_regions { struct process_vm; +struct sigfd { + struct sigfd *next; + int fd; + __sigset_t mask; +}; +#define SFD_CLOEXEC 02000000 +#define SFD_NONBLOCK 04000 + struct sig_handler { ihk_spinlock_t lock; ihk_atomic_t use; + struct sigfd *sigfd; struct k_sigaction action[_NSIG]; }; diff --git a/kernel/syscall.c b/kernel/syscall.c index 89e129f0..c69355f5 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -2163,7 +2163,7 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) { struct process *proc = cpu_local_var(current); struct k_sigaction *k; - int irqstate; + long irqstate; ihk_mc_user_context_t ctx0; irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock); @@ -2183,6 +2183,39 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) return 0; } +SYSCALL_DECLARE(close) +{ + int fd = ihk_mc_syscall_arg0(ctx); + int rc; + struct process *proc = cpu_local_var(current); + struct sigfd *sfd; + struct sigfd *sb; + long irqstate; + + irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock); + for(sfd = proc->sighandler->sigfd, sb = NULL; sfd; sb = sfd, sfd = sfd->next) + if(sfd->fd == fd) + break; + if(sfd){ + struct syscall_request request IHK_DMA_ALIGN; + if(sb) + sb->next = sfd->next; + else + proc->sighandler->sigfd = sfd->next; + ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); + request.number = __NR_signalfd4; + request.args[0] = 1; + request.args[1] = sfd->fd; + kfree(sfd); + rc = do_syscall(&request, ihk_mc_get_processor_id(), 0); + } + else{ + ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); + rc = syscall_generic_forwarding(__NR_close, ctx); + } + return rc; +} + SYSCALL_DECLARE(rt_sigprocmask) { int how = ihk_mc_syscall_arg0(ctx); @@ -2278,7 +2311,53 @@ SYSCALL_DECLARE(signalfd) SYSCALL_DECLARE(signalfd4) { - return -EOPNOTSUPP; + int fd = ihk_mc_syscall_arg0(ctx); + struct process *proc = cpu_local_var(current); + struct sigfd *sfd; + long irqstate; + sigset_t *maskp = (sigset_t *)ihk_mc_syscall_arg1(ctx);; + __sigset_t mask; + size_t sigsetsize = (size_t)ihk_mc_syscall_arg2(ctx); + int flags = ihk_mc_syscall_arg3(ctx); + + if(sigsetsize != sizeof(sigset_t)) + return -EINVAL; + if(copy_from_user(&mask, maskp, sizeof mask)) + return -EFAULT; + if(flags & ~(SFD_NONBLOCK | SFD_CLOEXEC)) + return -EINVAL; + + irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock); + if(fd == -1){ + struct syscall_request request IHK_DMA_ALIGN; + ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); + request.number = __NR_signalfd4; + request.args[0] = 0; + request.args[1] = flags; + fd = do_syscall(&request, ihk_mc_get_processor_id(), 0); + if(fd < 0){ + return fd; + } + sfd = kmalloc(sizeof(struct sigfd), IHK_MC_AP_NOWAIT); + if(!sfd) + return -ENOMEM; + sfd->fd = fd; + irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock); + sfd->next = proc->sighandler->sigfd; + proc->sighandler->sigfd = sfd; + } + else{ + for(sfd = proc->sighandler->sigfd; sfd; sfd = sfd->next) + if(sfd->fd == fd) + break; + if(!sfd){ + ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); + return -EINVAL; + } + } + memcpy(&sfd->mask, &mask, sizeof mask); + ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); + return sfd->fd; } SYSCALL_DECLARE(rt_sigtimedwait)