diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index ef8064c1..f4aac303 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -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])) { diff --git a/kernel/include/process.h b/kernel/include/process.h index 7d2a7216..2d466b18 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -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 diff --git a/kernel/process.c b/kernel/process.c index 6e319940..6604ad1a 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -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; diff --git a/kernel/syscall.c b/kernel/syscall.c index 3b4c2b9c..46811ed4 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -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));