From 301b115d609d2595189bf67894c5e3db2fd34cb0 Mon Sep 17 00:00:00 2001 From: davidxu Date: Thu, 3 Nov 2005 04:49:16 +0000 Subject: 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. --- sys/kern/kern_exec.c | 2 +- sys/kern/kern_kse.c | 2 +- sys/kern/kern_sig.c | 95 +++++++++++++++++++++++++++------------------------- sys/kern/kern_thr.c | 2 +- sys/kern/kern_time.c | 39 ++++++--------------- sys/sys/signalvar.h | 13 ++----- 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); -- cgit v1.1