FreeBSD ZFS
The Zettabyte File System
|
00001 /* 00002 * CDDL HEADER START 00003 * 00004 * The contents of this file are subject to the terms of the 00005 * Common Development and Distribution License (the "License"). 00006 * You may not use this file except in compliance with the License. 00007 * 00008 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 00009 * or http://www.opensolaris.org/os/licensing. 00010 * See the License for the specific language governing permissions 00011 * and limitations under the License. 00012 * 00013 * When distributing Covered Code, include this CDDL HEADER in each 00014 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 00015 * If applicable, add the following below this CDDL HEADER, with the 00016 * fields enclosed by brackets "[]" replaced with your own identifying 00017 * information: Portions Copyright [yyyy] [name of copyright owner] 00018 * 00019 * CDDL HEADER END 00020 */ 00021 /* 00022 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 00023 */ 00024 00042 #include <sys/zrlock.h> 00043 00044 /* 00045 * A ZRL can be locked only while there are zero references, so ZRL_LOCKED is 00046 * treated as zero references. 00047 */ 00048 #define ZRL_LOCKED ((uint32_t)-1) 00049 #define ZRL_DESTROYED -2 00050 00051 void 00052 zrl_init(zrlock_t *zrl) 00053 { 00054 mutex_init(&zrl->zr_mtx, NULL, MUTEX_DEFAULT, NULL); 00055 zrl->zr_refcount = 0; 00056 cv_init(&zrl->zr_cv, NULL, CV_DEFAULT, NULL); 00057 #ifdef ZFS_DEBUG 00058 zrl->zr_owner = NULL; 00059 zrl->zr_caller = NULL; 00060 #endif 00061 } 00062 00063 void 00064 zrl_destroy(zrlock_t *zrl) 00065 { 00066 ASSERT(zrl->zr_refcount == 0); 00067 00068 mutex_destroy(&zrl->zr_mtx); 00069 zrl->zr_refcount = ZRL_DESTROYED; 00070 cv_destroy(&zrl->zr_cv); 00071 } 00072 00073 void 00074 #ifdef ZFS_DEBUG 00075 zrl_add_debug(zrlock_t *zrl, const char *zc) 00076 #else 00077 zrl_add(zrlock_t *zrl) 00078 #endif 00079 { 00080 uint32_t n = (uint32_t)zrl->zr_refcount; 00081 00082 while (n != ZRL_LOCKED) { 00083 uint32_t cas = atomic_cas_32( 00084 (uint32_t *)&zrl->zr_refcount, n, n + 1); 00085 if (cas == n) { 00086 ASSERT((int32_t)n >= 0); 00087 #ifdef ZFS_DEBUG 00088 if (zrl->zr_owner == curthread) { 00089 DTRACE_PROBE2(zrlock__reentry, 00090 zrlock_t *, zrl, uint32_t, n); 00091 } 00092 zrl->zr_owner = curthread; 00093 zrl->zr_caller = zc; 00094 #endif 00095 return; 00096 } 00097 n = cas; 00098 } 00099 00100 mutex_enter(&zrl->zr_mtx); 00101 while (zrl->zr_refcount == ZRL_LOCKED) { 00102 cv_wait(&zrl->zr_cv, &zrl->zr_mtx); 00103 } 00104 ASSERT(zrl->zr_refcount >= 0); 00105 zrl->zr_refcount++; 00106 #ifdef ZFS_DEBUG 00107 zrl->zr_owner = curthread; 00108 zrl->zr_caller = zc; 00109 #endif 00110 mutex_exit(&zrl->zr_mtx); 00111 } 00112 00113 void 00114 zrl_remove(zrlock_t *zrl) 00115 { 00116 uint32_t n; 00117 00118 n = atomic_dec_32_nv((uint32_t *)&zrl->zr_refcount); 00119 ASSERT((int32_t)n >= 0); 00120 #ifdef ZFS_DEBUG 00121 if (zrl->zr_owner == curthread) { 00122 zrl->zr_owner = NULL; 00123 zrl->zr_caller = NULL; 00124 } 00125 #endif 00126 } 00127 00128 int 00129 zrl_tryenter(zrlock_t *zrl) 00130 { 00131 uint32_t n = (uint32_t)zrl->zr_refcount; 00132 00133 if (n == 0) { 00134 uint32_t cas = atomic_cas_32( 00135 (uint32_t *)&zrl->zr_refcount, 0, ZRL_LOCKED); 00136 if (cas == 0) { 00137 #ifdef ZFS_DEBUG 00138 ASSERT(zrl->zr_owner == NULL); 00139 zrl->zr_owner = curthread; 00140 #endif 00141 return (1); 00142 } 00143 } 00144 00145 ASSERT((int32_t)n > ZRL_DESTROYED); 00146 00147 return (0); 00148 } 00149 00150 void 00151 zrl_exit(zrlock_t *zrl) 00152 { 00153 ASSERT(zrl->zr_refcount == ZRL_LOCKED); 00154 00155 mutex_enter(&zrl->zr_mtx); 00156 #ifdef ZFS_DEBUG 00157 ASSERT(zrl->zr_owner == curthread); 00158 zrl->zr_owner = NULL; 00159 membar_producer(); /* make sure the owner store happens first */ 00160 #endif 00161 zrl->zr_refcount = 0; 00162 cv_broadcast(&zrl->zr_cv); 00163 mutex_exit(&zrl->zr_mtx); 00164 } 00165 00166 int 00167 zrl_refcount(zrlock_t *zrl) 00168 { 00169 ASSERT(zrl->zr_refcount > ZRL_DESTROYED); 00170 00171 int n = (int)zrl->zr_refcount; 00172 return (n <= 0 ? 0 : n); 00173 } 00174 00175 int 00176 zrl_is_zero(zrlock_t *zrl) 00177 { 00178 ASSERT(zrl->zr_refcount > ZRL_DESTROYED); 00179 00180 return (zrl->zr_refcount <= 0); 00181 } 00182 00183 int 00184 zrl_is_locked(zrlock_t *zrl) 00185 { 00186 ASSERT(zrl->zr_refcount > ZRL_DESTROYED); 00187 00188 return (zrl->zr_refcount == ZRL_LOCKED); 00189 } 00190 00191 #ifdef ZFS_DEBUG 00192 kthread_t * 00193 zrl_owner(zrlock_t *zrl) 00194 { 00195 return (zrl->zr_owner); 00196 } 00197 #endif