summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2002-04-04 17:49:48 +0000
committerbde <bde@FreeBSD.org>2002-04-04 17:49:48 +0000
commit14ae95f735978b62fd4a040a2f05a7d5c5a30712 (patch)
tree27b9df7330c17460156c8810b34fef449a2d1764 /sys
parent2a571683e0a57e785364a0bccbf360ed24409bd1 (diff)
downloadFreeBSD-src-14ae95f735978b62fd4a040a2f05a7d5c5a30712.zip
FreeBSD-src-14ae95f735978b62fd4a040a2f05a7d5c5a30712.tar.gz
Moved signal handling and rescheduling from userret() to ast() so that
they aren't in the usual path of execution for syscalls and traps. The main complication for this is that we have to set flags to control ast() everywhere that changes the signal mask. Avoid locking in userret() in most of the remaining cases. Submitted by: luoqi (first part only, long ago, reorganized by me) Reminded by: dillon
Diffstat (limited to 'sys')
-rw-r--r--sys/alpha/alpha/machdep.c2
-rw-r--r--sys/alpha/osf1/osf1_signal.c3
-rw-r--r--sys/amd64/amd64/machdep.c2
-rw-r--r--sys/coda/coda_psdev.c1
-rw-r--r--sys/compat/linux/linux_signal.c3
-rw-r--r--sys/compat/svr4/svr4_signal.c2
-rw-r--r--sys/fs/coda/coda_psdev.c1
-rw-r--r--sys/i386/i386/machdep.c2
-rw-r--r--sys/i386/ibcs2/ibcs2_signal.c3
-rw-r--r--sys/i386/linux/linux_sysvec.c2
-rw-r--r--sys/i386/svr4/svr4_machdep.c1
-rw-r--r--sys/ia64/ia64/machdep.c1
-rw-r--r--sys/kern/kern_sig.c28
-rw-r--r--sys/kern/subr_trap.c68
-rw-r--r--sys/pc98/i386/machdep.c2
-rw-r--r--sys/pc98/pc98/machdep.c2
-rw-r--r--sys/sparc64/sparc64/machdep.c1
-rw-r--r--sys/sys/proc.h10
-rw-r--r--sys/sys/signalvar.h1
19 files changed, 101 insertions, 34 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c
index e9e47ef..2319780 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 9e0cf5a..61803e7 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 ffb2094..c8b7c5e 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 c2653ec..8ed4f22 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 ccc30f0..3a5f6e5 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 471022a..fea5317 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 c2653ec..8ed4f22 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 ffb2094..c8b7c5e 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 fd32aaf..12bd038 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 e1321ef..c8bc6c8 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 c82718d..c015888 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 412d6dc..b21b9b5 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 bfefd24..6adda1d 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 4dcf90c..a5b035a 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 9e63dcc..6b7abe1 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 9e63dcc..6b7abe1 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 2042a8d..6248704 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 a75a8cf..f4cc25f 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 77923c2..31575c5 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);
/*
OpenPOWER on IntegriCloud