OpenAFS
OpenAFS distributed network file system
/cygdrive/c/src/openafs/openafs.git/repo/src/rx/rx_atomic.h
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
 All Data Structures Files Functions Variables