Index: i386/i386/trap.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/i386/i386/trap.c,v retrieving revision 1.303 diff -u -p -r1.303 trap.c --- i386/i386/trap.c 27 May 2007 19:16:44 -0000 1.303 +++ i386/i386/trap.c 3 Jun 2007 17:57:39 -0000 @@ -1064,10 +1064,18 @@ syscall(struct trapframe *frame) KASSERT(td->td_critnest == 0, ("System call %s returning in a critical section", (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); - KASSERT(td->td_locks == 0, + if (td->td_nlocks != 0) { + printf("Thread %p (system call %s) returning with %d locks held", + td, (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_nlocks); + kdb_enter("xxx"); + } +#if 0 + KASSERT(td->td_nlocks == 0, ("System call %s returning with %d locks held", (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", - td->td_locks)); + td->td_nlocks)); +#endif /* * Handle reschedule and other end-of-syscall issues Index: kern/kern_lock.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/kern_lock.c,v retrieving revision 1.110 diff -u -p -r1.110 kern_lock.c --- kern/kern_lock.c 18 May 2007 15:04:59 -0000 1.110 +++ kern/kern_lock.c 22 May 2007 22:41:31 -0000 @@ -96,7 +96,7 @@ unlock_lockmgr(struct lock_object *lock) panic("lockmgr locks do not support sleep interlocking"); } -#define COUNT(td, x) if ((td)) (td)->td_locks += (x) +#define COUNT(td, x) if ((td)) (td)->td_nlocks += (x) #define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \ LK_SHARE_NONZERO | LK_WAIT_NONZERO) Index: kern/kern_mutex.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/kern_mutex.c,v retrieving revision 1.190 diff -u -p -r1.190 kern_mutex.c --- kern/kern_mutex.c 18 May 2007 15:04:59 -0000 1.190 +++ kern/kern_mutex.c 22 May 2007 22:41:32 -0000 @@ -197,7 +197,7 @@ _mtx_lock_flags(struct mtx *m, int opts, LOCK_LOG_LOCK("LOCK", &m->lock_object, opts, m->mtx_recurse, file, line); WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line); - curthread->td_locks++; + td_add_lock(m); } void @@ -209,7 +209,7 @@ _mtx_unlock_flags(struct mtx *m, int opt KASSERT(LOCK_CLASS(&m->lock_object) == &lock_class_mtx_sleep, ("mtx_unlock() of spin mutex %s @ %s:%d", m->lock_object.lo_name, file, line)); - curthread->td_locks--; + td_del_lock(m); WITNESS_UNLOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line); LOCK_LOG_LOCK("UNLOCK", &m->lock_object, opts, m->mtx_recurse, file, line); @@ -285,7 +285,7 @@ _mtx_trylock(struct mtx *m, int opts, co if (rval) { WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE | LOP_TRYLOCK, file, line); - curthread->td_locks++; + td_add_lock(m); if (m->mtx_recurse == 0) lock_profile_obtain_lock_success(&m->lock_object, contested, waittime, file, line); @@ -733,7 +733,7 @@ mtx_destroy(struct mtx *m) if (LOCK_CLASS(&m->lock_object) == &lock_class_mtx_spin) spinlock_exit(); else - curthread->td_locks--; + td_del_lock(m); /* Tell witness this isn't locked to make it happy. */ WITNESS_UNLOCK(&m->lock_object, LOP_EXCLUSIVE, __FILE__, Index: kern/kern_rwlock.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/kern_rwlock.c,v retrieving revision 1.25 diff -u -p -r1.25 kern_rwlock.c --- kern/kern_rwlock.c 18 May 2007 15:04:59 -0000 1.25 +++ kern/kern_rwlock.c 22 May 2007 22:41:32 -0000 @@ -166,7 +166,7 @@ _rw_wlock(struct rwlock *rw, const char __rw_wlock(rw, curthread, file, line); LOCK_LOG_LOCK("WLOCK", &rw->lock_object, 0, 0, file, line); WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line); - curthread->td_locks++; + td_add_lock(rw); } void @@ -177,7 +177,7 @@ _rw_wunlock(struct rwlock *rw, const cha KASSERT(rw->rw_lock != RW_DESTROYED, ("rw_wunlock() of destroyed rwlock @ %s:%d", file, line)); _rw_assert(rw, RA_WLOCKED, file, line); - curthread->td_locks--; + td_del_lock(rw); WITNESS_UNLOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line); LOCK_LOG_LOCK("WUNLOCK", &rw->lock_object, 0, 0, file, line); lock_profile_release_lock(&rw->lock_object); @@ -328,7 +328,7 @@ _rw_rlock(struct rwlock *rw, const char LOCK_LOG_LOCK("RLOCK", &rw->lock_object, 0, 0, file, line); WITNESS_LOCK(&rw->lock_object, 0, file, line); - curthread->td_locks++; + td_add_lock(rw); } void @@ -340,7 +340,7 @@ _rw_runlock(struct rwlock *rw, const cha KASSERT(rw->rw_lock != RW_DESTROYED, ("rw_runlock() of destroyed rwlock @ %s:%d", file, line)); _rw_assert(rw, RA_RLOCKED, file, line); - curthread->td_locks--; + td_del_lock(rw); WITNESS_UNLOCK(&rw->lock_object, 0, file, line); LOCK_LOG_LOCK("RUNLOCK", &rw->lock_object, 0, 0, file, line); Index: kern/kern_sx.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/kern_sx.c,v retrieving revision 1.53 diff -u -p -r1.53 kern_sx.c --- kern/kern_sx.c 31 May 2007 09:14:47 -0000 1.53 +++ kern/kern_sx.c 3 Jun 2007 17:52:53 -0000 @@ -203,7 +203,7 @@ _sx_slock(struct sx *sx, int opts, const if (!error) { LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line); WITNESS_LOCK(&sx->lock_object, 0, file, line); - curthread->td_locks++; + td_add_lock(sx); } return (error); @@ -221,7 +221,7 @@ _sx_try_slock(struct sx *sx, const char x + SX_ONE_SHARER)) { LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line); WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line); - curthread->td_locks++; + td_add_lock(sx); return (1); } @@ -244,7 +244,7 @@ _sx_xlock(struct sx *sx, int opts, const LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse, file, line); WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line); - curthread->td_locks++; + td_add_lock(sx); } return (error); @@ -270,7 +270,7 @@ _sx_try_xlock(struct sx *sx, const char if (rval) { WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK, file, line); - curthread->td_locks++; + td_add_lock(sx); } return (rval); @@ -284,7 +284,7 @@ _sx_sunlock(struct sx *sx, const char *f KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, ("sx_sunlock() of destroyed sx @ %s:%d", file, line)); _sx_assert(sx, SA_SLOCKED, file, line); - curthread->td_locks--; + td_del_lock(sx); WITNESS_UNLOCK(&sx->lock_object, 0, file, line); LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line); if (SX_SHARERS(sx->sx_lock) == 1) @@ -300,7 +300,7 @@ _sx_xunlock(struct sx *sx, const char *f KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, ("sx_xunlock() of destroyed sx @ %s:%d", file, line)); _sx_assert(sx, SA_XLOCKED, file, line); - curthread->td_locks--; + td_del_lock(sx); WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line); LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file, line); Index: kern/subr_trap.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/subr_trap.c,v retrieving revision 1.295 diff -u -p -r1.295 subr_trap.c --- kern/subr_trap.c 1 Jun 2007 01:20:11 -0000 1.295 +++ kern/subr_trap.c 3 Jun 2007 17:56:19 -0000 @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD: src/sys/kern/subr_tr #include #include #include +#include #ifdef KTRACE #include #include @@ -133,8 +134,14 @@ userret(struct thread *td, struct trapfr * Let the scheduler adjust our priority etc. */ sched_userret(td); - KASSERT(td->td_locks == 0, - ("userret: Returning with %d locks held.", td->td_locks)); + if (td->td_nlocks != 0) { + printf("Thread %p returning with %d locks held", td, td->td_nlocks); + kdb_enter("xxx"); + } +#if 0 + KASSERT(td->td_nlocks == 0, + ("userret: Returning with %d locks held.", td->td_nlocks)); +#endif } /* Index: kern/subr_turnstile.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/subr_turnstile.c,v retrieving revision 1.167 diff -u -p -r1.167 subr_turnstile.c --- kern/subr_turnstile.c 18 May 2007 06:32:24 -0000 1.167 +++ kern/subr_turnstile.c 22 May 2007 22:41:32 -0000 @@ -1285,4 +1285,23 @@ DB_SHOW_COMMAND(locktree, db_show_locktr } else print_waiters(ts, 0); } + +DB_SHOW_COMMAND(tdlocks, db_show_tdlocks) +{ + struct lock_object *lock; + struct lock_class *class; + struct thread *td; + int n; + + if (!have_addr) + return; + td = (struct thread *)addr; + for (n = 0; n < 16; n++) { + lock = td->td_locks[n]; + if (lock == NULL) + continue; + class = LOCK_CLASS(lock); + db_printf("lock %p (%s) \"%s\"\n", lock, class->lc_name, lock->lo_name); + } +} #endif Index: sys/buf.h =================================================================== RCS file: /zoo/pjd/repo/src/sys/sys/buf.h,v retrieving revision 1.196 diff -u -p -r1.196 buf.h --- sys/buf.h 8 Mar 2007 06:44:34 -0000 1.196 +++ sys/buf.h 3 Jun 2007 12:01:02 -0000 @@ -343,7 +343,7 @@ BUF_KERNPROC(struct buf *bp) struct thread *td = curthread; if (!TD_IS_IDLETHREAD(td) && bp->b_lock.lk_lockholder == td) - td->td_locks--; + td_del_lock(&bp->b_lock); bp->b_lock.lk_lockholder = LK_KERNPROC; } #endif Index: sys/proc.h =================================================================== RCS file: /zoo/pjd/repo/src/sys/sys/proc.h,v retrieving revision 1.478 diff -u -p -r1.478 proc.h --- sys/proc.h 1 Jun 2007 01:12:45 -0000 1.478 +++ sys/proc.h 3 Jun 2007 17:34:34 -0000 @@ -242,7 +242,7 @@ struct thread { u_char td_lastcpu; /* (j) Last cpu we were on. */ u_char td_oncpu; /* (j) Which cpu we are on. */ volatile u_char td_owepreempt; /* (k*) Preempt on last critical_exit */ - short td_locks; /* (k) Count of non-spin locks. */ + short td_nlocks; /* (k) Count of non-spin locks. */ u_char td_tsqueue; /* (j) Turnstile queue blocked on. */ struct turnstile *td_blocked; /* (j) Lock thread is blocked on. */ const char *td_lockname; /* (j) Name of lock blocked on. */ @@ -274,6 +274,7 @@ struct thread { u_long td_profil_addr; /* (k) Temporary addr until AST. */ u_int td_profil_ticks; /* (k) Temporary ticks until AST. */ char td_name[MAXCOMLEN + 1]; /* (*) Thread name. */ + void *td_locks[16]; #define td_endzero td_base_pri /* Copied during fork1() or thread_sched_upcall(). */ @@ -919,6 +920,41 @@ void upcall_unlink(struct kse_upcall *ku void upcall_remove(struct thread *td); void upcall_stash(struct kse_upcall *ke); +#ifdef INVARIANTS +static __inline void +td_add_lock(void *lock) +{ + struct thread *td = curthread; + int n; + + for (n = 0; n < sizeof(td->td_locks) / sizeof(td->td_locks[0]); n++) { + if (td->td_locks[n] == NULL) { + td->td_locks[n] = lock; + break; + } + } + td->td_nlocks++; +} + +static __inline void +td_del_lock(void *lock) +{ + struct thread *td = curthread; + int n; + + for (n = 0; n < sizeof(td->td_locks) / sizeof(td->td_locks[0]); n++) { + if (td->td_locks[n] == lock) { + td->td_locks[n] = NULL; + break; + } + } + td->td_nlocks--; +} +#else +#define td_add_lock(lock) +#define td_del_lock(lock) +#endif + #endif /* _KERNEL */ #endif /* !_SYS_PROC_H_ */