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

Change 117289 by [EMAIL PROTECTED] 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.
         *
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to