use MCS locks in signal handling code
This commit is contained in:
@ -695,7 +695,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
int orgsig;
|
||||
int ptraceflag = 0;
|
||||
struct mcs_rwlock_node_irqsave lock;
|
||||
unsigned long irqstate;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
|
||||
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||
dkprintf("do_signal(): tid=%d, pid=%d, sig=%d\n", thread->tid, proc->pid, sig);
|
||||
@ -718,12 +718,12 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
rc = regs->gpr.rax;
|
||||
}
|
||||
|
||||
irqstate = ihk_mc_spinlock_lock(&thread->sigcommon->lock);
|
||||
mcs_rwlock_writer_lock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
k = thread->sigcommon->action + sig - 1;
|
||||
|
||||
if(k->sa.sa_handler == SIG_IGN){
|
||||
kfree(pending);
|
||||
ihk_mc_spinlock_unlock(&thread->sigcommon->lock, irqstate);
|
||||
mcs_rwlock_writer_unlock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
return;
|
||||
}
|
||||
else if(k->sa.sa_handler){
|
||||
@ -808,7 +808,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
|
||||
if(copy_to_user(sigsp, &ksigsp, sizeof ksigsp)){
|
||||
kfree(pending);
|
||||
ihk_mc_spinlock_unlock(&thread->sigcommon->lock, irqstate);
|
||||
mcs_rwlock_writer_unlock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
kprintf("do_signal,write_process_vm failed\n");
|
||||
terminate(0, sig);
|
||||
return;
|
||||
@ -827,7 +827,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
if(!(k->sa.sa_flags & SA_NODEFER))
|
||||
thread->sigmask.__val[0] |= pending->sigmask.__val[0];
|
||||
kfree(pending);
|
||||
ihk_mc_spinlock_unlock(&thread->sigcommon->lock, irqstate);
|
||||
mcs_rwlock_writer_unlock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
if(regs->gpr.rflags & RFLAGS_TF){
|
||||
struct siginfo info;
|
||||
|
||||
@ -853,7 +853,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
}
|
||||
else
|
||||
kfree(pending);
|
||||
ihk_mc_spinlock_unlock(&thread->sigcommon->lock, irqstate);
|
||||
mcs_rwlock_writer_unlock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
switch (sig) {
|
||||
case SIGSTOP:
|
||||
case SIGTSTP:
|
||||
@ -954,11 +954,11 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
static struct sig_pending *
|
||||
getsigpending(struct thread *thread, int delflag){
|
||||
struct list_head *head;
|
||||
ihk_spinlock_t *lock;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
struct sig_pending *next;
|
||||
struct sig_pending *pending;
|
||||
__sigset_t w;
|
||||
int irqstate;
|
||||
__sigset_t x;
|
||||
int sig;
|
||||
struct k_sigaction *k;
|
||||
@ -967,8 +967,12 @@ getsigpending(struct thread *thread, int delflag){
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
for(;;){
|
||||
irqstate = ihk_mc_spinlock_lock(lock);
|
||||
for(;;) {
|
||||
if (delflag)
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
else
|
||||
mcs_rwlock_reader_lock(lock, &mcs_rw_node);
|
||||
|
||||
list_for_each_entry_safe(pending, next, head, list){
|
||||
for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1);
|
||||
k = thread->sigcommon->action + sig - 1;
|
||||
@ -977,17 +981,26 @@ getsigpending(struct thread *thread, int delflag){
|
||||
(k->sa.sa_handler != (void *)1 &&
|
||||
k->sa.sa_handler != NULL)){
|
||||
if(!(pending->sigmask.__val[0] & w)){
|
||||
if(delflag)
|
||||
if(delflag)
|
||||
list_del(&pending->list);
|
||||
ihk_mc_spinlock_unlock(lock, irqstate);
|
||||
|
||||
if (delflag)
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
else
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
return pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock(lock, irqstate);
|
||||
|
||||
if (delflag)
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
else
|
||||
mcs_rwlock_reader_unlock(lock, &mcs_rw_node);
|
||||
|
||||
if(lock == &thread->sigpendinglock)
|
||||
return NULL;
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
}
|
||||
@ -1035,22 +1048,25 @@ check_signal(unsigned long rc, void *regs0, int num)
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock(&(cpu_local_var(runq_lock)), irqstate);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(regs != NULL && !interrupt_from_user(regs)) {
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(;;){
|
||||
pending = getsigpending(thread, 1);
|
||||
if(!pending) {
|
||||
dkprintf("check_signal,queue is empty\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do_signal(rc, regs, thread, pending, num);
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
@ -1064,7 +1080,8 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
|
||||
struct thread *tthread = NULL;
|
||||
int i;
|
||||
__sigset_t mask;
|
||||
ihk_spinlock_t *savelock = NULL;
|
||||
mcs_rwlock_lock_t *savelock = NULL;
|
||||
struct mcs_rwlock_node mcs_rw_node;
|
||||
struct list_head *head = NULL;
|
||||
int rc;
|
||||
unsigned long irqstate = 0;
|
||||
@ -1248,7 +1265,7 @@ done:
|
||||
|
||||
doint = 0;
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(savelock);
|
||||
mcs_rwlock_writer_lock_noirq(savelock, &mcs_rw_node);
|
||||
|
||||
/* Put signal event even when handler is SIG_IGN or SIG_DFL
|
||||
because target ptraced thread must call ptrace_report_signal
|
||||
@ -1287,7 +1304,7 @@ done:
|
||||
}
|
||||
}
|
||||
}
|
||||
ihk_mc_spinlock_unlock_noirq(savelock);
|
||||
mcs_rwlock_writer_unlock_noirq(savelock, &mcs_rw_node);
|
||||
cpu_restore_interrupt(irqstate);
|
||||
|
||||
if (doint && !(mask & tthread->sigmask.__val[0])) {
|
||||
|
||||
@ -407,7 +407,7 @@ struct mckfd {
|
||||
#define SFD_NONBLOCK 04000
|
||||
|
||||
struct sig_common {
|
||||
ihk_spinlock_t lock;
|
||||
mcs_rwlock_lock_t lock;
|
||||
ihk_atomic_t use;
|
||||
struct k_sigaction action[_NSIG];
|
||||
struct list_head sigpending;
|
||||
@ -624,7 +624,7 @@ struct thread {
|
||||
sigset_t sigmask;
|
||||
stack_t sigstack;
|
||||
struct list_head sigpending;
|
||||
ihk_spinlock_t sigpendinglock;
|
||||
mcs_rwlock_lock_t sigpendinglock;
|
||||
volatile int sigevent;
|
||||
|
||||
// gpio
|
||||
|
||||
@ -277,10 +277,10 @@ create_thread(unsigned long user_pc)
|
||||
dkprintf("fork(): sigshared\n");
|
||||
|
||||
ihk_atomic_set(&thread->sigcommon->use, 1);
|
||||
ihk_mc_spinlock_init(&thread->sigcommon->lock);
|
||||
mcs_rwlock_init(&thread->sigcommon->lock);
|
||||
INIT_LIST_HEAD(&thread->sigcommon->sigpending);
|
||||
|
||||
ihk_mc_spinlock_init(&thread->sigpendinglock);
|
||||
mcs_rwlock_init(&thread->sigpendinglock);
|
||||
INIT_LIST_HEAD(&thread->sigpending);
|
||||
|
||||
thread->sigstack.ss_sp = NULL;
|
||||
@ -441,11 +441,11 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
memcpy(thread->sigcommon->action, org->sigcommon->action,
|
||||
sizeof(struct k_sigaction) * _NSIG);
|
||||
ihk_atomic_set(&thread->sigcommon->use, 1);
|
||||
ihk_mc_spinlock_init(&thread->sigcommon->lock);
|
||||
mcs_rwlock_init(&thread->sigcommon->lock);
|
||||
INIT_LIST_HEAD(&thread->sigcommon->sigpending);
|
||||
// TODO: copy signalfd
|
||||
}
|
||||
ihk_mc_spinlock_init(&thread->sigpendinglock);
|
||||
mcs_rwlock_init(&thread->sigpendinglock);
|
||||
INIT_LIST_HEAD(&thread->sigpending);
|
||||
thread->sigmask = org->sigmask;
|
||||
|
||||
|
||||
@ -2627,16 +2627,16 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
|
||||
{
|
||||
struct thread *thread = cpu_local_var(current);
|
||||
struct k_sigaction *k;
|
||||
long irqstate;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
ihk_mc_user_context_t ctx0;
|
||||
|
||||
irqstate = ihk_mc_spinlock_lock(&thread->sigcommon->lock);
|
||||
mcs_rwlock_writer_lock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
k = thread->sigcommon->action + sig - 1;
|
||||
if(oact)
|
||||
memcpy(oact, k, sizeof(struct k_sigaction));
|
||||
if(act)
|
||||
memcpy(k, act, sizeof(struct k_sigaction));
|
||||
ihk_mc_spinlock_unlock(&thread->sigcommon->lock, irqstate);
|
||||
mcs_rwlock_writer_unlock(&thread->sigcommon->lock, &mcs_rw_node);
|
||||
|
||||
if(act){
|
||||
ihk_mc_syscall_arg0(&ctx0) = sig;
|
||||
@ -2808,10 +2808,10 @@ fault:
|
||||
|
||||
SYSCALL_DECLARE(rt_sigpending)
|
||||
{
|
||||
int flag;
|
||||
struct sig_pending *pending;
|
||||
struct list_head *head;
|
||||
ihk_spinlock_t *lock;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
__sigset_t w = 0;
|
||||
struct thread *thread = cpu_local_var(current);
|
||||
sigset_t *set = (sigset_t *)ihk_mc_syscall_arg0(ctx);
|
||||
@ -2822,19 +2822,19 @@ SYSCALL_DECLARE(rt_sigpending)
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
w |= pending->sigmask.__val[0];
|
||||
}
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
w |= pending->sigmask.__val[0];
|
||||
}
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
|
||||
if(copy_to_user(set->__val, &w, sizeof w))
|
||||
return -EFAULT;
|
||||
@ -3369,10 +3369,10 @@ SYSCALL_DECLARE(rt_sigtimedwait)
|
||||
__sigset_t wset;
|
||||
__sigset_t nset;
|
||||
struct timespec wtimeout;
|
||||
unsigned long flag;
|
||||
struct sig_pending *pending;
|
||||
struct list_head *head;
|
||||
ihk_spinlock_t *lock;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
int w;
|
||||
int sig;
|
||||
struct timespec ats;
|
||||
@ -3438,18 +3438,18 @@ SYSCALL_DECLARE(rt_sigtimedwait)
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
if(pending->sigmask.__val[0] & wset)
|
||||
break;
|
||||
}
|
||||
|
||||
if(&pending->list == head){
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
if(pending->sigmask.__val[0] & wset)
|
||||
break;
|
||||
@ -3459,25 +3459,25 @@ SYSCALL_DECLARE(rt_sigtimedwait)
|
||||
if(&pending->list != head){
|
||||
list_del(&pending->list);
|
||||
thread->sigmask.__val[0] = bset;
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
break;
|
||||
}
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
if(pending->sigmask.__val[0] & nset)
|
||||
break;
|
||||
}
|
||||
|
||||
if(&pending->list == head){
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
if(pending->sigmask.__val[0] & nset)
|
||||
break;
|
||||
@ -3487,11 +3487,11 @@ SYSCALL_DECLARE(rt_sigtimedwait)
|
||||
if(&pending->list != head){
|
||||
list_del(&pending->list);
|
||||
thread->sigmask.__val[0] = bset;
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
do_signal(-EINTR, NULL, thread, pending, 0);
|
||||
return -EINTR;
|
||||
}
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
thread->sigevent = 0;
|
||||
}
|
||||
|
||||
@ -3528,10 +3528,10 @@ do_sigsuspend(struct thread *thread, const sigset_t *set)
|
||||
{
|
||||
__sigset_t wset;
|
||||
__sigset_t bset;
|
||||
unsigned long flag;
|
||||
struct sig_pending *pending;
|
||||
struct list_head *head;
|
||||
ihk_spinlock_t *lock;
|
||||
mcs_rwlock_lock_t *lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
|
||||
wset = set->__val[0];
|
||||
wset &= ~__sigmask(SIGKILL);
|
||||
@ -3546,31 +3546,31 @@ do_sigsuspend(struct thread *thread, const sigset_t *set)
|
||||
|
||||
lock = &thread->sigcommon->lock;
|
||||
head = &thread->sigcommon->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
if(!(pending->sigmask.__val[0] & wset))
|
||||
break;
|
||||
}
|
||||
|
||||
if(&pending->list == head){
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
|
||||
lock = &thread->sigpendinglock;
|
||||
head = &thread->sigpending;
|
||||
flag = ihk_mc_spinlock_lock(lock);
|
||||
mcs_rwlock_writer_lock(lock, &mcs_rw_node);
|
||||
list_for_each_entry(pending, head, list){
|
||||
if(!(pending->sigmask.__val[0] & wset))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(&pending->list == head){
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
thread->sigevent = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
list_del(&pending->list);
|
||||
ihk_mc_spinlock_unlock(lock, flag);
|
||||
mcs_rwlock_writer_unlock(lock, &mcs_rw_node);
|
||||
thread->sigmask.__val[0] = bset;
|
||||
do_signal(-EINTR, NULL, thread, pending, 0);
|
||||
break;
|
||||
@ -8458,8 +8458,11 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
l = syscall_generic_forwarding(num, ctx);
|
||||
}
|
||||
|
||||
check_signal(l, NULL, num);
|
||||
|
||||
if (num != __NR_sched_yield &&
|
||||
num != __NR_futex) {
|
||||
check_signal(l, NULL, num);
|
||||
}
|
||||
|
||||
#ifdef TRACK_SYSCALLS
|
||||
if (num < 300) {
|
||||
if (!cpu_local_var(current)->syscall_cnts) {
|
||||
@ -8471,11 +8474,15 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
}
|
||||
}
|
||||
else {
|
||||
dkprintf("syscall > 300?? : %d\n", num);
|
||||
if (num != 701)
|
||||
kprintf("syscall > 300?? : %d\n", num);
|
||||
}
|
||||
#endif // TRACK_SYSCALLS
|
||||
|
||||
check_need_resched();
|
||||
if (num != __NR_sched_yield &&
|
||||
num != __NR_futex) {
|
||||
check_need_resched();
|
||||
}
|
||||
|
||||
if (cpu_local_var(current)->proc->ptrace) {
|
||||
ptrace_syscall_exit(cpu_local_var(current));
|
||||
|
||||
Reference in New Issue
Block a user