Print this page
3746 ZRLs are racy
Reviewed by: Boris Protopopov <bprotopopov@hotmail.com>
Reviewed by: Pavel Zakharov <pavel.zakha@gmail.com>
Reviewed by: Yuri Pankov <yuri.pankov@gmail.com>
Reviewed by: Justin T. Gibbs <gibbs@scsiguy.com>

@@ -19,10 +19,12 @@
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
+ * Copyright 2016 Spectra Logic Corporation. All rights reserved.
+ * Copyright 2016 The MathWorks, Inc. All rights reserved.
  */
 
 /*
  * A Zero Reference Lock (ZRL) is a reference count that can lock out new
  * references only when the count is zero and only without waiting if the count

@@ -69,15 +71,17 @@
 }
 
 void
 zrl_add_impl(zrlock_t *zrl, const char *zc)
 {
+        for (;;) {
         uint32_t n = (uint32_t)zrl->zr_refcount;
 
         while (n != ZRL_LOCKED) {
                 uint32_t cas = atomic_cas_32(
                     (uint32_t *)&zrl->zr_refcount, n, n + 1);
+
                 if (cas == n) {
                         ASSERT3S((int32_t)n, >=, 0);
 #ifdef  ZFS_DEBUG
                         if (zrl->zr_owner == curthread) {
                                 DTRACE_PROBE2(zrlock__reentry,

@@ -93,17 +97,12 @@
 
         mutex_enter(&zrl->zr_mtx);
         while (zrl->zr_refcount == ZRL_LOCKED) {
                 cv_wait(&zrl->zr_cv, &zrl->zr_mtx);
         }
-        ASSERT3S(zrl->zr_refcount, >=, 0);
-        zrl->zr_refcount++;
-#ifdef  ZFS_DEBUG
-        zrl->zr_owner = curthread;
-        zrl->zr_caller = zc;
-#endif
         mutex_exit(&zrl->zr_mtx);
+        }
 }
 
 void
 zrl_remove(zrlock_t *zrl)
 {