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);

_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to