diff options
author | jhb <jhb@FreeBSD.org> | 2007-06-13 20:01:42 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2007-06-13 20:01:42 +0000 |
commit | af94eb296cebbc50bb4aad466b0c66c9e0149ead (patch) | |
tree | 04c4626ae55b88c5f4812648c9e15bb1ef22b6fc | |
parent | 1c98f58fd259212d95e6e56051d12f66eddeb9e0 (diff) | |
download | FreeBSD-src-af94eb296cebbc50bb4aad466b0c66c9e0149ead.zip FreeBSD-src-af94eb296cebbc50bb4aad466b0c66c9e0149ead.tar.gz |
Improve the ktrace locking somewhat to reduce overhead:
- Depessimize userret() in kernels where KTRACE is enabled by doing an
unlocked check of the per-process queue of pending events before
acquiring any locks. Previously ktr_userret() unconditionally acquired
the global ktrace_sx lock on every return to userland for every thread,
even if ktrace wasn't enabled for the thread.
- Optimize the locking in exit() to first perform an unlocked read of
p_traceflag to see if ktrace is enabled and only acquire locks and
teardown ktrace if the test succeeds. Also, explicitly disable tracing
before draining any pending events so the pending events actually get
written out. The unlocked read is safe because proc lock is acquired
earlier after single-threading so p_traceflag can't change between then
and this check (well, it can currently due to a bug in ktrace I will fix
next, but that race existed prior to this change as well).
Reviewed by: rwatson
-rw-r--r-- | sys/kern/kern_exit.c | 42 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 2 |
2 files changed, 26 insertions, 18 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 7700a8f..696a101 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -356,26 +356,32 @@ retry: mtx_unlock(&Giant); #ifdef KTRACE /* - * Drain any pending records on the thread and release the trace - * file. It might be better if drain-and-clear were atomic. + * Disable tracing, then drain any pending records and release + * the trace file. */ - ktrprocexit(td); - PROC_LOCK(p); - mtx_lock(&ktrace_mtx); - p->p_traceflag = 0; /* don't trace the vrele() */ - tracevp = p->p_tracevp; - p->p_tracevp = NULL; - tracecred = p->p_tracecred; - p->p_tracecred = NULL; - mtx_unlock(&ktrace_mtx); - PROC_UNLOCK(p); - if (tracevp != NULL) { - locked = VFS_LOCK_GIANT(tracevp->v_mount); - vrele(tracevp); - VFS_UNLOCK_GIANT(locked); + if (p->p_traceflag != 0) { + PROC_LOCK(p); + mtx_lock(&ktrace_mtx); + p->p_traceflag = 0; + mtx_unlock(&ktrace_mtx); + PROC_UNLOCK(p); + ktrprocexit(td); + PROC_LOCK(p); + mtx_lock(&ktrace_mtx); + tracevp = p->p_tracevp; + p->p_tracevp = NULL; + tracecred = p->p_tracecred; + p->p_tracecred = NULL; + mtx_unlock(&ktrace_mtx); + PROC_UNLOCK(p); + if (tracevp != NULL) { + locked = VFS_LOCK_GIANT(tracevp->v_mount); + vrele(tracevp); + VFS_UNLOCK_GIANT(locked); + } + if (tracecred != NULL) + crfree(tracecred); } - if (tracecred != NULL) - crfree(tracecred); #endif /* * Release reference to text vnode diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 2b7ee33..0ca4a30 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -444,6 +444,8 @@ void ktruserret(struct thread *td) { + if (STAILQ_EMPTY(&td->td_proc->p_ktr)) + return; ktrace_enter(td); sx_xlock(&ktrace_sx); ktr_drain(td); |