diff options
-rw-r--r-- | sys/alpha/alpha/machdep.c | 2 | ||||
-rw-r--r-- | sys/alpha/osf1/osf1_signal.c | 3 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 2 | ||||
-rw-r--r-- | sys/coda/coda_psdev.c | 1 | ||||
-rw-r--r-- | sys/compat/linux/linux_signal.c | 3 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_signal.c | 2 | ||||
-rw-r--r-- | sys/fs/coda/coda_psdev.c | 1 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 2 | ||||
-rw-r--r-- | sys/i386/ibcs2/ibcs2_signal.c | 3 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysvec.c | 2 | ||||
-rw-r--r-- | sys/i386/svr4/svr4_machdep.c | 1 | ||||
-rw-r--r-- | sys/ia64/ia64/machdep.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 28 | ||||
-rw-r--r-- | sys/kern/subr_trap.c | 68 | ||||
-rw-r--r-- | sys/pc98/i386/machdep.c | 2 | ||||
-rw-r--r-- | sys/pc98/pc98/machdep.c | 2 | ||||
-rw-r--r-- | sys/sparc64/sparc64/machdep.c | 1 | ||||
-rw-r--r-- | sys/sys/proc.h | 10 | ||||
-rw-r--r-- | sys/sys/signalvar.h | 1 |
19 files changed, 101 insertions, 34 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index e9e47eff78b9..231978015c38 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -1471,6 +1471,7 @@ osigreturn(struct thread *td, */ SIGSETOLD(p->p_sigmask, ksc.sc_mask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); set_regs(td, (struct reg *)ksc.sc_regs); @@ -1553,6 +1554,7 @@ sigreturn(struct thread *td, p->p_sigmask = uc.uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); /* XXX ksc.sc_ownedfp ? */ diff --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c index 9e0cf5ab42f9..61803e7b6150 100644 --- a/sys/alpha/osf1/osf1_signal.c +++ b/sys/alpha/osf1/osf1_signal.c @@ -491,11 +491,13 @@ osf1_sigprocmask(td, uap) case OSF1_SIG_UNBLOCK: SIGSETNAND(p->p_sigmask, bss); + signotify(p); break; case OSF1_SIG_SETMASK: p->p_sigmask = bss; SIG_CANTMASK(p->p_sigmask); + signotify(p); break; default: @@ -729,6 +731,7 @@ osf1_sigreturn(struct thread *td, */ osf1_to_bsd_sigset(&ksc.sc_mask, &p->p_sigmask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); set_regs(td, (struct reg *)ksc.sc_regs); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index ffb209449dea..c8b7c5ef3ed5 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -649,6 +649,7 @@ osigreturn(td, uap) SIGSETOLD(p->p_sigmask, scp->sc_mask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); regs->tf_ebp = scp->sc_fp; regs->tf_esp = scp->sc_sp; @@ -758,6 +759,7 @@ sigreturn(td, uap) p->p_sigmask = ucp->uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); return (EJUSTRETURN); } diff --git a/sys/coda/coda_psdev.c b/sys/coda/coda_psdev.c index c2653ecbed10..8ed4f2299e48 100644 --- a/sys/coda/coda_psdev.c +++ b/sys/coda/coda_psdev.c @@ -602,6 +602,7 @@ coda_call(mntinfo, inSize, outSize, buffer) } } while (error && i++ < 128 && VC_OPEN(vcp)); p->p_sigmask = psig_omask; + signotify(p); PROC_UNLOCK(p); #else (void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0); diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index ccc30f0a86e4..3a5f6e5033c9 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/linux/linux_signal.c @@ -256,10 +256,12 @@ linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new, break; case LINUX_SIG_UNBLOCK: SIGSETNAND(p->p_sigmask, mask); + signotify(p); break; case LINUX_SIG_SETMASK: p->p_sigmask = mask; SIG_CANTMASK(p->p_sigmask); + signotify(p); break; default: error = EINVAL; @@ -377,6 +379,7 @@ linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args) linux_to_bsd_sigset(&lset, &bset); p->p_sigmask = bset; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); return (0); } diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c index 471022acc8f2..fea531771410 100644 --- a/sys/compat/svr4/svr4_signal.c +++ b/sys/compat/svr4/svr4_signal.c @@ -531,11 +531,13 @@ svr4_sys_sigprocmask(td, uap) case SVR4_SIG_UNBLOCK: SIGSETNAND(td->td_proc->p_sigmask, bss); + signotify(td->td_proc); break; case SVR4_SIG_SETMASK: td->td_proc->p_sigmask = bss; SIG_CANTMASK(td->td_proc->p_sigmask); + signotify(td->td_proc); break; default: diff --git a/sys/fs/coda/coda_psdev.c b/sys/fs/coda/coda_psdev.c index c2653ecbed10..8ed4f2299e48 100644 --- a/sys/fs/coda/coda_psdev.c +++ b/sys/fs/coda/coda_psdev.c @@ -602,6 +602,7 @@ coda_call(mntinfo, inSize, outSize, buffer) } } while (error && i++ < 128 && VC_OPEN(vcp)); p->p_sigmask = psig_omask; + signotify(p); PROC_UNLOCK(p); #else (void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0); diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index ffb209449dea..c8b7c5ef3ed5 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -649,6 +649,7 @@ osigreturn(td, uap) SIGSETOLD(p->p_sigmask, scp->sc_mask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); regs->tf_ebp = scp->sc_fp; regs->tf_esp = scp->sc_sp; @@ -758,6 +759,7 @@ sigreturn(td, uap) p->p_sigmask = ucp->uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); return (EJUSTRETURN); } diff --git a/sys/i386/ibcs2/ibcs2_signal.c b/sys/i386/ibcs2/ibcs2_signal.c index fd32aafb770f..12bd03802784 100644 --- a/sys/i386/ibcs2/ibcs2_signal.c +++ b/sys/i386/ibcs2/ibcs2_signal.c @@ -328,6 +328,7 @@ ibcs2_sigsys(td, uap) /* return SIG_HOLD and unblock signal*/ td->td_retval[0] = (int)IBCS2_SIG_HOLD; SIGDELSET(p->p_sigmask, signum); + signotify(p); } PROC_UNLOCK(p); } @@ -426,11 +427,13 @@ ibcs2_sigprocmask(td, uap) case IBCS2_SIG_UNBLOCK: SIGSETNAND(p->p_sigmask, bss); + signotify(p); break; case IBCS2_SIG_SETMASK: p->p_sigmask = bss; SIG_CANTMASK(p->p_sigmask); + signotify(p); break; default: diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index e1321ef08b63..c8bc6c8b99e4 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -555,6 +555,7 @@ linux_sigreturn(td, args) PROC_LOCK(p); linux_to_bsd_sigset(&lmask, &p->p_sigmask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); /* @@ -654,6 +655,7 @@ linux_rt_sigreturn(td, args) PROC_LOCK(p); linux_to_bsd_sigset(&uc.uc_sigmask, &p->p_sigmask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); /* diff --git a/sys/i386/svr4/svr4_machdep.c b/sys/i386/svr4/svr4_machdep.c index c82718df01d8..c01588892ba6 100644 --- a/sys/i386/svr4/svr4_machdep.c +++ b/sys/i386/svr4/svr4_machdep.c @@ -294,6 +294,7 @@ svr4_setcontext(td, uc) svr4_to_bsd_sigset(&uc->uc_sigmask, &mask); SIG_CANTMASK(mask); p->p_sigmask = mask; + signotify(p); } PROC_UNLOCK(p); diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 412d6dc9ad0e..b21b9b554b25 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1041,6 +1041,7 @@ sigreturn(struct thread *td, p->p_sigmask = uc.uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); /* XXX ksc.sc_ownedfp ? */ diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index bfefd2460def..6adda1d59cf6 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -180,6 +180,25 @@ CURSIG(struct proc *p) return (SIGPENDING(p) ? issignal(p) : 0); } +/* + * Arrange for ast() to handle unmasked pending signals on return to user + * mode. This must be called whenever a signal is added to p_siglist or + * unmasked in p_sigmask. + */ +void +signotify(struct proc *p) +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + mtx_assert(&sched_lock, MA_NOTOWNED); + mtx_lock_spin(&sched_lock); + if (SIGPENDING(p)) { + p->p_sflag |= PS_NEEDSIGCHK; + p->p_kse.ke_flags |= KEF_ASTPENDING; /* XXXKSE */ + } + mtx_unlock_spin(&sched_lock); +} + static __inline int sigprop(int sig) { @@ -514,6 +533,7 @@ do_sigprocmask(p, how, set, oset, old) break; case SIG_UNBLOCK: SIGSETNAND(p->p_sigmask, *set); + signotify(p); break; case SIG_SETMASK: SIG_CANTMASK(*set); @@ -521,6 +541,7 @@ do_sigprocmask(p, how, set, oset, old) SIGSETLO(p->p_sigmask, *set); else p->p_sigmask = *set; + signotify(p); break; default: error = EINVAL; @@ -753,6 +774,7 @@ osigsetmask(td, uap) PROC_LOCK(p); SIG2OSIG(p->p_sigmask, td->td_retval[0]); SIGSETLO(p->p_sigmask, set); + signotify(p); PROC_UNLOCK(p); mtx_unlock(&Giant); return (0); @@ -805,6 +827,7 @@ sigsuspend(td, uap) SIG_CANTMASK(mask); p->p_sigmask = mask; + signotify(p); while (msleep((caddr_t) ps, &p->p_mtx, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; PROC_UNLOCK(p); @@ -840,6 +863,7 @@ osigsuspend(td, uap) OSIG2SIG(uap->mask, mask); SIG_CANTMASK(mask); SIGSETLO(p->p_sigmask, mask); + signotify(p); while (msleep((caddr_t) ps, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) /* void */; PROC_UNLOCK(p); @@ -1303,6 +1327,7 @@ psignal(p, sig) SIG_CONTSIGMASK(p->p_siglist); } SIGADDSET(p->p_siglist, sig); + signotify(p); /* * Defer further processing for signals which are held, @@ -1475,7 +1500,6 @@ psignal(p, sig) #ifdef SMP struct kse *ke; struct thread *td = curthread; - signotify(&p->p_kse); /* XXXKSE */ /* we should only deliver to one thread.. but which one? */ FOREACH_KSEGRP_IN_PROC(p, kg) { FOREACH_KSE_IN_GROUP(kg, ke) { @@ -1485,8 +1509,6 @@ psignal(p, sig) forward_signal(ke->ke_thread); } } -#else - signotify(&p->p_kse); /* XXXKSE */ #endif } mtx_unlock_spin(&sched_lock); diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 4dcf90c132fb..a5b035ae8d41 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -70,44 +70,49 @@ userret(td, frame, oticks) struct proc *p = td->td_proc; struct kse *ke = td->td_kse; struct ksegrp *kg = td->td_ksegrp; - int sig; +#ifdef INVARIANTS + /* Check that we called signotify() enough. */ mtx_lock(&Giant); PROC_LOCK(p); - while ((sig = CURSIG(p)) != 0) - postsig(sig); + mtx_lock_spin(&sched_lock); + if (SIGPENDING(p) && ((p->p_sflag & PS_NEEDSIGCHK) == 0 || + (p->p_kse.ke_flags & KEF_ASTPENDING) == 0)) + printf("failed to set signal flags proprly for ast()\n"); + mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); mtx_unlock(&Giant); +#endif - mtx_lock_spin(&sched_lock); - td->td_priority = kg->kg_user_pri; - if (ke->ke_flags & KEF_NEEDRESCHED) { - DROP_GIANT(); - setrunqueue(td); - p->p_stats->p_ru.ru_nivcsw++; - mi_switch(); - mtx_unlock_spin(&sched_lock); - PICKUP_GIANT(); - mtx_lock(&Giant); - PROC_LOCK(p); - while ((sig = CURSIG(p)) != 0) - postsig(sig); - mtx_unlock(&Giant); - PROC_UNLOCK(p); + /* + * XXX we cheat slightly on the locking here to avoid locking in + * the usual case. Setting td_priority here is essentially an + * incomplete workaround for not setting it properly elsewhere. + * Now that some interrupt handlers are threads, not setting it + * properly elsewhere can clobber it in the window between setting + * it here and returning to user mode, so don't waste time setting + * it perfectly here. + */ + if (td->td_priority != kg->kg_user_pri) { mtx_lock_spin(&sched_lock); + td->td_priority = kg->kg_user_pri; + mtx_unlock_spin(&sched_lock); } /* * Charge system time if profiling. + * + * XXX should move PS_PROFIL to a place that can obviously be + * accessed safely without sched_lock. */ if (p->p_sflag & PS_PROFIL) { quad_t ticks; + mtx_lock_spin(&sched_lock); ticks = ke->ke_sticks - oticks; mtx_unlock_spin(&sched_lock); addupc_task(ke, TRAPF_PC(frame), (u_int)ticks * psratio); - } else - mtx_unlock_spin(&sched_lock); + } } /* @@ -122,9 +127,11 @@ ast(framep) struct thread *td = curthread; struct proc *p = td->td_proc; struct kse *ke = td->td_kse; + struct ksegrp *kg = td->td_ksegrp; u_int prticks, sticks; int sflag; int flags; + int sig; #if defined(DEV_NPX) && !defined(SMP) int ucode; #endif @@ -135,6 +142,7 @@ ast(framep) panic("Returning to user mode with mutex(s) held"); #endif mtx_assert(&Giant, MA_NOTOWNED); + mtx_assert(&sched_lock, MA_NOTOWNED); prticks = 0; /* XXX: Quiet warning. */ td->td_frame = framep; /* @@ -148,8 +156,8 @@ ast(framep) sticks = ke->ke_sticks; sflag = p->p_sflag; flags = ke->ke_flags; - p->p_sflag &= ~(PS_PROFPEND | PS_ALRMPEND); - ke->ke_flags &= ~(KEF_OWEUPC | KEF_ASTPENDING); + p->p_sflag &= ~(PS_ALRMPEND | PS_NEEDSIGCHK | PS_PROFPEND); + ke->ke_flags &= ~(KEF_ASTPENDING | KEF_NEEDRESCHED | KEF_OWEUPC); cnt.v_soft++; if (flags & KEF_OWEUPC && sflag & PS_PROFIL) { prticks = p->p_stats->p_prof.pr_ticks; @@ -181,6 +189,22 @@ ast(framep) psignal(p, SIGPROF); PROC_UNLOCK(p); } + if (flags & KEF_NEEDRESCHED) { + mtx_lock_spin(&sched_lock); + td->td_priority = kg->kg_user_pri; + setrunqueue(td); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + mtx_unlock_spin(&sched_lock); + } + if (sflag & PS_NEEDSIGCHK) { + mtx_lock(&Giant); + PROC_LOCK(p); + while ((sig = CURSIG(p)) != 0) + postsig(sig); + PROC_UNLOCK(p); + mtx_unlock(&Giant); + } userret(td, framep, sticks); #ifdef DIAGNOSTIC diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index 9e63dccd0d8d..6b7abe10eac5 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -662,6 +662,7 @@ osigreturn(td, uap) SIGSETOLD(p->p_sigmask, scp->sc_mask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); regs->tf_ebp = scp->sc_fp; regs->tf_esp = scp->sc_sp; @@ -771,6 +772,7 @@ sigreturn(td, uap) p->p_sigmask = ucp->uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); return (EJUSTRETURN); } diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 9e63dccd0d8d..6b7abe10eac5 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -662,6 +662,7 @@ osigreturn(td, uap) SIGSETOLD(p->p_sigmask, scp->sc_mask); SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); regs->tf_ebp = scp->sc_fp; regs->tf_esp = scp->sc_sp; @@ -771,6 +772,7 @@ sigreturn(td, uap) p->p_sigmask = ucp->uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); return (EJUSTRETURN); } diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 2042a8d9b33c..62487049d8f0 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -508,6 +508,7 @@ sigreturn(struct thread *td, struct sigreturn_args *uap) p->p_sigmask = uc.uc_sigmask; SIG_CANTMASK(p->p_sigmask); + signotify(p); PROC_UNLOCK(p); CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", td, tf->tf_tpc, tf->tf_sp, tf->tf_tstate); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index a75a8cfef972..f4cc25fc3dd2 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -503,6 +503,7 @@ struct proc { #define PS_PROFPEND 0x00040 /* Pending SIGPROF needs to be posted. */ #define PS_SWAPINREQ 0x00100 /* Swapin request due to wakeup. */ #define PS_SWAPPING 0x00200 /* Process is being swapped. */ +#define PS_NEEDSIGCHK 0x02000 /* Process may need signal delivery. */ /* flags kept in td_flags */ #define TDF_ONRUNQ 0x00001 /* This KE is on a run queue */ @@ -565,15 +566,6 @@ sigonstack(size_t sp) : 0); } -/* - * Notify the current process (p) that it has a signal pending, - * process as soon as possible. - */ -#define signotify(ke) do { \ - mtx_assert(&sched_lock, MA_OWNED); \ - (ke)->ke_flags |= KEF_ASTPENDING; \ -} while (0) - /* Handy macro to determine if p1 can mangle p2. */ #define PRISON_CHECK(p1, p2) \ ((p1)->p_prison == NULL || (p1)->p_prison == (p2)->p_prison) diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 77923c29c89e..31575c5f6e3c 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -233,6 +233,7 @@ void postsig(int sig); void psignal(struct proc *p, int sig); void sigexit(struct thread *td, int signum) __dead2; void siginit(struct proc *p); +void signotify(struct proc *p); void trapsignal(struct proc *p, int sig, u_long code); /* |