signal (part 2) sigpending
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
|
|
||||||
void terminate(int, int, ihk_mc_user_context_t *);
|
void terminate(int, int, ihk_mc_user_context_t *);
|
||||||
|
|
||||||
@@ -108,56 +109,97 @@ check_signal(unsigned long rc, unsigned long *regs)
|
|||||||
struct process *proc;
|
struct process *proc;
|
||||||
struct k_sigaction *k;
|
struct k_sigaction *k;
|
||||||
int sig;
|
int sig;
|
||||||
|
struct sig_pending *pending;
|
||||||
|
struct sig_pending *next;
|
||||||
|
struct list_head *head;
|
||||||
|
ihk_spinlock_t *lock;
|
||||||
|
__sigset_t w;
|
||||||
|
int irqstate;
|
||||||
|
|
||||||
if(clv == NULL)
|
if(clv == NULL)
|
||||||
return;
|
return;
|
||||||
proc = cpu_local_var(current);
|
proc = cpu_local_var(current);
|
||||||
if(proc == NULL || proc->pid == 0)
|
if(proc == NULL || proc->pid == 0)
|
||||||
return;
|
return;
|
||||||
sig = proc->signal;
|
|
||||||
|
|
||||||
proc->signal = 0;
|
w = proc->sigmask.__val[0];
|
||||||
if(sig){
|
lock = &proc->sigshared->lock;
|
||||||
int irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
head = &proc->sigshared->sigpending;
|
||||||
if(regs == NULL){ /* call from syscall */
|
pending = NULL;
|
||||||
asm volatile ("movq %%gs:132,%0" : "=r" (regs));
|
irqstate = ihk_mc_spinlock_lock(lock);
|
||||||
regs -= 16;
|
list_for_each_entry_safe(pending, next, head, list){
|
||||||
|
if(!(pending->sigmask.__val[0] & w)){
|
||||||
|
list_del(&pending->list);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else{
|
}
|
||||||
rc = regs[9]; /* rax */
|
if(&pending->list == head)
|
||||||
}
|
pending = NULL;
|
||||||
k = proc->sighandler->action + sig - 1;
|
ihk_mc_spinlock_unlock(lock, irqstate);
|
||||||
|
|
||||||
if(k->sa.sa_handler == (void *)1){
|
if(!pending){
|
||||||
|
lock = &proc->sigpendinglock;
|
||||||
|
head = &proc->sigpending;
|
||||||
|
irqstate = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry_safe(pending, next, head, list){
|
||||||
|
if(!(pending->sigmask.__val[0] & w)){
|
||||||
|
list_del(&pending->list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(&pending->list == head)
|
||||||
|
pending = NULL;
|
||||||
|
ihk_mc_spinlock_unlock(lock, irqstate);
|
||||||
|
}
|
||||||
|
if(!pending)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||||
|
|
||||||
|
irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
||||||
|
if(regs == NULL){ /* call from syscall */
|
||||||
|
asm volatile ("movq %%gs:132,%0" : "=r" (regs));
|
||||||
|
regs -= 16;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
rc = regs[9]; /* rax */
|
||||||
|
}
|
||||||
|
k = proc->sighandler->action + sig - 1;
|
||||||
|
|
||||||
|
if(k->sa.sa_handler == (void *)1){
|
||||||
|
kfree(pending);
|
||||||
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(k->sa.sa_handler){
|
||||||
|
unsigned long *usp; /* user stack */
|
||||||
|
|
||||||
|
if(regs[14] & 0x8000000000000000){ // kernel addr
|
||||||
|
int flag = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_add(&pending->list, head);
|
||||||
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(k->sa.sa_handler){
|
|
||||||
unsigned long *usp; /* user stack */
|
|
||||||
|
|
||||||
if(regs[14] & 0x8000000000000000){ // kernel addr
|
usp = (void *)regs[14];
|
||||||
proc->signal = sig;
|
memcpy(proc->sigstack, regs, 128);
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
proc->sigrc = rc;
|
||||||
return;
|
usp--;
|
||||||
}
|
*usp = (unsigned long)k->sa.sa_restorer;
|
||||||
|
|
||||||
usp = (void *)regs[14];
|
regs[4] = (unsigned long)sig;
|
||||||
memcpy(proc->sigstack, regs, 128);
|
regs[11] = (unsigned long)k->sa.sa_handler;
|
||||||
proc->sigrc = rc;
|
regs[14] = (unsigned long)usp;
|
||||||
usp--;
|
kfree(pending);
|
||||||
*usp = (unsigned long)k->sa.sa_restorer;
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
|
}
|
||||||
regs[4] = (unsigned long)sig;
|
else{
|
||||||
regs[11] = (unsigned long)k->sa.sa_handler;
|
kfree(pending);
|
||||||
regs[14] = (unsigned long)usp;
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
if(sig == SIGCHLD || sig == SIGURG)
|
||||||
}
|
return;
|
||||||
else{
|
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
|
||||||
if(sig == SIGCHLD || sig == SIGURG)
|
|
||||||
return;
|
|
||||||
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +208,12 @@ do_kill(int pid, int tid, int sig)
|
|||||||
{
|
{
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
struct process *tproc = NULL;
|
struct process *tproc = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
__sigset_t mask;
|
||||||
|
struct sig_pending *pending;
|
||||||
|
struct list_head *head;
|
||||||
|
int irqstate;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if(proc == NULL || proc->pid == 0){
|
if(proc == NULL || proc->pid == 0){
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
@@ -176,7 +223,11 @@ do_kill(int pid, int tid, int sig)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if(tid == -1){
|
if(tid == -1){
|
||||||
if(pid == proc->pid || pid <= 0){
|
if(pid == -1)
|
||||||
|
return -EPERM;
|
||||||
|
if(proc->pid == -pid)
|
||||||
|
pid = -pid;
|
||||||
|
if(pid == proc->pid || pid == 0){
|
||||||
tproc = proc;
|
tproc = proc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,13 +257,43 @@ do_kill(int pid, int tid, int sig)
|
|||||||
if(sig == 0)
|
if(sig == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(__sigmask(sig) & proc->sigmask.__val[0]){
|
if(tid == -1){
|
||||||
// TODO: masked signal: ignore -> pending
|
irqstate = ihk_mc_spinlock_lock(&tproc->sigshared->lock);
|
||||||
return 0;
|
head = &tproc->sigshared->sigpending;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
irqstate = ihk_mc_spinlock_lock(&tproc->sigpendinglock);
|
||||||
|
head = &tproc->sigpending;
|
||||||
|
}
|
||||||
|
mask = __sigmask(sig);
|
||||||
|
pending = NULL;
|
||||||
|
rc = 0;
|
||||||
|
if(sig < 34){
|
||||||
|
list_for_each_entry(pending, head, list){
|
||||||
|
if(pending->sigmask.__val[0] == mask)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(&pending->list == head)
|
||||||
|
pending = NULL;
|
||||||
|
}
|
||||||
|
if(pending == NULL){
|
||||||
|
pending = kmalloc(sizeof(struct sig_pending), IHK_MC_AP_NOWAIT);
|
||||||
|
pending->sigmask.__val[0] = mask;
|
||||||
|
if(!pending){
|
||||||
|
rc = -ENOMEM;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
list_add_tail(&pending->list, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(tid == -1){
|
||||||
|
ihk_mc_spinlock_unlock(&tproc->sigshared->lock, irqstate);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ihk_mc_spinlock_unlock(&tproc->sigpendinglock, irqstate);
|
||||||
}
|
}
|
||||||
proc->signal = sig;
|
|
||||||
interrupt_syscall(1);
|
interrupt_syscall(1);
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -227,11 +308,6 @@ set_signal(int sig, unsigned long *regs, int nonmaskable)
|
|||||||
if(nonmaskable){
|
if(nonmaskable){
|
||||||
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
// TODO: masked signal: ignore -> pending
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
proc->signal = sig;
|
do_kill(proc->pid, proc->tid, sig);
|
||||||
interrupt_syscall(1);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,18 @@ struct sig_handler {
|
|||||||
struct k_sigaction action[_NSIG];
|
struct k_sigaction action[_NSIG];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sig_pending {
|
||||||
|
struct list_head list;
|
||||||
|
sigset_t sigmask;
|
||||||
|
// TODO: siginfo
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sig_shared {
|
||||||
|
ihk_spinlock_t lock;
|
||||||
|
ihk_atomic_t use;
|
||||||
|
struct list_head sigpending;
|
||||||
|
};
|
||||||
|
|
||||||
typedef void pgio_func_t(void *arg);
|
typedef void pgio_func_t(void *arg);
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
@@ -110,10 +122,10 @@ struct process {
|
|||||||
|
|
||||||
int tid;
|
int tid;
|
||||||
sigset_t sigmask;
|
sigset_t sigmask;
|
||||||
int signal;
|
ihk_spinlock_t sigpendinglock;
|
||||||
// sigset_t sigpend;
|
struct list_head sigpending;
|
||||||
|
struct sig_shared *sigshared;
|
||||||
struct sig_handler *sighandler;
|
struct sig_handler *sighandler;
|
||||||
// ihk_mc_kernel_context_t sigctx;
|
|
||||||
char sigstack[512]; // TODO: 1. move to user stack
|
char sigstack[512]; // TODO: 1. move to user stack
|
||||||
// TODO: 2. backup FR and MMX regs
|
// TODO: 2. backup FR and MMX regs
|
||||||
unsigned long sigrc; // return code of rt_sigreturn (x86_64: rax reg.)
|
unsigned long sigrc; // return code of rt_sigreturn (x86_64: rax reg.)
|
||||||
|
|||||||
@@ -83,9 +83,20 @@ struct process *create_process(unsigned long user_pc)
|
|||||||
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
proc->sigshared = kmalloc(sizeof(struct sig_shared), IHK_MC_AP_NOWAIT);
|
||||||
|
if(!proc->sigshared){
|
||||||
|
ihk_mc_free_pages(proc->sighandler, KERNEL_STACK_NR_PAGES);
|
||||||
|
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
memset(proc->sighandler, '\0', sizeof(struct sig_handler));
|
memset(proc->sighandler, '\0', sizeof(struct sig_handler));
|
||||||
ihk_atomic_set(&proc->sighandler->use, 1);
|
ihk_atomic_set(&proc->sighandler->use, 1);
|
||||||
ihk_mc_spinlock_init(&proc->sighandler->lock);
|
ihk_mc_spinlock_init(&proc->sighandler->lock);
|
||||||
|
ihk_atomic_set(&proc->sigshared->use, 1);
|
||||||
|
ihk_mc_spinlock_init(&proc->sigshared->lock);
|
||||||
|
INIT_LIST_HEAD(&proc->sigshared->sigpending);
|
||||||
|
ihk_mc_spinlock_init(&proc->sigpendinglock);
|
||||||
|
INIT_LIST_HEAD(&proc->sigpending);
|
||||||
|
|
||||||
ihk_mc_init_user_process(&proc->ctx, &proc->uctx,
|
ihk_mc_init_user_process(&proc->ctx, &proc->uctx,
|
||||||
((char *)proc) +
|
((char *)proc) +
|
||||||
@@ -133,6 +144,12 @@ struct process *clone_process(struct process *org, unsigned long pc,
|
|||||||
proc->sighandler = org->sighandler;
|
proc->sighandler = org->sighandler;
|
||||||
ihk_atomic_inc(&org->sighandler->use);
|
ihk_atomic_inc(&org->sighandler->use);
|
||||||
|
|
||||||
|
proc->sigshared = org->sigshared;
|
||||||
|
ihk_atomic_inc(&org->sigshared->use);
|
||||||
|
|
||||||
|
ihk_mc_spinlock_init(&proc->sigpendinglock);
|
||||||
|
INIT_LIST_HEAD(&proc->sigpending);
|
||||||
|
|
||||||
ihk_mc_spinlock_init(&proc->spin_sleep_lock);
|
ihk_mc_spinlock_init(&proc->spin_sleep_lock);
|
||||||
proc->spin_sleep = 0;
|
proc->spin_sleep = 0;
|
||||||
|
|
||||||
@@ -1339,9 +1356,23 @@ void hold_process(struct process *proc)
|
|||||||
|
|
||||||
void destroy_process(struct process *proc)
|
void destroy_process(struct process *proc)
|
||||||
{
|
{
|
||||||
|
struct sig_pending *pending;
|
||||||
|
struct sig_pending *next;
|
||||||
if(ihk_atomic_dec_and_test(&proc->sighandler->use)){
|
if(ihk_atomic_dec_and_test(&proc->sighandler->use)){
|
||||||
kfree(proc->sighandler);
|
kfree(proc->sighandler);
|
||||||
}
|
}
|
||||||
|
if(ihk_atomic_dec_and_test(&proc->sigshared->use)){
|
||||||
|
list_for_each_entry_safe(pending, next, &proc->sigshared->sigpending, list){
|
||||||
|
list_del(&pending->list);
|
||||||
|
kfree(pending);
|
||||||
|
}
|
||||||
|
list_del(&proc->sigshared->sigpending);
|
||||||
|
kfree(proc->sigshared);
|
||||||
|
}
|
||||||
|
list_for_each_entry_safe(pending, next, &proc->sigpending, list){
|
||||||
|
list_del(&pending->list);
|
||||||
|
kfree(pending);
|
||||||
|
}
|
||||||
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1075,7 +1075,7 @@ SYSCALL_DECLARE(rt_sigprocmask)
|
|||||||
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg1(ctx);
|
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg1(ctx);
|
||||||
sigset_t *oldset = (sigset_t *)ihk_mc_syscall_arg2(ctx);
|
sigset_t *oldset = (sigset_t *)ihk_mc_syscall_arg2(ctx);
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
int irqstate;
|
int flag;
|
||||||
|
|
||||||
if(set &&
|
if(set &&
|
||||||
how != SIG_BLOCK &&
|
how != SIG_BLOCK &&
|
||||||
@@ -1083,7 +1083,7 @@ SYSCALL_DECLARE(rt_sigprocmask)
|
|||||||
how != SIG_SETMASK)
|
how != SIG_SETMASK)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
flag = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
||||||
if(oldset)
|
if(oldset)
|
||||||
oldset->__val[0] = proc->sigmask.__val[0];
|
oldset->__val[0] = proc->sigmask.__val[0];
|
||||||
if(set){
|
if(set){
|
||||||
@@ -1099,12 +1099,38 @@ SYSCALL_DECLARE(rt_sigprocmask)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, flag);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigpending)
|
SYSCALL_DECLARE(rt_sigpending)
|
||||||
{
|
{
|
||||||
|
int flag;
|
||||||
|
struct sig_pending *pending;
|
||||||
|
struct list_head *head;
|
||||||
|
ihk_spinlock_t *lock;
|
||||||
|
__sigset_t w = 0;
|
||||||
|
struct process *proc = cpu_local_var(current);
|
||||||
|
sigset_t *set = (sigset_t *)ihk_mc_syscall_arg0(ctx);
|
||||||
|
|
||||||
|
lock = &proc->sigshared->lock;
|
||||||
|
head = &proc->sigshared->sigpending;
|
||||||
|
flag = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry(pending, head, list){
|
||||||
|
w |= pending->sigmask.__val[0];
|
||||||
|
}
|
||||||
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
|
|
||||||
|
lock = &proc->sigpendinglock;
|
||||||
|
head = &proc->sigpending;
|
||||||
|
flag = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry(pending, head, list){
|
||||||
|
w |= pending->sigmask.__val[0];
|
||||||
|
}
|
||||||
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
|
|
||||||
|
set->__val[0] = w;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user