? bugmagnet.diff ? cont.diff ? foo ? kris-contention.diff ? out ? sched_lock ? stack-07-20.diff ? stack2.diff ? sys.diff ? sysback.diff ? threadlock.diff ? tophalf.diff ? ule.diff ? amd64/amd64/switch.diff ? amd64/amd64/trace.diff ? kern/bak ? kern/pcpu ? kern/stats ? kern/throw ? kern/tophalf.diff ? modules/md/export_syms ? modules/md/geom_md.ko ? modules/md/opt_geom.h ? modules/md/opt_md.h ? modules/md/vnode_if.h ? modules/md/vnode_if_newproto.h ? modules/md/vnode_if_typedef.h ? nfsserver/nfs.diff ? sys/stats Index: kern/kern_descrip.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.303 diff -u -r1.303 kern_descrip.c --- kern/kern_descrip.c 15 Feb 2007 10:55:43 -0000 1.303 +++ kern/kern_descrip.c 25 Feb 2007 21:28:37 -0000 @@ -1410,7 +1410,7 @@ struct filedesc0 *newfdp; newfdp = malloc(sizeof *newfdp, M_FILEDESC, M_WAITOK | M_ZERO); - mtx_init(&newfdp->fd_fd.fd_mtx, FILEDESC_LOCK_DESC, NULL, MTX_DEF); + mtx_init(&newfdp->fd_fd.fd_mtx, FILEDESC_LOCK_DESC, NULL, MTX_TOPHALF); if (fdp != NULL) { FILEDESC_LOCK(fdp); newfdp->fd_fd.fd_cdir = fdp->fd_cdir; Index: kern/kern_mutex.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/kern_mutex.c,v retrieving revision 1.179 diff -u -r1.179 kern_mutex.c --- kern/kern_mutex.c 16 Dec 2006 02:37:57 -0000 1.179 +++ kern/kern_mutex.c 25 Feb 2007 21:28:37 -0000 @@ -109,6 +109,10 @@ db_show_mtx #endif }; +struct lock_class lock_class_mtx_tophalf = { + "tophalf mutex", + LC_SLEEPLOCK | LC_RECURSABLE | LC_SLEEPABLE +}; /* * System-wide mutexes @@ -142,9 +146,12 @@ MPASS(curthread != NULL); KASSERT(m->mtx_lock != MTX_DESTROYED, ("mtx_lock() of destroyed mutex @ %s:%d", file, line)); - KASSERT(LOCK_CLASS(&m->mtx_object) == &lock_class_mtx_sleep, + KASSERT(LOCK_CLASS(&m->mtx_object) != &lock_class_mtx_spin, ("mtx_lock() of spin mutex %s @ %s:%d", m->mtx_object.lo_name, file, line)); + KASSERT(LOCK_CLASS(&m->mtx_object) != &lock_class_mtx_tophalf || + curthread->td_intr_nesting_level == 0, + ("_mtx_lock_flags: acquiring tophalf lock from interrupt context")); WITNESS_CHECKORDER(&m->mtx_object, opts | LOP_NEWORDER | LOP_EXCLUSIVE, file, line); @@ -164,7 +171,7 @@ MPASS(curthread != NULL); KASSERT(m->mtx_lock != MTX_DESTROYED, ("mtx_unlock() of destroyed mutex @ %s:%d", file, line)); - KASSERT(LOCK_CLASS(&m->mtx_object) == &lock_class_mtx_sleep, + KASSERT(LOCK_CLASS(&m->mtx_object) != &lock_class_mtx_spin, ("mtx_unlock() of spin mutex %s @ %s:%d", m->mtx_object.lo_name, file, line)); curthread->td_locks--; @@ -231,7 +238,7 @@ MPASS(curthread != NULL); KASSERT(m->mtx_lock != MTX_DESTROYED, ("mtx_trylock() of destroyed mutex @ %s:%d", file, line)); - KASSERT(LOCK_CLASS(&m->mtx_object) == &lock_class_mtx_sleep, + KASSERT(LOCK_CLASS(&m->mtx_object) != &lock_class_mtx_spin, ("mtx_trylock() of spin mutex %s @ %s:%d", m->mtx_object.lo_name, file, line)); @@ -641,7 +648,7 @@ struct lock_class *class; int flags; - MPASS((opts & ~(MTX_SPIN | MTX_QUIET | MTX_RECURSE | + MPASS((opts & ~(MTX_SPIN | MTX_QUIET | MTX_RECURSE | MTX_TOPHALF | MTX_NOWITNESS | MTX_DUPOK | MTX_NOPROFILE)) == 0); #ifdef MUTEX_DEBUG @@ -652,6 +659,8 @@ /* Determine lock class and lock flags. */ if (opts & MTX_SPIN) class = &lock_class_mtx_spin; + else if (opts & MTX_TOPHALF) + class = &lock_class_mtx_tophalf; else class = &lock_class_mtx_sleep; flags = 0; @@ -665,6 +674,8 @@ flags |= LO_DUPOK; if (opts & MTX_NOPROFILE) flags |= LO_NOPROFILE; + if (opts & MTX_TOPHALF) + flags |= LO_SLEEPABLE; /* Initialize mutex. */ m->mtx_lock = MTX_UNOWNED; Index: kern/subr_lock.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/subr_lock.c,v retrieving revision 1.12 diff -u -r1.12 subr_lock.c --- kern/subr_lock.c 4 Dec 2006 22:15:50 -0000 1.12 +++ kern/subr_lock.c 25 Feb 2007 21:28:37 -0000 @@ -56,6 +56,7 @@ struct lock_class *lock_classes[LOCK_CLASS_MAX + 1] = { &lock_class_mtx_spin, &lock_class_mtx_sleep, + &lock_class_mtx_tophalf, &lock_class_sx, &lock_class_rw, &lock_class_lockmgr, Index: kern/subr_turnstile.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/subr_turnstile.c,v retrieving revision 1.166 diff -u -r1.166 subr_turnstile.c --- kern/subr_turnstile.c 23 Jan 2007 08:46:50 -0000 1.166 +++ kern/subr_turnstile.c 25 Feb 2007 21:28:37 -0000 @@ -121,6 +121,7 @@ LIST_ENTRY(turnstile) ts_link; /* (q) Contested locks. */ LIST_HEAD(, turnstile) ts_free; /* (c) Free turnstiles. */ struct lock_object *ts_lockobj; /* (c) Lock we reference. */ + int ts_flags; /* (c) flags from lockobj. */ struct thread *ts_owner; /* (c + q) Who owns the lock. */ }; @@ -189,20 +190,17 @@ MPASS(td->td_proc->p_magic == P_MAGIC); /* - * If the thread is asleep, then we are probably about - * to deadlock. To make debugging this easier, just - * panic and tell the user which thread misbehaved so - * they can hopefully get a stack trace from the truly - * misbehaving thread. + * If the owning thread is asleep with a non-sleepable lock + * we are probably about to deadlock. */ - if (TD_IS_SLEEPING(td)) { - printf( - "Sleeping thread (tid %d, pid %d) owns a non-sleepable lock\n", - td->td_tid, td->td_proc->p_pid); + if (!((ts->ts_flags & LC_SLEEPABLE) || !TD_IS_SLEEPING(td))) { #ifdef DDB db_trace_thread(td, -1); #endif - panic("sleeping thread"); + panic("sleeping thread owns a non-sleepable lock " + "(%s:'%s')", + ts->ts_lockobj->lo_type, ts->ts_lockobj->lo_name); + } /* @@ -233,14 +231,17 @@ */ KASSERT(td != curthread, ("Deadlock detected")); #endif - /* - * If we aren't blocked on a lock, we should be. + * If we aren't sleepable we must be blocked on a lock. */ - KASSERT(TD_ON_LOCK(td), ( - "thread %d(%s):%d holds %s but isn't blocked on a lock\n", - td->td_tid, td->td_proc->p_comm, td->td_state, - ts->ts_lockobj->lo_name)); + if (!TD_ON_LOCK(td)) { + if (ts->ts_flags & LC_SLEEPABLE) + return; + panic("thread %d(%s):%d holds %s but isn't" + " blocked on a lock\n", + td->td_tid, td->td_proc->p_comm, td->td_state, + ts->ts_lockobj->lo_name); + } /* * Pick up the lock that td is blocked on. @@ -623,6 +624,7 @@ ("thread's turnstile has a non-empty free list")); KASSERT(ts->ts_lockobj == NULL, ("stale ts_lockobj pointer")); ts->ts_lockobj = lock; + ts->ts_flags = LOCK_CLASS(lock)->lc_flags; mtx_lock_spin(&td_contested_lock); TAILQ_INSERT_TAIL(&ts->ts_blocked[queue], td, td_lockq); turnstile_setowner(ts, owner); @@ -686,13 +688,19 @@ CTR4(KTR_LOCK, "%s: td %d blocked on [%p] %s", __func__, td->td_tid, lock, lock->lo_name); - mi_switch(SW_VOL, NULL); - + if (ts->ts_flags & LC_SLEEPABLE) { + DROP_GIANT(); + mi_switch(SW_VOL, NULL); + mtx_unlock_spin(&sched_lock); + PICKUP_GIANT(); + } else { + mi_switch(SW_VOL, NULL); + mtx_unlock_spin(&sched_lock); + } if (LOCK_LOG_TEST(lock, 0)) CTR4(KTR_LOCK, "%s: td %d free from blocked on [%p] %s", __func__, td->td_tid, lock, lock->lo_name); - mtx_unlock_spin(&sched_lock); } /* Index: kern/subr_witness.c =================================================================== RCS file: /usr/home/ncvs/src/sys/kern/subr_witness.c,v retrieving revision 1.225 diff -u -r1.225 subr_witness.c --- kern/subr_witness.c 20 Feb 2007 23:49:30 -0000 1.225 +++ kern/subr_witness.c 25 Feb 2007 21:28:38 -0000 @@ -281,7 +281,6 @@ * Various mutexes */ { "Giant", &lock_class_mtx_sleep }, - { "filedesc structure", &lock_class_mtx_sleep }, { "pipe mutex", &lock_class_mtx_sleep }, { "sigio lock", &lock_class_mtx_sleep }, { "process group", &lock_class_mtx_sleep }, @@ -294,7 +293,7 @@ /* * Sockets */ - { "filedesc structure", &lock_class_mtx_sleep }, + { "filedesc structure", &lock_class_mtx_tophalf }, { "accept", &lock_class_mtx_sleep }, { "so_snd", &lock_class_mtx_sleep }, { "so_rcv", &lock_class_mtx_sleep }, Index: sys/filedesc.h =================================================================== RCS file: /usr/home/ncvs/src/sys/sys/filedesc.h,v retrieving revision 1.75 diff -u -r1.75 filedesc.h --- sys/filedesc.h 7 Apr 2006 05:16:02 -0000 1.75 +++ sys/filedesc.h 25 Feb 2007 21:28:42 -0000 @@ -62,8 +62,6 @@ u_short fd_holdcnt; /* hold count on structure + mutex */ struct mtx fd_mtx; /* protects members of this struct */ - int fd_locked; /* long lock flag */ - int fd_wanted; /* "" */ struct kqlist fd_kqlist; /* list of kqueues on this filedesc */ int fd_holdleaderscount; /* block fdfree() for shared close() */ int fd_holdleaderswakeup; /* fdfree() needs wakeup */ @@ -96,60 +94,11 @@ #ifdef _KERNEL /* Lock a file descriptor table. */ -#define FILEDESC_LOCK(fd) \ - do { \ - mtx_lock(&(fd)->fd_mtx); \ - (fd)->fd_wanted++; \ - while ((fd)->fd_locked) \ - msleep(&(fd)->fd_locked, &(fd)->fd_mtx, PLOCK, "fdesc", 0); \ - (fd)->fd_locked = 2; \ - (fd)->fd_wanted--; \ - mtx_unlock(&(fd)->fd_mtx); \ - } while (0) - -#define FILEDESC_UNLOCK(fd) \ - do { \ - mtx_lock(&(fd)->fd_mtx); \ - KASSERT((fd)->fd_locked == 2, \ - ("fdesc locking mistake %d should be %d", (fd)->fd_locked, 2)); \ - (fd)->fd_locked = 0; \ - if ((fd)->fd_wanted) \ - wakeup(&(fd)->fd_locked); \ - mtx_unlock(&(fd)->fd_mtx); \ - } while (0) - -#define FILEDESC_LOCK_FAST(fd) \ - do { \ - mtx_lock(&(fd)->fd_mtx); \ - (fd)->fd_wanted++; \ - while ((fd)->fd_locked) \ - msleep(&(fd)->fd_locked, &(fd)->fd_mtx, PLOCK, "fdesc", 0); \ - (fd)->fd_locked = 1; \ - (fd)->fd_wanted--; \ - } while (0) - -#define FILEDESC_UNLOCK_FAST(fd) \ - do { \ - KASSERT((fd)->fd_locked == 1, \ - ("fdesc locking mistake %d should be %d", (fd)->fd_locked, 1)); \ - (fd)->fd_locked = 0; \ - if ((fd)->fd_wanted) \ - wakeup(&(fd)->fd_locked); \ - mtx_unlock(&(fd)->fd_mtx); \ - } while (0) - -#ifdef INVARIANT_SUPPORT -#define FILEDESC_LOCK_ASSERT(fd, arg) \ - do { \ - if ((arg) == MA_OWNED) \ - KASSERT((fd)->fd_locked != 0, ("fdesc locking mistake")); \ - else \ - KASSERT((fd)->fd_locked == 0, ("fdesc locking mistake")); \ - } while (0) -#else -#define FILEDESC_LOCK_ASSERT(fd, arg) -#endif - +#define FILEDESC_LOCK(fd) mtx_lock(&(fd)->fd_mtx) +#define FILEDESC_UNLOCK(fd) mtx_unlock(&(fd)->fd_mtx) +#define FILEDESC_LOCK_FAST(fd) mtx_lock(&(fd)->fd_mtx) +#define FILEDESC_UNLOCK_FAST(fd) mtx_unlock(&(fd)->fd_mtx) +#define FILEDESC_LOCK_ASSERT(fd, arg) mtx_assert(&(fd)->fd_mtx, (arg)) #define FILEDESC_LOCK_DESC "filedesc structure" struct thread; Index: sys/lock.h =================================================================== RCS file: /usr/home/ncvs/src/sys/sys/lock.h,v retrieving revision 1.63 diff -u -r1.63 lock.h --- sys/lock.h 3 Feb 2007 07:49:20 -0000 1.63 +++ sys/lock.h 25 Feb 2007 21:28:42 -0000 @@ -211,6 +211,7 @@ extern struct lock_class lock_class_mtx_sleep; extern struct lock_class lock_class_mtx_spin; +extern struct lock_class lock_class_mtx_tophalf; extern struct lock_class lock_class_sx; extern struct lock_class lock_class_rw; extern struct lock_class lock_class_lockmgr; Index: sys/mutex.h =================================================================== RCS file: /usr/home/ncvs/src/sys/sys/mutex.h,v retrieving revision 1.87 diff -u -r1.87 mutex.h --- sys/mutex.h 21 Dec 2006 22:42:18 -0000 1.87 +++ sys/mutex.h 25 Feb 2007 21:28:42 -0000 @@ -58,6 +58,7 @@ #define MTX_RECURSE 0x00000004 /* Option: lock allowed to recurse */ #define MTX_NOWITNESS 0x00000008 /* Don't do any witness checking. */ #define MTX_NOPROFILE 0x00000020 /* Don't profile this lock */ +#define MTX_TOPHALF 0x00000040 /* tophalf mutex */ /* * Option flags passed to certain lock/unlock routines, through the use