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)
{