svn commit: r213642 - in head/sys: kern sys
Robert Watson
rwatson at FreeBSD.org
Sat Oct 9 12:00:40 UTC 2010
On Sat, 9 Oct 2010, David Xu wrote:
> Create a global thread hash table to speed up thread lookup, use
> rwlock to protect the table. In old code, thread lookup is done with
> process lock held, to find a thread, kernel has to iterate through
> process and thread list, this is quite inefficient.
> With this change, test shows in extreme case performance is
> dramatically improved.
Could you say a little more about which workloads this helps with?
Obviously, things that look up thread IDs, but since I'm less familiar with
the threading code, a hand-wave would give me useful intuitions!
BTW, my experience with switching to read-write locking in the pcbinfo hash
lookup is that it made a huge difference, and that I experience only fairly
incremental performance changes on <= 8 cores by trying to go to more refined
models (such as encouraging CPU affinity for table entries, etc).
Robert
>
> Earlier patch was reviewed by: jhb, julian
>
> Modified:
> head/sys/kern/init_main.c
> head/sys/kern/kern_exit.c
> head/sys/kern/kern_fork.c
> head/sys/kern/kern_kthread.c
> head/sys/kern/kern_resource.c
> head/sys/kern/kern_sig.c
> head/sys/kern/kern_thr.c
> head/sys/kern/kern_thread.c
> head/sys/kern/kern_time.c
> head/sys/kern/kern_umtx.c
> head/sys/kern/sys_process.c
> head/sys/kern/uipc_mqueue.c
> head/sys/kern/vfs_aio.c
> head/sys/sys/proc.h
> head/sys/sys/signalvar.h
>
> Modified: head/sys/kern/init_main.c
> ==============================================================================
> --- head/sys/kern/init_main.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/init_main.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -443,6 +443,7 @@ proc0_init(void *dummy __unused)
> */
> LIST_INSERT_HEAD(&allproc, p, p_list);
> LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
> + LIST_INSERT_HEAD(TIDHASH(0), td, td_hash);
> mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK);
> p->p_pgrp = &pgrp0;
> LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
>
> Modified: head/sys/kern/kern_exit.c
> ==============================================================================
> --- head/sys/kern/kern_exit.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_exit.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -403,6 +403,8 @@ exit1(struct thread *td, int rv)
> PROC_UNLOCK(p);
> lim_free(plim);
>
> + tidhash_remove(td);
> +
> /*
> * Remove proc from allproc queue and pidhash chain.
> * Place onto zombproc. Unlink from parent's child list.
>
> Modified: head/sys/kern/kern_fork.c
> ==============================================================================
> --- head/sys/kern/kern_fork.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_fork.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -456,7 +456,7 @@ again:
> AUDIT_ARG_PID(p2->p_pid);
> LIST_INSERT_HEAD(&allproc, p2, p_list);
> LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
> -
> + tidhash_add(td2);
> PROC_LOCK(p2);
> PROC_LOCK(p1);
>
>
> Modified: head/sys/kern/kern_kthread.c
> ==============================================================================
> --- head/sys/kern/kern_kthread.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_kthread.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -295,6 +295,7 @@ kthread_add(void (*func)(void *), void *
> thread_unlock(oldtd);
> PROC_UNLOCK(p);
>
> + tidhash_add(newtd);
>
> /* Delay putting it on the run queue until now. */
> if (!(flags & RFSTOPPED)) {
> @@ -314,6 +315,8 @@ kthread_exit(void)
>
> p = curthread->td_proc;
>
> + tidhash_remove(curthread);
> +
> /* A module may be waiting for us to exit. */
> wakeup(curthread);
> PROC_LOCK(p);
>
> Modified: head/sys/kern/kern_resource.c
> ==============================================================================
> --- head/sys/kern/kern_resource.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_resource.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -295,25 +295,23 @@ rtprio_thread(struct thread *td, struct
> else
> cierror = 0;
>
> - /*
> - * Though lwpid is unique, only current process is supported
> - * since there is no efficient way to look up a LWP yet.
> - */
> - p = td->td_proc;
> - PROC_LOCK(p);
> + if (uap->lwpid == 0 || uap->lwpid == td->td_tid) {
> + p = td->td_proc;
> + td1 = td;
> + PROC_LOCK(p);
> + } else {
> + /* Only look up thread in current process */
> + td1 = tdfind(uap->lwpid, curproc->p_pid);
> + if (td1 == NULL)
> + return (ESRCH);
> + p = td1->td_proc;
> + }
>
> switch (uap->function) {
> case RTP_LOOKUP:
> if ((error = p_cansee(td, p)))
> break;
> - if (uap->lwpid == 0 || uap->lwpid == td->td_tid)
> - td1 = td;
> - else
> - td1 = thread_find(p, uap->lwpid);
> - if (td1 != NULL)
> - pri_to_rtp(td1, &rtp);
> - else
> - error = ESRCH;
> + pri_to_rtp(td1, &rtp);
> PROC_UNLOCK(p);
> return (copyout(&rtp, uap->rtp, sizeof(struct rtprio)));
> case RTP_SET:
> @@ -337,15 +335,7 @@ rtprio_thread(struct thread *td, struct
> if (error)
> break;
> }
> -
> - if (uap->lwpid == 0 || uap->lwpid == td->td_tid)
> - td1 = td;
> - else
> - td1 = thread_find(p, uap->lwpid);
> - if (td1 != NULL)
> - error = rtp_to_pri(&rtp, td1);
> - else
> - error = ESRCH;
> + error = rtp_to_pri(&rtp, td1);
> break;
> default:
> error = EINVAL;
>
> Modified: head/sys/kern/kern_sig.c
> ==============================================================================
> --- head/sys/kern/kern_sig.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_sig.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -107,8 +107,6 @@ static int killpg1(struct thread *td, in
> ksiginfo_t *ksi);
> static int issignal(struct thread *td, int stop_allowed);
> static int sigprop(int sig);
> -static int tdsendsignal(struct proc *p, struct thread *td, int sig,
> - ksiginfo_t *ksi);
> static void tdsigwakeup(struct thread *, int, sig_t, int);
> static void sig_suspend_threads(struct thread *, struct proc *, int);
> static int filt_sigattach(struct knote *kn);
> @@ -1974,27 +1972,22 @@ pksignal(struct proc *p, int sig, ksigin
> return (tdsendsignal(p, NULL, sig, ksi));
> }
>
> +/* Utility function for finding a thread to send signal event to. */
> int
> -psignal_event(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi)
> +sigev_findtd(struct proc *p ,struct sigevent *sigev, struct thread **ttd)
> {
> - struct thread *td = NULL;
> -
> - PROC_LOCK_ASSERT(p, MA_OWNED);
> -
> - KASSERT(!KSI_ONQ(ksi), ("psignal_event: ksi on queue"));
> + struct thread *td;
>
> - /*
> - * ksi_code and other fields should be set before
> - * calling this function.
> - */
> - 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);
> + td = tdfind(sigev->sigev_notify_thread_id, p->p_pid);
> if (td == NULL)
> return (ESRCH);
> + *ttd = td;
> + } else {
> + *ttd = NULL;
> + PROC_LOCK(p);
> }
> - return (tdsendsignal(p, td, ksi->ksi_signo, ksi));
> + return (0);
> }
>
> void
> @@ -2015,7 +2008,7 @@ tdksignal(struct thread *td, int sig, ks
> (void) tdsendsignal(td->td_proc, td, sig, ksi);
> }
>
> -static int
> +int
> tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
> {
> sig_t action;
> @@ -2026,6 +2019,7 @@ tdsendsignal(struct proc *p, struct thre
> int ret = 0;
> int wakeup_swapper;
>
> + MPASS(td == NULL || p == td->td_proc);
> PROC_LOCK_ASSERT(p, MA_OWNED);
>
> if (!_SIG_VALID(sig))
>
> Modified: head/sys/kern/kern_thr.c
> ==============================================================================
> --- head/sys/kern/kern_thr.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_thr.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
> #include <sys/systm.h>
> #include <sys/sysproto.h>
> #include <sys/signalvar.h>
> +#include <sys/sx.h>
> #include <sys/ucontext.h>
> #include <sys/thr.h>
> #include <sys/rtprio.h>
> @@ -240,6 +241,9 @@ create_thread(struct thread *td, mcontex
> if (P_SHOULDSTOP(p))
> newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
> PROC_UNLOCK(p);
> +
> + tidhash_add(newtd);
> +
> thread_lock(newtd);
> if (rtp != NULL) {
> if (!(td->td_pri_class == PRI_TIMESHARE &&
> @@ -281,6 +285,8 @@ thr_exit(struct thread *td, struct thr_e
> kern_umtx_wake(td, uap->state, INT_MAX, 0);
> }
>
> + tidhash_remove(td);
> +
> PROC_LOCK(p);
> tdsigcleanup(td);
> PROC_SLOCK(p);
> @@ -309,18 +315,17 @@ thr_kill(struct thread *td, struct thr_k
> int error;
>
> p = td->td_proc;
> - error = 0;
> ksiginfo_init(&ksi);
> ksi.ksi_signo = uap->sig;
> ksi.ksi_code = SI_LWP;
> ksi.ksi_pid = p->p_pid;
> ksi.ksi_uid = td->td_ucred->cr_ruid;
> - PROC_LOCK(p);
> if (uap->id == -1) {
> if (uap->sig != 0 && !_SIG_VALID(uap->sig)) {
> error = EINVAL;
> } else {
> error = ESRCH;
> + PROC_LOCK(p);
> FOREACH_THREAD_IN_PROC(p, ttd) {
> if (ttd != td) {
> error = 0;
> @@ -329,22 +334,21 @@ thr_kill(struct thread *td, struct thr_k
> tdksignal(ttd, uap->sig, &ksi);
> }
> }
> + PROC_UNLOCK(p);
> }
> } else {
> - if (uap->id != td->td_tid)
> - ttd = thread_find(p, uap->id);
> - else
> - ttd = td;
> + error = 0;
> + ttd = tdfind((lwpid_t)uap->id, p->p_pid);
> if (ttd == NULL)
> - error = ESRCH;
> - else if (uap->sig == 0)
> + return (ESRCH);
> + if (uap->sig == 0)
> ;
> else if (!_SIG_VALID(uap->sig))
> error = EINVAL;
> - else
> + else
> tdksignal(ttd, uap->sig, &ksi);
> + PROC_UNLOCK(ttd->td_proc);
> }
> - PROC_UNLOCK(p);
> return (error);
> }
>
> @@ -359,51 +363,49 @@ thr_kill2(struct thread *td, struct thr_
>
> AUDIT_ARG_SIGNUM(uap->sig);
>
> - if (uap->pid == td->td_proc->p_pid) {
> - p = td->td_proc;
> - PROC_LOCK(p);
> - } else if ((p = pfind(uap->pid)) == NULL) {
> - return (ESRCH);
> - }
> - AUDIT_ARG_PROCESS(p);
> -
> - error = p_cansignal(td, p, uap->sig);
> - if (error == 0) {
> - ksiginfo_init(&ksi);
> - ksi.ksi_signo = uap->sig;
> - ksi.ksi_code = SI_LWP;
> - ksi.ksi_pid = td->td_proc->p_pid;
> - ksi.ksi_uid = td->td_ucred->cr_ruid;
> - if (uap->id == -1) {
> - if (uap->sig != 0 && !_SIG_VALID(uap->sig)) {
> - error = EINVAL;
> - } else {
> - error = ESRCH;
> - FOREACH_THREAD_IN_PROC(p, ttd) {
> - if (ttd != td) {
> - error = 0;
> - if (uap->sig == 0)
> - break;
> - tdksignal(ttd, uap->sig, &ksi);
> - }
> + ksiginfo_init(&ksi);
> + ksi.ksi_signo = uap->sig;
> + ksi.ksi_code = SI_LWP;
> + ksi.ksi_pid = td->td_proc->p_pid;
> + ksi.ksi_uid = td->td_ucred->cr_ruid;
> + if (uap->id == -1) {
> + if ((p = pfind(uap->pid)) == NULL)
> + return (ESRCH);
> + AUDIT_ARG_PROCESS(p);
> + error = p_cansignal(td, p, uap->sig);
> + if (error) {
> + PROC_UNLOCK(p);
> + return (error);
> + }
> + if (uap->sig != 0 && !_SIG_VALID(uap->sig)) {
> + error = EINVAL;
> + } else {
> + error = ESRCH;
> + FOREACH_THREAD_IN_PROC(p, ttd) {
> + if (ttd != td) {
> + error = 0;
> + if (uap->sig == 0)
> + break;
> + tdksignal(ttd, uap->sig, &ksi);
> }
> }
> - } else {
> - if (uap->id != td->td_tid)
> - ttd = thread_find(p, uap->id);
> - else
> - ttd = td;
> - if (ttd == NULL)
> - error = ESRCH;
> - else if (uap->sig == 0)
> - ;
> - else if (!_SIG_VALID(uap->sig))
> - error = EINVAL;
> - else
> - tdksignal(ttd, uap->sig, &ksi);
> }
> + PROC_UNLOCK(p);
> + } else {
> + ttd = tdfind((lwpid_t)uap->id, uap->pid);
> + if (ttd == NULL)
> + return (ESRCH);
> + p = ttd->td_proc;
> + AUDIT_ARG_PROCESS(p);
> + error = p_cansignal(td, p, uap->sig);
> + if (uap->sig == 0)
> + ;
> + else if (!_SIG_VALID(uap->sig))
> + error = EINVAL;
> + else
> + tdksignal(ttd, uap->sig, &ksi);
> + PROC_UNLOCK(p);
> }
> - PROC_UNLOCK(p);
> return (error);
> }
>
> @@ -485,12 +487,9 @@ thr_wake(struct thread *td, struct thr_w
> }
>
> p = td->td_proc;
> - PROC_LOCK(p);
> - ttd = thread_find(p, uap->id);
> - if (ttd == NULL) {
> - PROC_UNLOCK(p);
> + ttd = tdfind((lwpid_t)uap->id, p->p_pid);
> + if (ttd == NULL)
> return (ESRCH);
> - }
> thread_lock(ttd);
> ttd->td_flags |= TDF_THRWAKEUP;
> thread_unlock(ttd);
> @@ -502,7 +501,7 @@ thr_wake(struct thread *td, struct thr_w
> int
> thr_set_name(struct thread *td, struct thr_set_name_args *uap)
> {
> - struct proc *p = td->td_proc;
> + struct proc *p;
> char name[MAXCOMLEN + 1];
> struct thread *ttd;
> int error;
> @@ -515,15 +514,11 @@ thr_set_name(struct thread *td, struct t
> if (error)
> return (error);
> }
> - PROC_LOCK(p);
> - if (uap->id == td->td_tid)
> - ttd = td;
> - else
> - ttd = thread_find(p, uap->id);
> - if (ttd != NULL)
> - strcpy(ttd->td_name, name);
> - else
> - error = ESRCH;
> + p = td->td_proc;
> + ttd = tdfind((lwpid_t)uap->id, p->p_pid);
> + if (ttd == NULL)
> + return (ESRCH);
> + strcpy(ttd->td_name, name);
> PROC_UNLOCK(p);
> return (error);
> }
>
> Modified: head/sys/kern/kern_thread.c
> ==============================================================================
> --- head/sys/kern/kern_thread.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_thread.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
> #include <sys/selinfo.h>
> #include <sys/turnstile.h>
> #include <sys/ktr.h>
> +#include <sys/rwlock.h>
> #include <sys/umtx.h>
> #include <sys/cpuset.h>
> #ifdef HWPMC_HOOKS
> @@ -83,6 +84,12 @@ static void thread_zombie(struct thread
> struct mtx tid_lock;
> static struct unrhdr *tid_unrhdr;
>
> +static MALLOC_DEFINE(M_TIDHASH, "tidhash", "thread hash");
> +
> +struct tidhashhead *tidhashtbl;
> +u_long tidhash;
> +struct rwlock tidhash_lock;
> +
> /*
> * Prepare a thread for use.
> */
> @@ -230,6 +237,8 @@ threadinit(void)
> thread_zone = uma_zcreate("THREAD", sched_sizeof_thread(),
> thread_ctor, thread_dtor, thread_init, thread_fini,
> 16 - 1, 0);
> + tidhashtbl = hashinit(maxproc / 2, M_TIDHASH, &tidhash);
> + rw_init(&tidhash_lock, "tidhash");
> }
>
> /*
> @@ -748,8 +757,14 @@ thread_suspend_check(int return_instead)
> * this thread should just suicide.
> * Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE.
> */
> - if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td))
> + if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
> + PROC_SUNLOCK(p);
> + PROC_UNLOCK(p);
> + tidhash_remove(td);
> + PROC_LOCK(p);
> + PROC_SLOCK(p);
> thread_exit();
> + }
> if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
> if (p->p_numthreads == p->p_suspcount + 1) {
> thread_lock(p->p_singlethread);
> @@ -923,3 +938,57 @@ thread_find(struct proc *p, lwpid_t tid)
> }
> return (td);
> }
> +
> +/* Locate a thread by number; return with proc lock held. */
> +struct thread *
> +tdfind(lwpid_t tid, pid_t pid)
> +{
> +#define RUN_THRESH 16
> + struct thread *td;
> + int run = 0;
> +
> + rw_rlock(&tidhash_lock);
> + LIST_FOREACH(td, TIDHASH(tid), td_hash) {
> + if (td->td_tid == tid) {
> + if (pid != -1 && td->td_proc->p_pid != pid) {
> + td = NULL;
> + break;
> + }
> + if (td->td_proc->p_state == PRS_NEW) {
> + td = NULL;
> + break;
> + }
> + if (run > RUN_THRESH) {
> + if (rw_try_upgrade(&tidhash_lock)) {
> + LIST_REMOVE(td, td_hash);
> + LIST_INSERT_HEAD(TIDHASH(td->td_tid),
> + td, td_hash);
> + PROC_LOCK(td->td_proc);
> + rw_wunlock(&tidhash_lock);
> + return (td);
> + }
> + }
> + PROC_LOCK(td->td_proc);
> + break;
> + }
> + run++;
> + }
> + rw_runlock(&tidhash_lock);
> + return (td);
> +}
> +
> +void
> +tidhash_add(struct thread *td)
> +{
> + rw_wlock(&tidhash_lock);
> + LIST_INSERT_HEAD(TIDHASH(td->td_tid), td, td_hash);
> + rw_wunlock(&tidhash_lock);
> +}
> +
> +void
> +tidhash_remove(struct thread *td)
> +{
> + rw_wlock(&tidhash_lock);
> + LIST_REMOVE(td, td_hash);
> + rw_wunlock(&tidhash_lock);
> +}
>
> Modified: head/sys/kern/kern_time.c
> ==============================================================================
> --- head/sys/kern/kern_time.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_time.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -1402,28 +1402,22 @@ void
> itimer_fire(struct itimer *it)
> {
> struct proc *p = it->it_proc;
> - int ret;
> + struct thread *td;
>
> if (it->it_sigev.sigev_notify == SIGEV_SIGNAL ||
> it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
> - PROC_LOCK(p);
> + if (sigev_findtd(p, &it->it_sigev, &td) != 0) {
> + ITIMER_LOCK(it);
> + timespecclear(&it->it_time.it_value);
> + timespecclear(&it->it_time.it_interval);
> + callout_stop(&it->it_callout);
> + ITIMER_UNLOCK(it);
> + return;
> + }
> if (!KSI_ONQ(&it->it_ksi)) {
> it->it_ksi.ksi_errno = 0;
> - 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.
> - */
> - 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);
> - }
> - }
> + ksiginfo_set_sigev(&it->it_ksi, &it->it_sigev);
> + tdsendsignal(p, td, it->it_ksi.ksi_signo, &it->it_ksi);
> } else {
> if (it->it_overrun < INT_MAX)
> it->it_overrun++;
>
> Modified: head/sys/kern/kern_umtx.c
> ==============================================================================
> --- head/sys/kern/kern_umtx.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/kern_umtx.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -1588,20 +1588,15 @@ umtxq_sleep_pi(struct umtx_q *uq, struct
> umtxq_insert(uq);
> mtx_lock_spin(&umtx_lock);
> if (pi->pi_owner == NULL) {
> - /* XXX
> - * Current, We only support process private PI-mutex,
> - * we need a faster way to find an owner thread for
> - * process-shared mutex (not available yet).
> - */
> mtx_unlock_spin(&umtx_lock);
> - PROC_LOCK(curproc);
> - td1 = thread_find(curproc, owner);
> + /* XXX Only look up thread in current process. */
> + td1 = tdfind(owner, curproc->p_pid);
> mtx_lock_spin(&umtx_lock);
> if (td1 != NULL && pi->pi_owner == NULL) {
> uq1 = td1->td_umtxq;
> umtx_pi_setowner(pi, td1);
> }
> - PROC_UNLOCK(curproc);
> + PROC_UNLOCK(td1->td_proc);
> }
>
> TAILQ_FOREACH(uq1, &pi->pi_blocked, uq_lockq) {
>
> Modified: head/sys/kern/sys_process.c
> ==============================================================================
> --- head/sys/kern/sys_process.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/sys_process.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -721,24 +721,13 @@ kern_ptrace(struct thread *td, int req,
> return (ESRCH);
> }
> } else {
> - /* this is slow, should be optimized */
> - sx_slock(&allproc_lock);
> - FOREACH_PROC_IN_SYSTEM(p) {
> - PROC_LOCK(p);
> - FOREACH_THREAD_IN_PROC(p, td2) {
> - if (td2->td_tid == pid)
> - break;
> - }
> - if (td2 != NULL)
> - break; /* proc lock held */
> - PROC_UNLOCK(p);
> - }
> - sx_sunlock(&allproc_lock);
> - if (p == NULL) {
> + td2 = tdfind(pid, -1);
> + if (td2 == NULL) {
> if (proctree_locked)
> sx_xunlock(&proctree_lock);
> return (ESRCH);
> }
> + p = td2->td_proc;
> tid = pid;
> pid = p->p_pid;
> }
>
> Modified: head/sys/kern/uipc_mqueue.c
> ==============================================================================
> --- head/sys/kern/uipc_mqueue.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/uipc_mqueue.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -1747,15 +1747,23 @@ static void
> mqueue_send_notification(struct mqueue *mq)
> {
> struct mqueue_notifier *nt;
> + struct thread *td;
> struct proc *p;
> + int error;
>
> mtx_assert(&mq->mq_mutex, MA_OWNED);
> nt = mq->mq_notifier;
> if (nt->nt_sigev.sigev_notify != SIGEV_NONE) {
> p = nt->nt_proc;
> - PROC_LOCK(p);
> - if (!KSI_ONQ(&nt->nt_ksi))
> - psignal_event(p, &nt->nt_sigev, &nt->nt_ksi);
> + error = sigev_findtd(p, &nt->nt_sigev, &td);
> + if (error) {
> + mq->mq_notifier = NULL;
> + return;
> + }
> + if (!KSI_ONQ(&nt->nt_ksi)) {
> + ksiginfo_set_sigev(&nt->nt_ksi, &nt->nt_sigev);
> + tdsendsignal(p, td, nt->nt_ksi.ksi_signo, &nt->nt_ksi);
> + }
> PROC_UNLOCK(p);
> }
> mq->mq_notifier = NULL;
>
> Modified: head/sys/kern/vfs_aio.c
> ==============================================================================
> --- head/sys/kern/vfs_aio.c Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/kern/vfs_aio.c Sat Oct 9 02:50:23 2010 (r213642)
> @@ -609,16 +609,20 @@ aio_init_aioinfo(struct proc *p)
> static int
> aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi)
> {
> - int ret = 0;
> + struct thread *td;
> + int error;
>
> - PROC_LOCK(p);
> + error = sigev_findtd(p, sigev, &td);
> + if (error)
> + return (error);
> if (!KSI_ONQ(ksi)) {
> + ksiginfo_set_sigev(ksi, sigev);
> ksi->ksi_code = SI_ASYNCIO;
> ksi->ksi_flags |= KSI_EXT | KSI_INS;
> - ret = psignal_event(p, sigev, ksi);
> + tdsendsignal(p, td, ksi->ksi_signo, ksi);
> }
> PROC_UNLOCK(p);
> - return (ret);
> + return (error);
> }
>
> /*
>
> Modified: head/sys/sys/proc.h
> ==============================================================================
> --- head/sys/sys/proc.h Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/sys/proc.h Sat Oct 9 02:50:23 2010 (r213642)
> @@ -205,6 +205,7 @@ struct thread {
> TAILQ_ENTRY(thread) td_runq; /* (t) Run queue. */
> TAILQ_ENTRY(thread) td_slpq; /* (t) Sleep queue. */
> TAILQ_ENTRY(thread) td_lockq; /* (t) Lock queue. */
> + LIST_ENTRY(thread) td_hash; /* (d) Hash chain. */
> struct cpuset *td_cpuset; /* (t) CPU affinity mask. */
> struct seltd *td_sel; /* Select queue/channel. */
> struct sleepqueue *td_sleepqueue; /* (k) Associated sleep queue. */
> @@ -766,6 +767,10 @@ MALLOC_DECLARE(M_ZOMBIE);
> #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash])
> extern LIST_HEAD(pidhashhead, proc) *pidhashtbl;
> extern u_long pidhash;
> +#define TIDHASH(tid) (&tidhashtbl[(tid) & tidhash])
> +extern LIST_HEAD(tidhashhead, thread) *tidhashtbl;
> +extern u_long tidhash;
> +extern struct rwlock tidhash_lock;
>
> #define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash])
> extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl;
> @@ -837,7 +842,10 @@ void setsugid(struct proc *p);
> int sigonstack(size_t sp);
> void sleepinit(void);
> void stopevent(struct proc *, u_int, u_int);
> +struct thread *tdfind(lwpid_t, pid_t);
> void threadinit(void);
> +void tidhash_add(struct thread *);
> +void tidhash_remove(struct thread *);
> void cpu_idle(int);
> int cpu_idle_wakeup(int);
> extern void (*cpu_idle_hook)(void); /* Hook to machdep CPU idler. */
>
> Modified: head/sys/sys/signalvar.h
> ==============================================================================
> --- head/sys/sys/signalvar.h Sat Oct 9 00:36:32 2010 (r213641)
> +++ head/sys/sys/signalvar.h Sat Oct 9 02:50:23 2010 (r213642)
> @@ -294,6 +294,13 @@ ksiginfo_copy(ksiginfo_t *src, ksiginfo_
> (dst)->ksi_flags = (src->ksi_flags & KSI_COPYMASK);
> }
>
> +static __inline void
> +ksiginfo_set_sigev(ksiginfo_t *dst, struct sigevent *sigev)
> +{
> + dst->ksi_signo = sigev->sigev_signo;
> + dst->ksi_value = sigev->sigev_value;
> +}
> +
> struct pgrp;
> struct proc;
> struct sigio;
> @@ -331,7 +338,6 @@ void pgsigio(struct sigio **sigiop, int
> void pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi);
> int postsig(int sig);
> void psignal(struct proc *p, int sig);
> -int psignal_event(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi);
> int ptracestop(struct thread *td, int sig);
> void sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *retmask);
> struct sigacts *sigacts_alloc(void);
> @@ -340,6 +346,7 @@ void sigacts_free(struct sigacts *ps);
> struct sigacts *sigacts_hold(struct sigacts *ps);
> int sigacts_shared(struct sigacts *ps);
> void sigexit(struct thread *td, int sig) __dead2;
> +int sigev_findtd(struct proc *p, struct sigevent *sigev, struct thread **);
> int sig_ffs(sigset_t *set);
> void siginit(struct proc *p);
> void signotify(struct thread *td);
> @@ -349,6 +356,8 @@ void sigqueue_flush(struct sigqueue *que
> void sigqueue_init(struct sigqueue *queue, struct proc *p);
> void sigqueue_take(ksiginfo_t *ksi);
> void tdksignal(struct thread *td, int sig, ksiginfo_t *ksi);
> +int tdsendsignal(struct proc *p, struct thread *td, int sig,
> + ksiginfo_t *ksi);
> void tdsigcleanup(struct thread *td);
> void tdsignal(struct thread *td, int sig);
> void trapsignal(struct thread *td, ksiginfo_t *ksi);
>
More information about the svn-src-head
mailing list