summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-10-09 02:50:23 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-10-09 02:50:23 +0000
commit55194e796cd9e8eb27d9bb4ec9f07184e390d01a (patch)
tree84ad0652e39fc58da6ca522cc6bf55a188109780 /sys
parent6afff59f3c11c8f879672f8dbcb0a74bcbae79a5 (diff)
downloadFreeBSD-src-55194e796cd9e8eb27d9bb4ec9f07184e390d01a.zip
FreeBSD-src-55194e796cd9e8eb27d9bb4ec9f07184e390d01a.tar.gz
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. Earlier patch was reviewed by: jhb, julian
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/init_main.c1
-rw-r--r--sys/kern/kern_exit.c2
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_kthread.c3
-rw-r--r--sys/kern/kern_resource.c36
-rw-r--r--sys/kern/kern_sig.c28
-rw-r--r--sys/kern/kern_thr.c127
-rw-r--r--sys/kern/kern_thread.c71
-rw-r--r--sys/kern/kern_time.c28
-rw-r--r--sys/kern/kern_umtx.c11
-rw-r--r--sys/kern/sys_process.c17
-rw-r--r--sys/kern/uipc_mqueue.c14
-rw-r--r--sys/kern/vfs_aio.c12
-rw-r--r--sys/sys/proc.h8
-rw-r--r--sys/sys/signalvar.h11
15 files changed, 216 insertions, 155 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index de35a52..1dd8e73 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -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);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 8358f75..029f1c3 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -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.
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 81631f6..da2c415 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -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);
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 264fc4a..9ab0922 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -295,6 +295,7 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p,
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);
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index ec2d6b6..09c8603 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -295,25 +295,23 @@ rtprio_thread(struct thread *td, struct rtprio_thread_args *uap)
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 rtprio_thread_args *uap)
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;
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index d315ff1..4ac4d78 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -107,8 +107,6 @@ static int killpg1(struct thread *td, int sig, int pgid, int all,
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, ksiginfo_t *ksi)
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, ksiginfo_t *ksi)
(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 thread *td, int sig, ksiginfo_t *ksi)
int ret = 0;
int wakeup_swapper;
+ MPASS(td == NULL || p == td->td_proc);
PROC_LOCK_ASSERT(p, MA_OWNED);
if (!_SIG_VALID(sig))
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 21f0644..7627027 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -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, mcontext_t *ctx,
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_exit_args *uap)
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_kill_args *uap)
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_kill_args *uap)
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_kill2_args *uap)
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_wake_args *uap)
}
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_wake_args *uap)
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 thr_set_name_args *uap)
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);
}
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index e500e0a..89f6137 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -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);
+}
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 3aea2bd..a153fbc 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -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++;
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index bdae3e8..cf8c534 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -1588,20 +1588,15 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi,
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) {
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 525c0e2..af6b298 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -721,24 +721,13 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
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;
}
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index de65462..30c1aa9 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -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;
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index e05106a..69b4e0a 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -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);
}
/*
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index b16fcc9..9bce569 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -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. */
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index bd6d9da..f5abae6 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -294,6 +294,13 @@ ksiginfo_copy(ksiginfo_t *src, ksiginfo_t *dst)
(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 sig, int checkctty);
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 *queue);
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);
OpenPOWER on IntegriCloud