Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Nov 2007 20:47:53 +0100
From:      Kris Kennaway <kris@FreeBSD.org>
To:        Kris Kennaway <kris@FreeBSD.org>
Cc:        Attilio Rao <attilio@freebsd.org>, freebsd-stable@freebsd.org, Alexey Popov <lol@chistydom.ru>
Subject:   Re: 2 x quad-core system is slower that 2 x dual core on FreeBSD
Message-ID:  <474339E9.4080301@FreeBSD.org>
In-Reply-To: <47432F77.3030606@FreeBSD.org>
References:  <4741905E.8050300@chistydom.ru>	<fhs3s5$knj$1@ger.gmane.org>	<47419AB3.5030008@chistydom.ru>	<fhs7hp$2es$2@ger.gmane.org> <4741A7DA.2050706@chistydom.ru> <4741DA15.9000308@FreeBSD.org> <47429DB8.7040504@chistydom.ru> <4742ADFE.40902@FreeBSD.org> <4742C46A.1060701@chistydom.ru> <47432F77.3030606@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------030803050501020800060905
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Kris Kennaway wrote:
> In the meantime there is unfortunately not a lot that can be done, 
> AFAICT.  There is one hack that I will send you later but it is not 
> likely to help much.  I will also think about how to track down the 
> cause of the contention further (the profiling trace only shows that it 
> comes mostly from vget/vput but doesn't show where these are called from).

Actually this patch might help.  It doesn't replace lockmgr but it does 
fix a silly thundering herd behaviour.  It probably needs some 
adjustment to get it to apply cleanly (it is about 7 months old), and I 
apparently stopped using it because I ran into deadlocks.  It might be 
stable enough to at least see how much it helps.

Set the vfs.lookup_shared=1 sysctl to enable the other half of the patch.

Kris


--------------030803050501020800060905
Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0";
	name="lockmgr.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="lockmgr.diff"

Change 117289 by kris@kris_xor on 2007/04/03 18:43:03

	Rewrite of lockmgr to avoid the silly multiple wakeups.  On a
	microbenchmark designed for high lockmgr contention (80 processes
	doing 1000 stat() calls of the same file on an 8-core amd64), this
	reduces system time by 95% and real time by 82%.
	
	This was ported from 6.x so support for LOCK_PROFILING is currently
	removed.
	
	Also add a hack to fake up shared lookups on UFS: acquire the lock
	in shared mode and then upgrade it to exclusive mode.  This has
	a small benefit on my tests, and it is claimed there is a very
	large benefit in some workloads.
	
	Submitted by:	ups

Affected files ...

... //depot/user/kris/contention/sys/conf/options#10 edit
... //depot/user/kris/contention/sys/kern/kern_lock.c#7 edit
... //depot/user/kris/contention/sys/kern/subr_lock.c#6 edit
... //depot/user/kris/contention/sys/kern/vfs_default.c#4 edit
... //depot/user/kris/contention/sys/sys/lockmgr.h#5 edit
... //depot/user/kris/contention/sys/ufs/ffs/ffs_vfsops.c#6 edit
... //depot/user/kris/contention/sys/ufs/ffs/ffs_vnops.c#6 edit
... //depot/user/kris/contention/sys/ufs/ufs/ufs_lookup.c#4 edit

Differences ...

==== //depot/user/kris/contention/sys/conf/options#10 (text+ko) ====

@@ -248,6 +248,9 @@
 # Enable gjournal-based UFS journal.
 UFS_GJOURNAL	opt_ufs.h
 
+# Disable shared lookups for UFS
+NO_UFS_LOOKUP_SHARED	opt_ufs.h	
+
 # The below sentence is not in English, and neither is this one.
 # We plan to remove the static dependences above, with a
 # <filesystem>_ROOT option to control if it usable as root.  This list

==== //depot/user/kris/contention/sys/kern/kern_lock.c#7 (text+ko) ====

@@ -41,10 +41,9 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_lock.c,v 1.109 2007/03/30 18:07:24 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_lock.c,v 1.89.2.5 2006/10/09 20:04:45 tegge Exp $");
 
 #include "opt_ddb.h"
-#include "opt_global.h"
 
 #include <sys/param.h>
 #include <sys/kdb.h>
@@ -55,52 +54,21 @@
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
-#include <sys/lock_profile.h>
 #ifdef DEBUG_LOCKS
 #include <sys/stack.h>
 #endif
 
 #ifdef DDB
 #include <ddb/ddb.h>
-static void	db_show_lockmgr(struct lock_object *lock);
-#endif
-static void	lock_lockmgr(struct lock_object *lock, int how);
-static int	unlock_lockmgr(struct lock_object *lock);
-
-struct lock_class lock_class_lockmgr = {
-	.lc_name = "lockmgr",
-	.lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
-#ifdef DDB
-	.lc_ddb_show = db_show_lockmgr,
 #endif
-	.lc_lock = lock_lockmgr,
-	.lc_unlock = unlock_lockmgr,
-};
 
 /*
  * Locking primitives implementation.
  * Locks provide shared/exclusive sychronization.
  */
 
-void
-lock_lockmgr(struct lock_object *lock, int how)
-{
-
-	panic("lockmgr locks do not support sleep interlocking");
-}
-
-int
-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 LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \
-	LK_SHARE_NONZERO | LK_WAIT_NONZERO)
 
-static int acquire(struct lock **lkpp, int extflags, int wanted, int *contested, uint64_t *waittime);
 static int acquiredrain(struct lock *lkp, int extflags) ;
 
 static __inline void
@@ -117,60 +85,16 @@
 
 	COUNT(td, -decr);
 	if (lkp->lk_sharecount == decr) {
-		lkp->lk_flags &= ~LK_SHARE_NONZERO;
-		if (lkp->lk_flags & (LK_WANT_UPGRADE | LK_WANT_EXCL)) {
-			wakeup(lkp);
-		}
+		if (lkp->lk_exclusivewait != 0)
+			wakeup_one(&lkp->lk_exclusivewait);
 		lkp->lk_sharecount = 0;
 	} else {
 		lkp->lk_sharecount -= decr;
+		if (lkp->lk_sharecount == 1 && lkp->lk_flags & LK_WANT_UPGRADE)
+			wakeup(&lkp->lk_flags);
 	}
 }
 
-static int
-acquire(struct lock **lkpp, int extflags, int wanted, int *contested, uint64_t *waittime)
-{
-	struct lock *lkp = *lkpp;
-	int error;
-	CTR3(KTR_LOCK,
-	    "acquire(): lkp == %p, extflags == 0x%x, wanted == 0x%x",
-	    lkp, extflags, wanted);
-
-	if ((extflags & LK_NOWAIT) && (lkp->lk_flags & wanted))
-		return EBUSY;
-	error = 0;
-	if ((lkp->lk_flags & wanted) != 0)
-		lock_profile_obtain_lock_failed(&lkp->lk_object, contested, waittime);
-	
-	while ((lkp->lk_flags & wanted) != 0) {
-		CTR2(KTR_LOCK,
-		    "acquire(): lkp == %p, lk_flags == 0x%x sleeping",
-		    lkp, lkp->lk_flags);
-		lkp->lk_flags |= LK_WAIT_NONZERO;
-		lkp->lk_waitcount++;
-		error = msleep(lkp, lkp->lk_interlock, lkp->lk_prio,
-		    lkp->lk_wmesg, 
-		    ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
-		lkp->lk_waitcount--;
-		if (lkp->lk_waitcount == 0)
-			lkp->lk_flags &= ~LK_WAIT_NONZERO;
-		if (error)
-			break;
-		if (extflags & LK_SLEEPFAIL) {
-			error = ENOLCK;
-			break;
-		}
-		if (lkp->lk_newlock != NULL) {
-			mtx_lock(lkp->lk_newlock->lk_interlock);
-			mtx_unlock(lkp->lk_interlock);
-			if (lkp->lk_waitcount == 0)
-				wakeup((void *)(&lkp->lk_newlock));
-			*lkpp = lkp = lkp->lk_newlock;
-		}
-	}
-	mtx_assert(lkp->lk_interlock, MA_OWNED);
-	return (error);
-}
 
 /*
  * Set, change, or release a lock.
@@ -180,16 +104,16 @@
  * accepted shared locks and shared-to-exclusive upgrades to go away.
  */
 int
-_lockmgr(struct lock *lkp, u_int flags, struct mtx *interlkp, 
-	 struct thread *td, char *file, int line)
-
+lockmgr(lkp, flags, interlkp, td)
+	struct lock *lkp;
+	u_int flags;
+	struct mtx *interlkp;
+	struct thread *td;
 {
 	int error;
 	struct thread *thr;
-	int extflags, lockflags;
-	int contested = 0;
-	uint64_t waitstart = 0;
-	
+	int extflags;
+
 	error = 0;
 	if (td == NULL)
 		thr = LK_KERNPROC;
@@ -217,7 +141,7 @@
 
 	if ((flags & (LK_NOWAIT|LK_RELEASE)) == 0)
 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
-		    &lkp->lk_interlock->lock_object,
+		    &lkp->lk_interlock->mtx_object,
 		    "Acquiring lockmgr lock \"%s\"", lkp->lk_wmesg);
 
 	if (panicstr != NULL) {
@@ -244,16 +168,30 @@
 		 * lock itself ).
 		 */
 		if (lkp->lk_lockholder != thr) {
-			lockflags = LK_HAVE_EXCL;
-			if (td != NULL && !(td->td_pflags & TDP_DEADLKTREAT))
-				lockflags |= LK_WANT_EXCL | LK_WANT_UPGRADE;
-			error = acquire(&lkp, extflags, lockflags, &contested, &waitstart);
-			if (error)
+			
+			while (lkp->lk_exclusivecount != 0 /*  ||
+			    (!(td->td_pflags & TDP_DEADLKTREAT) && 
+				(lkp->lk_flags & LK_WANT_UPGRADE)) */) {
+				lkp->lk_sharewait++;
+			       	error = msleep(&lkp->lk_sharewait, lkp->lk_interlock,
+				    lkp->lk_prio,lkp->lk_wmesg, 
+				    ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
+			
+				if (error)
+					break;
+				if (extflags & LK_SLEEPFAIL) {
+					error = ENOLCK;
+					break;
+				}
+
+				lkp->lk_sharewait--;
+			}
+
+			if (error != 0) {
+				shareunlock(td,lkp,0);
 				break;
+			}
 			sharelock(td, lkp, 1);
-			if (lkp->lk_sharecount == 1)
-				lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
-
 #if defined(DEBUG_LOCKS)
 			stack_save(&lkp->lk_stack);
 #endif
@@ -264,8 +202,6 @@
 		 * An alternative would be to fail with EDEADLK.
 		 */
 		sharelock(td, lkp, 1);
-		if (lkp->lk_sharecount == 1)
-			lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
 		/* FALLTHROUGH downgrade */
 
 	case LK_DOWNGRADE:
@@ -276,10 +212,9 @@
 		sharelock(td, lkp, lkp->lk_exclusivecount);
 		COUNT(td, -lkp->lk_exclusivecount);
 		lkp->lk_exclusivecount = 0;
-		lkp->lk_flags &= ~LK_HAVE_EXCL;
 		lkp->lk_lockholder = LK_NOPROC;
-		if (lkp->lk_waitcount)
-			wakeup((void *)lkp);
+		if (lkp->lk_sharewait)
+			wakeup((void *)&lkp->lk_sharewait);
 		break;
 
 	case LK_EXCLUPGRADE:
@@ -308,15 +243,13 @@
 			panic("lockmgr: upgrade exclusive lock");
 		if (lkp->lk_sharecount <= 0)
 			panic("lockmgr: upgrade without shared");
-		shareunlock(td, lkp, 1);
-		if (lkp->lk_sharecount == 0)
-			lock_profile_release_lock(&lkp->lk_object);
 		/*
 		 * If we are just polling, check to see if we will block.
 		 */
 		if ((extflags & LK_NOWAIT) &&
 		    ((lkp->lk_flags & LK_WANT_UPGRADE) ||
 		     lkp->lk_sharecount > 1)) {
+			shareunlock(td, lkp, 1);
 			error = EBUSY;
 			break;
 		}
@@ -327,34 +260,43 @@
 			 * drop to zero, then take exclusive lock.
 			 */
 			lkp->lk_flags |= LK_WANT_UPGRADE;
-			error = acquire(&lkp, extflags, LK_SHARE_NONZERO, &contested, &waitstart);
+
+			while(lkp->lk_sharecount != 1) {
+
+				error = msleep(&lkp->lk_flags, lkp->lk_interlock,
+				    lkp->lk_prio,lkp->lk_wmesg, 
+				    ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
+			
+				if (error)
+					break;
+				if (extflags & LK_SLEEPFAIL) {
+					error = ENOLCK;
+					break;
+				}
+			}
+
 			lkp->lk_flags &= ~LK_WANT_UPGRADE;
 
 			if (error) {
-			         if ((lkp->lk_flags & ( LK_WANT_EXCL | LK_WAIT_NONZERO)) == (LK_WANT_EXCL | LK_WAIT_NONZERO))
-			                   wakeup((void *)lkp);
+				shareunlock(td, lkp, 1);
+				if (lkp->lk_sharewait)
+					wakeup(&lkp->lk_sharewait);
 			         break;
 			}
+
 			if (lkp->lk_exclusivecount != 0)
 				panic("lockmgr: non-zero exclusive count");
-			lkp->lk_flags |= LK_HAVE_EXCL;
 			lkp->lk_lockholder = thr;
 			lkp->lk_exclusivecount = 1;
+			lkp->lk_sharecount = 0;	
 			COUNT(td, 1);
-			lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
 #if defined(DEBUG_LOCKS)
 			stack_save(&lkp->lk_stack);
 #endif
 			break;
 		}
-		/*
-		 * Someone else has requested upgrade. Release our shared
-		 * lock, awaken upgrade requestor if we are the last shared
-		 * lock, then request an exclusive lock.
-		 */
-		if ( (lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) ==
-			LK_WAIT_NONZERO)
-			wakeup((void *)lkp);
+
+		shareunlock(td, lkp, 1);
 		/* FALLTHROUGH exclusive request */
 
 	case LK_EXCLUSIVE:
@@ -370,38 +312,52 @@
 				break;
 			}
 		}
-		/*
-		 * If we are just polling, check to see if we will sleep.
-		 */
-		if ((extflags & LK_NOWAIT) &&
-		    (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO))) {
-			error = EBUSY;
-			break;
+
+	
+		if (lkp->lk_exclusivecount != 0 || lkp->lk_sharecount != 0) {
+
+
+			/*
+			 * If we are just polling, check to see if we will sleep.
+			 */
+			if (extflags & LK_NOWAIT) {
+				error = EBUSY;
+				break;
+			}
+
+			lkp->lk_exclusivewait++;
+
+			while(lkp->lk_exclusivecount != 0 || lkp->lk_sharecount != 0) {
+				error = msleep(&lkp->lk_exclusivewait, lkp->lk_interlock,
+				    lkp->lk_prio,lkp->lk_wmesg, 
+				    ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
+			
+				if (error)
+					break;
+				if (extflags & LK_SLEEPFAIL) {
+					error = ENOLCK;
+					break;
+				}
+
+			}
+			lkp->lk_exclusivewait--;
+		
+			if(error) {
+				if (lkp->lk_exclusivewait != 0)
+					wakeup(&lkp->lk_exclusivewait);
+				else if  (lkp->lk_sharewait != 0)
+					wakeup(&lkp->lk_sharewait);
+	
+				break;
+			}
 		}
-		/*
-		 * Try to acquire the want_exclusive flag.
-		 */
-		error = acquire(&lkp, extflags, (LK_HAVE_EXCL | LK_WANT_EXCL), &contested, &waitstart);
-		if (error)
-			break;
-		lkp->lk_flags |= LK_WANT_EXCL;
-		/*
-		 * Wait for shared locks and upgrades to finish.
-		 */
-		error = acquire(&lkp, extflags, LK_HAVE_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO, &contested, &waitstart);
-		lkp->lk_flags &= ~LK_WANT_EXCL;
-		if (error) {
-			if (lkp->lk_flags & LK_WAIT_NONZERO)		
-			         wakeup((void *)lkp);
-			break;
-		}	
-		lkp->lk_flags |= LK_HAVE_EXCL;
+
+
 		lkp->lk_lockholder = thr;
 		if (lkp->lk_exclusivecount != 0)
 			panic("lockmgr: non-zero exclusive count");
 		lkp->lk_exclusivecount = 1;
 		COUNT(td, 1);
-		lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
 #if defined(DEBUG_LOCKS)
 		stack_save(&lkp->lk_stack);
 #endif
@@ -418,23 +374,21 @@
 			if (lkp->lk_lockholder != LK_KERNPROC)
 				COUNT(td, -1);
 			if (lkp->lk_exclusivecount == 1) {
-				lkp->lk_flags &= ~LK_HAVE_EXCL;
 				lkp->lk_lockholder = LK_NOPROC;
 				lkp->lk_exclusivecount = 0;
-				lock_profile_release_lock(&lkp->lk_object);
+				if (lkp->lk_sharewait)
+					wakeup(&lkp->lk_sharewait);
+				else if (lkp->lk_exclusivewait)
+					wakeup_one(&lkp->lk_exclusivewait);
 			} else {
 				lkp->lk_exclusivecount--;
 			}
-		} else if (lkp->lk_flags & LK_SHARE_NONZERO)
+		} else if (lkp->lk_sharecount != 0)
 			shareunlock(td, lkp, 1);
-		else  {
-			printf("lockmgr: thread %p unlocking unheld lock\n",
-			    thr);
-			kdb_backtrace();
-		}
-
-		if (lkp->lk_flags & LK_WAIT_NONZERO)
-			wakeup((void *)lkp);
+		else 
+			panic("lockmgr: thread %p, not holding a lock",
+				    thr);	
+	
 		break;
 
 	case LK_DRAIN:
@@ -450,7 +404,7 @@
 		error = acquiredrain(lkp, extflags);
 		if (error)
 			break;
-		lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
+		lkp->lk_flags |= LK_DRAINING;
 		lkp->lk_lockholder = thr;
 		lkp->lk_exclusivecount = 1;
 		COUNT(td, 1);
@@ -466,8 +420,10 @@
 		/* NOTREACHED */
 	}
 	if ((lkp->lk_flags & LK_WAITDRAIN) &&
-	    (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
-		LK_SHARE_NONZERO | LK_WAIT_NONZERO)) == 0) {
+	    (lkp->lk_sharewait == 0) &&
+	    (lkp->lk_exclusivewait == 0) &&
+	    (lkp->lk_sharecount== 0) &&
+	    (lkp->lk_exclusivecount== 0)) {
 		lkp->lk_flags &= ~LK_WAITDRAIN;
 		wakeup((void *)&lkp->lk_flags);
 	}
@@ -479,10 +435,14 @@
 acquiredrain(struct lock *lkp, int extflags) {
 	int error;
 
-	if ((extflags & LK_NOWAIT) && (lkp->lk_flags & LK_ALL)) {
-		return EBUSY;
-	}
-	while (lkp->lk_flags & LK_ALL) {
+
+	while ((lkp->lk_sharecount != 0) ||
+	    (lkp->lk_sharewait != 0) ||
+	    (lkp->lk_exclusivecount != 0) ||
+	    (lkp->lk_exclusivewait != 0)) {
+			
+		if (extflags & LK_NOWAIT) return EBUSY;
+
 		lkp->lk_flags |= LK_WAITDRAIN;
 		error = msleep(&lkp->lk_flags, lkp->lk_interlock, lkp->lk_prio,
 			lkp->lk_wmesg, 
@@ -496,34 +456,7 @@
 	return 0;
 }
 
-/*
- * Transfer any waiting processes from one lock to another.
- */
-void
-transferlockers(from, to)
-	struct lock *from;
-	struct lock *to;
-{
-
-	KASSERT(from != to, ("lock transfer to self"));
-	KASSERT((from->lk_flags&LK_WAITDRAIN) == 0, ("transfer draining lock"));
 
-	mtx_lock(from->lk_interlock);
-	if (from->lk_waitcount == 0) {
-		mtx_unlock(from->lk_interlock);
-		return;
-	}
-	from->lk_newlock = to;
-	wakeup((void *)from);
-	msleep(&from->lk_newlock, from->lk_interlock, from->lk_prio,
-	    "lkxfer", 0);
-	from->lk_newlock = NULL;
-	from->lk_flags &= ~(LK_WANT_EXCL | LK_WANT_UPGRADE);
-	KASSERT(from->lk_waitcount == 0, ("active lock"));
-	mtx_unlock(from->lk_interlock);
-}
-
-
 /*
  * Initialize a lock; required before use.
  */
@@ -541,18 +474,16 @@
 	lkp->lk_interlock = mtx_pool_alloc(mtxpool_lockbuilder);
 	lkp->lk_flags = (flags & LK_EXTFLG_MASK);
 	lkp->lk_sharecount = 0;
-	lkp->lk_waitcount = 0;
+	lkp->lk_sharewait = 0;
 	lkp->lk_exclusivecount = 0;
+	lkp->lk_exclusivewait = 0;
 	lkp->lk_prio = prio;
+	lkp->lk_wmesg = wmesg;
 	lkp->lk_timo = timo;
 	lkp->lk_lockholder = LK_NOPROC;
-	lkp->lk_newlock = NULL;
 #ifdef DEBUG_LOCKS
 	stack_zero(&lkp->lk_stack);
 #endif
-	lock_profile_object_init(&lkp->lk_object, &lock_class_lockmgr, wmesg);
-	lock_init(&lkp->lk_object, &lock_class_lockmgr, wmesg, NULL,
-	    LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE);
 }
 
 /*
@@ -564,8 +495,6 @@
 {
 	CTR2(KTR_LOCK, "lockdestroy(): lkp == %p (lk_wmesg == \"%s\")",
 	    lkp, lkp->lk_wmesg);
-	lock_profile_object_destroy(&lkp->lk_object);
-	lock_destroy(&lkp->lk_object);
 }
 
 /*
@@ -606,7 +535,8 @@
 	int count;
 
 	mtx_lock(lkp->lk_interlock);
-	count = lkp->lk_exclusivecount + lkp->lk_sharecount;
+	count = lkp->lk_exclusivecount + 
+		lkp->lk_sharecount;
 	mtx_unlock(lkp->lk_interlock);
 	return (count);
 }
@@ -621,7 +551,9 @@
 	int count;
 
 	mtx_lock(lkp->lk_interlock);
-	count = lkp->lk_waitcount;
+	count = lkp->lk_exclusivewait + 
+		lkp->lk_sharewait + 
+		(lkp->lk_flags & LK_WANT_UPGRADE) ? 1 : 0;
 	mtx_unlock(lkp->lk_interlock);
 	return (count);
 }
@@ -638,12 +570,14 @@
 	if (lkp->lk_sharecount)
 		printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
 		    lkp->lk_sharecount);
-	else if (lkp->lk_flags & LK_HAVE_EXCL)
+	else if (lkp->lk_exclusivecount)
 		printf(" lock type %s: EXCL (count %d) by thread %p (pid %d)",
 		    lkp->lk_wmesg, lkp->lk_exclusivecount,
 		    lkp->lk_lockholder, lkp->lk_lockholder->td_proc->p_pid);
-	if (lkp->lk_waitcount > 0)
-		printf(" with %d pending", lkp->lk_waitcount);
+	if (lkp->lk_sharewait > 0)
+		printf(" with %d pending readers", lkp->lk_sharewait);
+	if (lkp->lk_exclusivewait > 0)
+		printf(" with %d pending writers", lkp->lk_exclusivewait);
 #ifdef DEBUG_LOCKS
 	stack_print(&lkp->lk_stack);
 #endif
@@ -663,24 +597,9 @@
 	lkp = td->td_wchan;
 
 	/* Simple test to see if wchan points to a lockmgr lock. */
-	if (LOCK_CLASS(&lkp->lk_object) == &lock_class_lockmgr &&
-	    lkp->lk_wmesg == td->td_wmesg)
-		goto ok;
-
-	/*
-	 * If this thread is doing a DRAIN, then it would be asleep on
-	 * &lkp->lk_flags rather than lkp.
-	 */
-	lkp = (struct lock *)((char *)td->td_wchan -
-	    offsetof(struct lock, lk_flags));
-	if (LOCK_CLASS(&lkp->lk_object) == &lock_class_lockmgr &&
-	    lkp->lk_wmesg == td->td_wmesg && (lkp->lk_flags & LK_WAITDRAIN))
-		goto ok;
+	if (lkp->lk_wmesg != td->td_wmesg)
+		return (0);
 
-	/* Doen't seem to be a lockmgr lock. */
-	return (0);
-
-ok:
 	/* Ok, we think we have a lockmgr lock, so output some details. */
 	db_printf("blocked on lk \"%s\" ", lkp->lk_wmesg);
 	if (lkp->lk_sharecount) {
@@ -693,26 +612,29 @@
 	return (1);
 }
 
-void
-db_show_lockmgr(struct lock_object *lock)
+DB_SHOW_COMMAND(lockmgr, db_show_lockmgr)
 {
 	struct thread *td;
 	struct lock *lkp;
 
-	lkp = (struct lock *)lock;
+	if (!have_addr)
+		return;
+	lkp = (struct lock *)addr;
 
-	db_printf(" lock type: %s\n", lkp->lk_wmesg);
-	db_printf(" state: ");
+	db_printf("lock type: %s\n", lkp->lk_wmesg);
+	db_printf("state: ");
 	if (lkp->lk_sharecount)
 		db_printf("SHARED (count %d)\n", lkp->lk_sharecount);
-	else if (lkp->lk_flags & LK_HAVE_EXCL) {
+	else if (lkp->lk_exclusivecount != 0) {
 		td = lkp->lk_lockholder;
 		db_printf("EXCL (count %d) %p ", lkp->lk_exclusivecount, td);
 		db_printf("(tid %d, pid %d, \"%s\")\n", td->td_tid,
 		    td->td_proc->p_pid, td->td_proc->p_comm);
 	} else
 		db_printf("UNLOCKED\n");
-	if (lkp->lk_waitcount > 0)
-		db_printf(" waiters: %d\n", lkp->lk_waitcount);
+	if (lkp->lk_sharewait > 0)
+		db_printf("waiters shared: %d\n", lkp->lk_sharewait);
+	if (lkp->lk_exclusivewait > 0)
+		db_printf("waiters exclusive: %d\n", lkp->lk_exclusivewait);
 }
 #endif

==== //depot/user/kris/contention/sys/kern/subr_lock.c#6 (text+ko) ====

@@ -58,7 +58,6 @@
 	&lock_class_mtx_sleep,
 	&lock_class_sx,
 	&lock_class_rw,
-	&lock_class_lockmgr,
 };
 
 #ifdef LOCK_PROFILING

==== //depot/user/kris/contention/sys/kern/vfs_default.c#4 (text+ko) ====

@@ -263,7 +263,7 @@
 {
 	struct vnode *vp = ap->a_vp;
 
-	return (_lockmgr(vp->v_vnlock, ap->a_flags, VI_MTX(vp), ap->a_td, ap->a_file, ap->a_line));
+	return (lockmgr(vp->v_vnlock, ap->a_flags, VI_MTX(vp), ap->a_td));
 }
 
 /* See above. */

==== //depot/user/kris/contention/sys/sys/lockmgr.h#5 (text+ko) ====

@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)lock.h	8.12 (Berkeley) 5/19/95
- * $FreeBSD: src/sys/sys/lockmgr.h,v 1.53 2007/03/30 18:07:24 jhb Exp $
+ * $FreeBSD: src/sys/sys/lockmgr.h,v 1.47.2.3 2006/10/09 20:04:46 tegge Exp $
  */
 
 #ifndef	_SYS_LOCKMGR_H_
@@ -40,8 +40,6 @@
 #ifdef	DEBUG_LOCKS
 #include <sys/stack.h> /* XXX */
 #endif
-#include <sys/queue.h>
-#include <sys/_lock.h>
 
 struct	mtx;
 
@@ -51,23 +49,22 @@
  * can be gained.
  */
 struct lock {
-	struct lock_object lk_object;   /* common lock properties */
 	struct	mtx *lk_interlock;	/* lock on remaining fields */
 	u_int	lk_flags;		/* see below */
 	int	lk_sharecount;		/* # of accepted shared locks */
-	int	lk_waitcount;		/* # of processes sleeping for lock */
-	short	lk_exclusivecount;	/* # of recursive exclusive locks */
+	int	lk_sharewait;		/* # waiting for shared locks */
+	int	lk_exclusivecount;	/* # of recursive exclusive locks */
+	int	lk_exclusivewait;	/* # of recursive exclusive locks */
+
 	short	lk_prio;		/* priority at which to sleep */
+	const char *lk_wmesg;		/* resource sleeping (for tsleep) */
 	int	lk_timo;		/* maximum sleep time (for tsleep) */
 	struct thread *lk_lockholder;	/* thread of exclusive lock holder */
-	struct	lock *lk_newlock;	/* lock taking over this lock */
-
+	
 #ifdef	DEBUG_LOCKS
 	struct stack lk_stack;
 #endif
 };
-
-#define lk_wmesg lk_object.lo_name
 /*
  * Lock request types:
  *   LK_SHARED - get one of many possible shared locks. If a process
@@ -202,15 +199,13 @@
 			int timo, int flags);
 void	lockdestroy(struct lock *);
 
-int	_lockmgr(struct lock *, u_int flags,
-		 struct mtx *, struct thread *p, char *file, int line);
+int	lockmgr(struct lock *, u_int flags,
+			struct mtx *, struct thread *p);
 void	transferlockers(struct lock *, struct lock *);
 void	lockmgr_printinfo(struct lock *);
 int	lockstatus(struct lock *, struct thread *);
 int	lockcount(struct lock *);
 int	lockwaiters(struct lock *);
-
-#define lockmgr(lock, flags, mtx, td) _lockmgr((lock), (flags), (mtx), (td), __FILE__, __LINE__)
 #ifdef DDB
 int	lockmgr_chain(struct thread *td, struct thread **ownerp);
 #endif

==== //depot/user/kris/contention/sys/ufs/ffs/ffs_vfsops.c#6 (text+ko) ====

@@ -881,6 +881,9 @@
 #endif /* !UFS_EXTATTR_AUTOSTART */
 #endif /* !UFS_EXTATTR */
 	MNT_ILOCK(mp);
+#ifndef NO_UFS_LOOKUP_SHARED
+        mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED;
+#endif
 	mp->mnt_kern_flag |= MNTK_MPSAFE;
 	MNT_IUNLOCK(mp);
 	return (0);

==== //depot/user/kris/contention/sys/ufs/ffs/ffs_vnops.c#6 (text+ko) ====

@@ -370,7 +370,7 @@
 				flags |= LK_INTERLOCK;
 			}
 			lkp = vp->v_vnlock;
-			result = _lockmgr(lkp, flags, VI_MTX(vp), ap->a_td, ap->a_file, ap->a_line);
+			result = lockmgr(lkp, flags, VI_MTX(vp), ap->a_td);
 			if (lkp == vp->v_vnlock || result != 0)
 				break;
 			/*
@@ -381,7 +381,7 @@
 			 * right lock.  Release it, and try to get the
 			 * new lock.
 			 */
-			(void) _lockmgr(lkp, LK_RELEASE, VI_MTX(vp), ap->a_td, ap->a_file, ap->a_line);
+			(void) lockmgr(lkp, LK_RELEASE, VI_MTX(vp), ap->a_td);
 			if ((flags & LK_TYPE_MASK) == LK_UPGRADE)
 				flags = (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE;
 			flags &= ~LK_INTERLOCK;

==== //depot/user/kris/contention/sys/ufs/ufs/ufs_lookup.c#4 (text+ko) ====

@@ -166,6 +166,14 @@
 
 	vdp = ap->a_dvp;
 	dp = VTOI(vdp);
+
+#ifndef NO_UFS_LOOKUP_SHARED
+	if ((vdp->v_mount->mnt_kern_flag & MNTK_LOOKUP_SHARED) &&
+            (VOP_ISLOCKED(vdp, td) != LK_EXCLUSIVE)) {
+                /* Upgrade to exclusive lock, this might block */
+                VOP_LOCK(vdp, LK_UPGRADE, td);
+        }
+#endif
 	/*
 	 * We now have a segment name to search for, and a directory to search.
 	 *

--------------030803050501020800060905--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?474339E9.4080301>