diff options
author | Julian Elischer <julian@FreeBSD.org> | 2002-02-22 23:58:22 +0000 |
---|---|---|
committer | Julian Elischer <julian@FreeBSD.org> | 2002-02-22 23:58:22 +0000 |
commit | 77c406642402ab19132b0c2f8c96d4f7766cc03f (patch) | |
tree | 7d75b1e48c3b7ef34eb52967d22fcf93f2addadc /sys/kern/subr_trap.c | |
parent | a3dbc1d8045cfd2c057ba0803bfb778217000e5d (diff) | |
download | src-77c406642402ab19132b0c2f8c96d4f7766cc03f.tar.gz src-77c406642402ab19132b0c2f8c96d4f7766cc03f.zip |
Add some DIAGNOSTIC code.
While in userland, keep the thread's ucred reference in a shadow
field so that the usual place to store it is NULL.
If DIAGNOSTIC is not set, the thread ucred is kept valid until the next
kernel entry, at which time it is checked against the process cred
and possibly corrected. Produces a BIG speedup in
kernels with INVARIANTS set. (A previous commit corrected it
for the non INVARIANTS case already)
Reviewed by: dillon@freebsd.org
Notes
Notes:
svn path=/head/; revision=91090
Diffstat (limited to 'sys/kern/subr_trap.c')
-rw-r--r-- | sys/kern/subr_trap.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index d599b91bfa23..cefce4ef9a10 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -131,7 +131,6 @@ ast(framep) #endif KASSERT(TRAPF_USERMODE(framep), ("ast in kernel mode")); - KASSERT(td->td_ucred == NULL, ("leaked ucred")); #ifdef WITNESS if (witness_list(td)) panic("Returning to user mode with mutex(s) held"); @@ -161,6 +160,30 @@ ast(framep) p->p_stats->p_prof.pr_ticks = 0; } mtx_unlock_spin(&sched_lock); + +#ifdef DIAGNOSTIC + /* + * As a diagnostic tool we make sure that td->td_ucred + * is NULL while we are in user space. This is + * because theoreticaly this field is only defined + * while the thread is in the kernel. Making it NULL + * will immediatly trap invalid usage of this field. + * In practice however we keep the reference to the ucred + * because it's almost always going to be the same cred we will + * need at the next syscall, and it can be expensive + * to keep dropping and reacquiring the reference. + * We thus stash it away elsewhere until we return + * to the kernel, where we bring it back. If + * DIAGNOSTIC is not defined we don't bother with + * making it NULL, and just leave it in place. + * (don't remove this comment without removing the pointers + * to it in sys/proc.h, */*/trap.c, kern/kern_fork.c and here.) + */ + if (td->td_ucred) + panic("ast:thread got a cred before reaching AST"); + td->td_ucred = td->td_ucred_cache; + td->td_ucred_cache = NULL; +#endif /* DIAGNOSTIC */ if (td->td_ucred != p->p_ucred) cred_update_thread(td); if (flags & KEF_OWEUPC && sflag & PS_PROFIL) @@ -187,12 +210,13 @@ ast(framep) } userret(td, framep, sticks); -#ifdef INVARIANTS - mtx_lock(&Giant); - crfree(td->td_ucred); - mtx_unlock(&Giant); +#ifdef DIAGNOSTIC /* see comment above */ + if (td->td_ucred_cache) + panic("ast:thread already has cached ucred"); + td->td_ucred_cache = td->td_ucred; td->td_ucred = NULL; -#endif +#endif /* DIAGNOSTIC */ + s = cpu_critical_enter(); } mtx_assert(&Giant, MA_NOTOWNED); |