From 55194e796cd9e8eb27d9bb4ec9f07184e390d01a Mon Sep 17 00:00:00 2001 From: davidxu Date: Sat, 9 Oct 2010 02:50:23 +0000 Subject: 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 --- sys/kern/kern_thr.c | 127 +++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 66 deletions(-) (limited to 'sys/kern/kern_thr.c') 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 #include #include +#include #include #include #include @@ -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); } -- cgit v1.1