Hello,

While studying the spinlock implementation, I found that
spin_trylock_wr() does not decrement back
globaldata.gd_spinlock_wr if it fails to get the lock.

This looks like a bug because gd_spinlock_wr is tested in several
locations to check if a lock is held.

The following patch changes this.  I'll commit it if nobody objects.

Cheers,
Nicolas

Index: src2/sys/kern/kern_spinlock.c
===================================================================
--- src2.orig/sys/kern/kern_spinlock.c  2008-05-26 01:42:36.000000000 +0200
+++ src2/sys/kern/kern_spinlock.c       2008-06-03 22:12:33.000000000 +0200
@@ -125,7 +125,7 @@ exponential_init(struct exponential_back
  * we couldn't clear (and also clear our exclusive bit).
  */
 int
-spin_trylock_wr_contested(struct spinlock *mtx, int value)
+spin_trylock_wr_contested(globaldata_t gd, struct spinlock *mtx, int value)
 {
        int bit;

@@ -135,12 +135,14 @@ spin_trylock_wr_contested(struct spinloc
                        bit = bsfl(value);
                        if (globaldata_find(bit)->gd_spinlock_rd != mtx) {
                                atomic_swap_int(&mtx->lock, value);
+                               --gd->gd_spinlocks_wr;
                                return (FALSE);
                        }
                        value &= ~(1 << bit);
                }
                return (TRUE);
        }
+       --gd->gd_spinlocks_wr;
        return (FALSE);
 }

Index: src2/sys/sys/spinlock2.h
===================================================================
--- src2.orig/sys/sys/spinlock2.h       2008-06-03 22:20:27.000000000 +0200
+++ src2/sys/sys/spinlock2.h    2008-06-03 22:21:15.000000000 +0200
@@ -67,7 +67,8 @@

 #ifdef SMP

-extern int spin_trylock_wr_contested(struct spinlock *mtx, int value);
+extern int spin_trylock_wr_contested(globaldata_t gd, struct spinlock *mtx,
+    int value);
 extern void spin_lock_wr_contested(struct spinlock *mtx, int value);
 extern void spin_lock_rd_contested(struct spinlock *mtx);

@@ -88,7 +89,7 @@ spin_trylock_wr(struct spinlock *mtx)

        ++gd->gd_spinlocks_wr;
        if ((value = atomic_swap_int(&mtx->lock, SPINLOCK_EXCLUSIVE)) != 0)
-               return (spin_trylock_wr_contested(mtx, value));
+               return (spin_trylock_wr_contested(gd, mtx, value));
        return (TRUE);
 }

Reply via email to