Date: Sat, 9 Oct 2010 13:00:38 +0100 (BST) From: Robert Watson <rwatson@FreeBSD.org> To: David Xu <davidxu@FreeBSD.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r213642 - in head/sys: kern sys Message-ID: <alpine.BSF.2.00.1010091256390.1232@fledge.watson.org> In-Reply-To: <201010090250.o992oNw0022369@svn.freebsd.org> References: <201010090250.o992oNw0022369@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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); >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.BSF.2.00.1010091256390.1232>