summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sig.c
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/kern/kern_sig.c
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/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c28
1 files changed, 25 insertions, 3 deletions
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);
OpenPOWER on IntegriCloud