OpenAFS
OpenAFS distributed network file system
|
00001 /* 00002 * Copyright (c) 2010 Your Filesystem Inc. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 1. Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * 2. Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * 00013 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 00014 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00015 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00016 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00017 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00018 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00019 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00020 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00021 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00022 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00023 */ 00024 00025 #ifndef OPENAFS_RX_ATOMIC_H 00026 #define OPENAFS_RX_ATOMIC_H 1 00027 00028 #define RX_ATOMIC_INIT(i) { (i) } 00029 00030 #ifdef AFS_NT40_ENV 00031 typedef struct { 00032 volatile int var; 00033 } rx_atomic_t; 00034 00035 static_inline void 00036 rx_atomic_set(rx_atomic_t *atomic, int val) { 00037 atomic->var = val; 00038 } 00039 00040 static_inline int 00041 rx_atomic_read(rx_atomic_t *atomic) { 00042 return atomic->var; 00043 } 00044 00045 static_inline void 00046 rx_atomic_inc(rx_atomic_t *atomic) { 00047 InterlockedIncrement(&atomic->var); 00048 } 00049 00050 static_inline int 00051 rx_atomic_inc_and_read(rx_atomic_t *atomic) { 00052 return InterlockedIncrement(&atomic->var); 00053 } 00054 00055 static_inline void 00056 rx_atomic_add(rx_atomic_t *atomic, int change) { 00057 InterlockedExchangeAdd(&atomic->var, change); 00058 } 00059 00060 static_inline int 00061 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) { 00062 return InterlockedExchangeAdd(&atomic->var, change) + change; 00063 } 00064 00065 static_inline void 00066 rx_atomic_dec(rx_atomic_t *atomic) { 00067 InterlockedDecrement(&atomic->var); 00068 } 00069 00070 static_inline int 00071 rx_atomic_dec_and_read(rx_atomic_t *atomic) { 00072 return InterlockedDecrement(&atomic->var); 00073 } 00074 00075 static_inline void 00076 rx_atomic_sub(rx_atomic_t *atomic, int change) { 00077 InterlockedExchangeAdd(&atomic->var, 0 - change); 00078 } 00079 00080 #elif defined(AFS_AIX61_ENV) || defined(AFS_USR_AIX61_ENV) 00081 #include <sys/atomic_op.h> 00082 00083 typedef struct { 00084 volatile int var; 00085 } rx_atomic_t; 00086 00087 static_inline void 00088 rx_atomic_set(rx_atomic_t *atomic, int val) { 00089 atomic->var = val; 00090 } 00091 00092 static_inline int 00093 rx_atomic_read(rx_atomic_t *atomic) { 00094 return atomic->var; 00095 } 00096 00097 static_inline void 00098 rx_atomic_inc(rx_atomic_t *atomic) { 00099 fetch_and_add(&atomic->var, 1); 00100 } 00101 00102 static_inline int 00103 rx_atomic_inc_and_read(rx_atomic_t *atomic) { 00104 return (fetch_and_add(&atomic->var, 1) + 1); 00105 } 00106 00107 static_inline void 00108 rx_atomic_add(rx_atomic_t *atomic, int change) { 00109 fetch_and_add(&atomic->var, change); 00110 } 00111 00112 static_inline int 00113 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) { 00114 return (fetch_and_add(&atomic->var, change) + change); 00115 } 00116 00117 static_inline void 00118 rx_atomic_dec(rx_atomic_t *atomic) { 00119 fetch_and_add(&atomic->var, -1); 00120 } 00121 00122 static_inline int 00123 rx_atomic_dec_and_read(rx_atomic_t *atomic) { 00124 return (fetch_and_add(&atomic->var, -1) - 1); 00125 } 00126 00127 static_inline void 00128 rx_atomic_sub(rx_atomic_t *atomic, int change) { 00129 fetch_and_add(&atomic->var, -change); 00130 } 00131 00132 #elif defined(AFS_DARWIN80_ENV) || defined(AFS_USR_DARWIN80_ENV) 00133 00134 #include <libkern/OSAtomic.h> 00135 #if defined(KERNEL) && !defined(UKERNEL) 00136 #define OSAtomicIncrement32 OSIncrementAtomic 00137 #define OSAtomicAdd32 OSAddAtomic 00138 #define OSAtomicDecrement32 OSDecrementAtomic 00139 #endif 00140 00141 typedef struct { 00142 volatile int var; 00143 } rx_atomic_t; 00144 00145 static_inline void 00146 rx_atomic_set(rx_atomic_t *atomic, int val) { 00147 atomic->var = val; 00148 } 00149 00150 static_inline int 00151 rx_atomic_read(rx_atomic_t *atomic) { 00152 return atomic->var; 00153 } 00154 00155 static_inline void 00156 rx_atomic_inc(rx_atomic_t *atomic) { 00157 OSAtomicIncrement32(&atomic->var); 00158 } 00159 00160 static_inline int 00161 rx_atomic_inc_and_read(rx_atomic_t *atomic) { 00162 return OSAtomicIncrement32(&atomic->var); 00163 } 00164 00165 static_inline void 00166 rx_atomic_add(rx_atomic_t *atomic, int change) { 00167 OSAtomicAdd32(change, &atomic->var); 00168 } 00169 00170 static_inline int 00171 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) { 00172 return OSAtomicAdd32(change, &atomic->var); 00173 } 00174 00175 static_inline void 00176 rx_atomic_dec(rx_atomic_t *atomic) { 00177 OSAtomicDecrement32(&atomic->var); 00178 } 00179 00180 static_inline int 00181 rx_atomic_dec_and_read(rx_atomic_t *atomic) { 00182 return OSAtomicDecrement32(&atomic->var); 00183 } 00184 00185 static_inline void 00186 rx_atomic_sub(rx_atomic_t *atomic, int change) { 00187 OSAtomicAdd32(0 - change, &atomic->var); 00188 } 00189 #elif defined(AFS_LINUX26_ENV) && defined(KERNEL) 00190 #include <asm/atomic.h> 00191 00192 typedef atomic_t rx_atomic_t; 00193 00194 #define rx_atomic_set(X, V) atomic_set(X, V) 00195 #define rx_atomic_read(X) atomic_read(X) 00196 #define rx_atomic_inc(X) atomic_inc(X) 00197 #define rx_atomic_inc_and_read(X) atomic_inc_return(X) 00198 #define rx_atomic_add(X, V) atomic_add(V, X) 00199 #define rx_atomic_add_and_read(X, V) atomic_add_return(V, X); 00200 #define rx_atomic_dec(X) atomic_dec(X) 00201 #define rx_atomic_dec_and_read(X) atomic_dec_return(X) 00202 #define rx_atomic_sub(X, V) atomic_sub(V, X) 00203 00204 #elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL)) 00205 00206 # if defined(KERNEL) && !defined(UKERNEL) 00207 # include <sys/atomic.h> 00208 # else 00209 # include <atomic.h> 00210 # endif 00211 00212 #ifndef AFS_SUN510_ENV 00213 # define atomic_inc_32(X) atomic_add_32((X), 1) 00214 # define atomic_inc_32_nv(X) atomic_add_32_nv((X), 1) 00215 # define atomic_dec_32(X) atomic_add_32((X), -1) 00216 # define atomic_dec_32_nv(X) atomic_add_32_nv((X), -1) 00217 #endif 00218 00219 typedef struct { 00220 volatile unsigned int var; 00221 } rx_atomic_t; 00222 00223 static_inline void 00224 rx_atomic_set(rx_atomic_t *atomic, int val) { 00225 atomic->var = val; 00226 } 00227 00228 static_inline int 00229 rx_atomic_read(rx_atomic_t *atomic) { 00230 return atomic->var; 00231 } 00232 00233 static_inline void 00234 rx_atomic_inc(rx_atomic_t *atomic) { 00235 atomic_inc_32(&atomic->var); 00236 } 00237 00238 static_inline int 00239 rx_atomic_inc_and_read(rx_atomic_t *atomic) { 00240 return atomic_inc_32_nv(&atomic->var); 00241 } 00242 00243 static_inline void 00244 rx_atomic_add(rx_atomic_t *atomic, int change) { 00245 atomic_add_32(&atomic->var, change); 00246 } 00247 00248 static_inline int 00249 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) { 00250 return atomic_add_32_nv(&atomic->var, change); 00251 } 00252 00253 static_inline void 00254 rx_atomic_dec(rx_atomic_t *atomic) { 00255 atomic_dec_32(&atomic->var); 00256 } 00257 00258 static_inline int 00259 rx_atomic_dec_and_read(rx_atomic_t *atomic) { 00260 return atomic_dec_32_nv(&atomic->var); 00261 } 00262 00263 static_inline void 00264 rx_atomic_sub(rx_atomic_t *atomic, int change) { 00265 atomic_add_32(&atomic->var, 0 - change); 00266 } 00267 00268 #elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD) 00269 00270 typedef struct { 00271 volatile int var; 00272 } rx_atomic_t; 00273 00274 static_inline void 00275 rx_atomic_set(rx_atomic_t *atomic, int val) { 00276 atomic->var = val; 00277 } 00278 00279 static_inline int 00280 rx_atomic_read(rx_atomic_t *atomic) { 00281 return atomic->var; 00282 } 00283 00284 static_inline void 00285 rx_atomic_inc(rx_atomic_t *atomic) { 00286 (void)__sync_fetch_and_add(&atomic->var, 1); 00287 } 00288 00289 static_inline int 00290 rx_atomic_inc_and_read(rx_atomic_t *atomic) { 00291 return __sync_add_and_fetch(&atomic->var, 1); 00292 } 00293 00294 static_inline void 00295 rx_atomic_add(rx_atomic_t *atomic, int change) { 00296 (void)__sync_fetch_and_add(&atomic->var, change); 00297 } 00298 00299 static_inline int 00300 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) { 00301 return __sync_fetch_and_add(&atomic->var, change); 00302 } 00303 00304 static_inline void 00305 rx_atomic_dec(rx_atomic_t *atomic) { 00306 (void)__sync_fetch_and_sub(&atomic->var, 1); 00307 } 00308 00309 static_inline int 00310 rx_atomic_dec_and_read(rx_atomic_t *atomic) { 00311 return __sync_sub_and_fetch(&atomic->var, 1); 00312 } 00313 00314 static_inline void 00315 rx_atomic_sub(rx_atomic_t *atomic, int change) { 00316 (void)__sync_fetch_and_sub(&atomic->var, change); 00317 } 00318 00319 #else 00320 00321 /* If we're on a platform where we have no idea how to do atomics, 00322 * then we fall back to using a single process wide mutex to protect 00323 * all atomic variables. This won't be the quickest thing ever. 00324 */ 00325 00326 #ifdef RX_ENABLE_LOCKS 00327 extern afs_kmutex_t rx_atomic_mutex; 00328 #endif 00329 00330 typedef struct { 00331 int var; 00332 } rx_atomic_t; 00333 00334 static_inline void 00335 rx_atomic_set(rx_atomic_t *atomic, int val) { 00336 MUTEX_ENTER(&rx_atomic_mutex); 00337 atomic->var = val; 00338 MUTEX_EXIT(&rx_atomic_mutex); 00339 } 00340 00341 static_inline int 00342 rx_atomic_read(rx_atomic_t *atomic) { 00343 int out; 00344 00345 MUTEX_ENTER(&rx_atomic_mutex); 00346 out = atomic->var; 00347 MUTEX_EXIT(&rx_atomic_mutex); 00348 00349 return out; 00350 } 00351 00352 static_inline void 00353 rx_atomic_inc(rx_atomic_t *atomic) { 00354 MUTEX_ENTER(&rx_atomic_mutex); 00355 atomic->var++; 00356 MUTEX_EXIT(&rx_atomic_mutex); 00357 } 00358 00359 static_inline int 00360 rx_atomic_inc_and_read(rx_atomic_t *atomic) { 00361 int retval; 00362 MUTEX_ENTER(&rx_atomic_mutex); 00363 atomic->var++; 00364 retval = atomic->var; 00365 MUTEX_EXIT(&rx_atomic_mutex); 00366 return retval; 00367 } 00368 00369 static_inline void 00370 rx_atomic_add(rx_atomic_t *atomic, int change) { 00371 MUTEX_ENTER(&rx_atomic_mutex); 00372 atomic->var += change; 00373 MUTEX_EXIT(&rx_atomic_mutex); 00374 } 00375 00376 static_inline int 00377 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) { 00378 int retval; 00379 00380 MUTEX_ENTER(&rx_atomic_mutex); 00381 atomic->var += change; 00382 retval = atomic->var; 00383 MUTEX_EXIT(&rx_atomic_mutex); 00384 00385 return retval; 00386 } 00387 00388 static_inline void 00389 rx_atomic_dec(rx_atomic_t *atomic) { 00390 MUTEX_ENTER(&rx_atomic_mutex); 00391 atomic->var--; 00392 MUTEX_EXIT(&rx_atomic_mutex); 00393 } 00394 00395 static_inline int 00396 rx_atomic_dec_and_read(rx_atomic_t *atomic) { 00397 int retval; 00398 MUTEX_ENTER(&rx_atomic_mutex); 00399 atomic->var--; 00400 retval = atomic->var; 00401 MUTEX_EXIT(&rx_atomic_mutex); 00402 return retval; 00403 } 00404 00405 00406 static_inline void 00407 rx_atomic_sub(rx_atomic_t *atomic, int change) { 00408 MUTEX_ENTER(&rx_atomic_mutex); 00409 atomic->var -= change; 00410 MUTEX_EXIT(&rx_atomic_mutex); 00411 } 00412 00413 #endif 00414 00415 #endif