summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2005-11-03 04:49:16 +0000
committerdavidxu <davidxu@FreeBSD.org>2005-11-03 04:49:16 +0000
commit301b115d609d2595189bf67894c5e3db2fd34cb0 (patch)
treeb8ef20963382d8a5edc4b03cfb0512134beca910 /sys
parentc4f51b40511670f148550caa0d16bba6bd30f3fa (diff)
downloadFreeBSD-src-301b115d609d2595189bf67894c5e3db2fd34cb0.zip
FreeBSD-src-301b115d609d2595189bf67894c5e3db2fd34cb0.tar.gz
Cleanup some signal interfaces. Now the tdsignal function accepts
both proc pointer and thread pointer, if thread pointer is NULL, tdsignal automatically finds a thread, otherwise it sends signal to given thread. Add utility function psignal_event to send a realtime sigevent to a process according to the delivery requirement specified in struct sigevent.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_exec.c2
-rw-r--r--sys/kern/kern_kse.c2
-rw-r--r--sys/kern/kern_sig.c95
-rw-r--r--sys/kern/kern_thr.c2
-rw-r--r--sys/kern/kern_time.c39
-rw-r--r--sys/sys/signalvar.h13
6 files changed, 67 insertions, 86 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 811bd9f..51f012f 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -670,7 +670,7 @@ interpret:
* single thread mode.
*/
if (p->p_flag & P_TRACED)
- tdsignal(td, SIGTRAP, NULL, SIGTARGET_TD);
+ tdsignal(p, td, SIGTRAP, NULL);
/* clear "fork but no exec" flag, as we _are_ execing */
p->p_acflag &= ~AFORK;
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index f3c9a3e..15c0f18 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -210,7 +210,7 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
if (uap->data > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
- tdsignal(td2, (int)uap->data, NULL, SIGTARGET_TD);
+ tdsignal(p, td2, (int)uap->data, NULL);
} else {
mtx_unlock_spin(&sched_lock);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index d63affa..bfa9ff3 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -96,9 +96,8 @@ static int filt_signal(struct knote *kn, long hint);
static struct thread *sigtd(struct proc *p, int sig, int prop);
static int kern_sigtimedwait(struct thread *, sigset_t,
ksiginfo_t *, struct timespec *);
-static int do_tdsignal(struct thread *, int, ksiginfo_t *, sigtarget_t);
+static int do_tdsignal(struct proc *, struct thread *, int, ksiginfo_t *);
static void sigqueue_start(void);
-static int psignal_common(struct proc *p, int sig, ksiginfo_t *ksi);
static uma_zone_t ksiginfo_zone = NULL;
struct filterops sig_filtops =
@@ -1787,7 +1786,7 @@ sigqueue(struct thread *td, struct sigqueue_args *uap)
ksi.ksi_pid = td->td_proc->p_pid;
ksi.ksi_uid = td->td_ucred->cr_ruid;
ksi.ksi_value.sigval_ptr = uap->value;
- error = psignal_info(p, &ksi);
+ error = tdsignal(p, NULL, ksi.ksi_signo, &ksi);
}
PROC_UNLOCK(p);
return (error);
@@ -1922,7 +1921,7 @@ trapsignal(struct thread *td, ksiginfo_t *ksi)
mtx_unlock(&ps->ps_mtx);
p->p_code = code; /* XXX for core dump/debugger */
p->p_sig = sig; /* XXX to verify code */
- tdsignal(td, sig, ksi, SIGTARGET_TD);
+ tdsignal(p, td, sig, ksi);
}
PROC_UNLOCK(p);
}
@@ -1972,53 +1971,44 @@ sigtd(struct proc *p, int sig, int prop)
void
psignal(struct proc *p, int sig)
{
- (void) psignal_common(p, sig, NULL);
+ (void) tdsignal(p, NULL, sig, NULL);
}
int
-psignal_info(struct proc *p, ksiginfo_t *ksi)
+psignal_event(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi)
{
- return (psignal_common(p, ksi->ksi_signo, ksi));
-}
-
-static int
-psignal_common(struct proc *p, int sig, ksiginfo_t *ksi)
-{
- struct thread *td;
- int prop;
-
- if (!_SIG_VALID(sig))
- panic("psignal(): invalid signal");
+ struct thread *td = NULL;
PROC_LOCK_ASSERT(p, MA_OWNED);
- /*
- * IEEE Std 1003.1-2001: return success when killing a zombie.
- */
- if (p->p_state == PRS_ZOMBIE)
- return (0);
- prop = sigprop(sig);
+
+ KASSERT(!KSI_ONQ(ksi), ("psignal_event: ksi on queue"));
/*
- * Find a thread to deliver the signal to.
+ * ksi_code and other fields should be set before
+ * calling this function.
*/
- td = sigtd(p, sig, prop);
-
- return (tdsignal(td, sig, ksi, SIGTARGET_P));
+ ksi->ksi_signo = sigev->sigev_signo;
+ ksi->ksi_value = sigev->sigev_value;
+ if (sigev->sigev_notify == SIGEV_THREAD_ID) {
+ td = thread_find(p, sigev->sigev_notify_thread_id);
+ if (td == NULL)
+ return (ESRCH);
+ }
+ return (tdsignal(p, td, ksi->ksi_signo, ksi));
}
/*
* MPSAFE
*/
int
-tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
+tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
{
sigset_t saved;
- struct proc *p = td->td_proc;
int ret;
if (p->p_flag & P_SA)
saved = p->p_sigqueue.sq_signals;
- ret = do_tdsignal(td, sig, ksi, target);
+ ret = do_tdsignal(p, td, sig, ksi);
if ((p->p_flag & P_SA) && !(p->p_flag & P_SIGEVENT)) {
if (!SIGSETEQ(saved, p->p_sigqueue.sq_signals)) {
/* pending set changed */
@@ -2030,9 +2020,8 @@ tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
}
static int
-do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
+do_tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
{
- struct proc *p;
sig_t action;
sigqueue_t *sigqueue;
struct thread *td0;
@@ -2040,15 +2029,24 @@ do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
struct sigacts *ps;
int ret = 0;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
if (!_SIG_VALID(sig))
panic("do_tdsignal(): invalid signal");
- p = td->td_proc;
- ps = p->p_sigacts;
+ KASSERT(ksi == NULL || !KSI_ONQ(ksi), ("do_tdsignal: ksi on queue"));
- PROC_LOCK_ASSERT(p, MA_OWNED);
- KNOTE_LOCKED(&p->p_klist, NOTE_SIGNAL | sig);
+ /*
+ * IEEE Std 1003.1-2001: return success when killing a zombie.
+ */
+ if (p->p_state == PRS_ZOMBIE) {
+ if (ksi && (ksi->ksi_flags & KSI_INS))
+ ksiginfo_tryfree(ksi);
+ return (ret);
+ }
+ ps = p->p_sigacts;
+ KNOTE_LOCKED(&p->p_klist, NOTE_SIGNAL | sig);
prop = sigprop(sig);
/*
@@ -2056,13 +2054,15 @@ do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
* assign it to the process so that we can find it later in the first
* thread that unblocks it. Otherwise, assign it to this thread now.
*/
- if (target == SIGTARGET_TD) {
- sigqueue = &td->td_sigqueue;
- } else {
- if (!SIGISMEMBER(td->td_sigmask, sig))
- sigqueue = &td->td_sigqueue;
- else
+ if (td == NULL) {
+ td = sigtd(p, sig, prop);
+ if (SIGISMEMBER(td->td_sigmask, sig))
sigqueue = &p->p_sigqueue;
+ else
+ sigqueue = &td->td_sigqueue;
+ } else {
+ KASSERT(td->td_proc == p, ("invalid thread"));
+ sigqueue = &td->td_sigqueue;
}
/*
@@ -2077,6 +2077,8 @@ do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
if (SIGISMEMBER(ps->ps_sigignore, sig) ||
(p->p_flag & P_WEXIT)) {
mtx_unlock(&ps->ps_mtx);
+ if (ksi && (ksi->ksi_flags & KSI_INS))
+ ksiginfo_tryfree(ksi);
return (ret);
}
if (SIGISMEMBER(td->td_sigmask, sig))
@@ -2098,8 +2100,11 @@ do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
*/
if ((prop & SA_TTYSTOP) &&
(p->p_pgrp->pg_jobc == 0) &&
- (action == SIG_DFL))
- return (ret);
+ (action == SIG_DFL)) {
+ if (ksi && (ksi->ksi_flags & KSI_INS))
+ ksiginfo_tryfree(ksi);
+ return (ret);
+ }
sigqueue_delete_proc(p, SIGCONT);
p->p_flag &= ~P_CONTINUED;
}
@@ -2107,7 +2112,7 @@ do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target)
ret = sigqueue_add(sigqueue, sig, ksi);
if (ret != 0)
return (ret);
- signotify(td); /* uses schedlock */
+ signotify(td);
/*
* Defer further processing for signals which are held,
* except that stopped processes must be continued by SIGCONT.
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 1b19533..6b67672 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -321,7 +321,7 @@ thr_kill(struct thread *td, struct thr_kill_args *uap)
error = EINVAL;
goto out;
}
- tdsignal(ttd, uap->sig, NULL, SIGTARGET_TD);
+ tdsignal(p, ttd, uap->sig, NULL);
out:
PROC_UNLOCK(p);
return (error);
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 7d3ac1a..b796529 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1413,46 +1413,29 @@ void
itimer_fire(struct itimer *it)
{
struct proc *p = it->it_proc;
- struct thread *td;
+ int ret;
if (it->it_sigev.sigev_notify == SIGEV_SIGNAL ||
it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
PROC_LOCK(p);
- if (KSI_ONQ(&it->it_ksi)) {
- it->it_overrun++;
- } else {
- if (it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
- /* XXX
- * This is too slow if there are many threads,
- * why the world don't have a thread hash table,
- * sigh.
+ if (!KSI_ONQ(&it->it_ksi)) {
+ ret = psignal_event(p, &it->it_sigev, &it->it_ksi);
+ if (__predict_false(ret != 0)) {
+ it->it_overrun++;
+ /*
+ * Broken userland code, thread went
+ * away, disarm the timer.
*/
- FOREACH_THREAD_IN_PROC(p, td) {
- if (td->td_tid ==
- it->it_sigev.sigev_notify_thread_id)
- break;
- }
- if (td != NULL)
- tdsignal(td, it->it_ksi.ksi_signo,
- &it->it_ksi, SIGTARGET_TD);
- else {
- /*
- * Broken userland code, thread went
- * away, disarm the timer.
- */
-#if 0
- it->it_overrun++;
-#else
+ if (ret == ESRCH) {
ITIMER_LOCK(it);
timespecclear(&it->it_time.it_value);
timespecclear(&it->it_time.it_interval);
callout_stop(&it->it_callout);
ITIMER_UNLOCK(it);
-#endif
}
- } else {
- psignal_info(p, &it->it_ksi);
}
+ } else {
+ it->it_overrun++;
}
PROC_UNLOCK(p);
}
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index cde9742..0338635 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -248,13 +248,6 @@ typedef struct sigqueue {
#ifdef _KERNEL
-/*
- * Specifies the target of a signal.
- * P - Doesn't matter which thread it gets delivered to.
- * TD - Must be delivered to a specific thread.
- */
-typedef enum sigtarget_enum { SIGTARGET_P, SIGTARGET_TD } sigtarget_t;
-
/* Return nonzero if process p has an unmasked pending signal. */
#define SIGPENDING(td) \
(!SIGISEMPTY((td)->td_siglist) && \
@@ -326,7 +319,7 @@ void pgsigio(struct sigio **, int signum, int checkctty);
void pgsignal(struct pgrp *pgrp, int sig, int checkctty);
void postsig(int sig);
void psignal(struct proc *p, int sig);
-int psignal_info(struct proc *p, ksiginfo_t *ksi);
+int psignal_event(struct proc *p, struct sigevent *, ksiginfo_t *);
struct sigacts *sigacts_alloc(void);
void sigacts_copy(struct sigacts *dest, struct sigacts *src);
void sigacts_free(struct sigacts *ps);
@@ -336,8 +329,8 @@ void sigexit(struct thread *td, int signum) __dead2;
int sig_ffs(sigset_t *set);
void siginit(struct proc *p);
void signotify(struct thread *td);
-int tdsignal(struct thread *td, int sig, ksiginfo_t *ksi,
- sigtarget_t target);
+int tdsignal(struct proc *p, struct thread *td, int sig,
+ ksiginfo_t *ksi);
void trapsignal(struct thread *td, ksiginfo_t *);
int ptracestop(struct thread *td, int sig);
ksiginfo_t * ksiginfo_alloc(void);
OpenPOWER on IntegriCloud