summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_thr.c
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/kern/kern_thr.c
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/kern/kern_thr.c')
-rw-r--r--sys/kern/kern_thr.c127
1 files changed, 61 insertions, 66 deletions
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);
}
OpenPOWER on IntegriCloud