Fix bugs in spin_trylock_wr():
authorNicolas Thery <nth@dragonflybsd.org>
Wed, 4 Jun 2008 04:34:54 +0000 (04:34 +0000)
committerNicolas Thery <nth@dragonflybsd.org>
Wed, 4 Jun 2008 04:34:54 +0000 (04:34 +0000)
- globaldata.gd_spinlock_wr was not decremented back on failure;

- incorrect comparison in loop trying to clear cached shared bits (loop
  must fail if spinlock is still held for read by another cpu).

Reviewed-by: dillon@
sys/kern/kern_spinlock.c
sys/sys/spinlock2.h

index 322f385..02829a6 100644 (file)
@@ -29,7 +29,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/kern_spinlock.c,v 1.14 2008/05/24 12:52:49 sephe Exp $
+ * $DragonFly: src/sys/kern/kern_spinlock.c,v 1.15 2008/06/04 04:34:54 nth Exp $
  */
 
 #include <sys/param.h>
@@ -125,7 +125,7 @@ exponential_init(struct exponential_backoff *bo, struct spinlock *mtx)
  * 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;
 
@@ -133,14 +133,16 @@ spin_trylock_wr_contested(struct spinlock *mtx, int value)
        if ((value & SPINLOCK_EXCLUSIVE) == 0) {
                while (value) {
                        bit = bsfl(value);
-                       if (globaldata_find(bit)->gd_spinlock_rd != mtx) {
+                       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 a2222cf..b0fe767 100644 (file)
@@ -29,7 +29,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/spinlock2.h,v 1.11 2006/06/01 19:02:39 dillon Exp $
+ * $DragonFly: src/sys/sys/spinlock2.h,v 1.12 2008/06/04 04:34:54 nth Exp $
  */
 
 #ifndef _SYS_SPINLOCK2_H_
@@ -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);
 }