svn commit: r213642 - in head/sys: kern sys

Robert Watson rwatson at FreeBSD.org
Sat Oct 9 12:00:40 UTC 2010


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


More information about the svn-src-all mailing list