2 x quad-core system is slower that 2 x dual core on FreeBSD
Kris Kennaway
kris at FreeBSD.org
Tue Nov 20 11:47:50 PST 2007
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
-------------- next part --------------
Change 117289 by kris at 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.
*
More information about the freebsd-stable
mailing list