atomic.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 #ifndef ISC_ATOMIC_H
00020 #define ISC_ATOMIC_H 1
00021 
00022 #include <isc/platform.h>
00023 #include <isc/types.h>
00024 
00025 /*!\file
00026  * static inline isc_int32_t
00027  * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val);
00028  *
00029  * This routine atomically increments the value stored in 'p' by 'val', and
00030  * returns the previous value.
00031  *
00032  * static inline void
00033  * isc_atomic_store(void *p, isc_int32_t val);
00034  *
00035  * This routine atomically stores the value 'val' in 'p'.
00036  *
00037  * static inline isc_int32_t
00038  * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val);
00039  *
00040  * This routine atomically replaces the value in 'p' with 'val', if the
00041  * original value is equal to 'cmpval'.  The original value is returned in any
00042  * case.
00043  */
00044 
00045 #if defined(_AIX)
00046 
00047 #include <sys/atomic_op.h>
00048 
00049 #define isc_atomic_store(p, v) _clear_lock(p, v)
00050 
00051 #ifdef __GNUC__
00052 static inline isc_int32_t
00053 #else
00054 static isc_int32_t
00055 #endif
00056 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
00057         int ret;
00058 
00059 #ifdef __GNUC__
00060         asm("ics");
00061 #else
00062          __isync();
00063 #endif
00064 
00065         ret = fetch_and_add((atomic_p)p, (int)val);
00066 
00067 #ifdef __GNUC__
00068         asm("ics");
00069 #else
00070          __isync();
00071 #endif
00072 
00073          return (ret);
00074 }
00075 
00076 #ifdef __GNUC__
00077 static inline int
00078 #else
00079 static int
00080 #endif
00081 isc_atomic_cmpxchg(atomic_p p, int old, int new) {
00082         int orig = old;
00083 
00084 #ifdef __GNUC__
00085         asm("ics");
00086 #else
00087          __isync();
00088 #endif
00089         if (compare_and_swap(p, &orig, new))
00090                 orig = old;
00091 
00092 #ifdef __GNUC__
00093         asm("ics");
00094 #else
00095          __isync();
00096 #endif
00097 
00098         return (orig);
00099 }
00100 
00101 #elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
00102 static inline isc_int32_t
00103 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
00104         isc_int32_t orig;
00105 
00106         __asm__ volatile (
00107 #ifdef ISC_PLATFORM_USEMACASM
00108                 "1:"
00109                 "lwarx r6, 0, %1\n"
00110                 "mr %0, r6\n"
00111                 "add r6, r6, %2\n"
00112                 "stwcx. r6, 0, %1\n"
00113                 "bne- 1b\n"
00114                 "sync"
00115 #else
00116                 "1:"
00117                 "lwarx 6, 0, %1\n"
00118                 "mr %0, 6\n"
00119                 "add 6, 6, %2\n"
00120                 "stwcx. 6, 0, %1\n"
00121                 "bne- 1b\n"
00122                 "sync"
00123 #endif
00124                 : "=&r"(orig)
00125                 : "r"(p), "r"(val)
00126                 : "r6", "memory"
00127                 );
00128 
00129         return (orig);
00130 }
00131 
00132 static inline void
00133 isc_atomic_store(void *p, isc_int32_t val) {
00134         __asm__ volatile (
00135 #ifdef ISC_PLATFORM_USEMACASM
00136                 "1:"
00137                 "lwarx r6, 0, %0\n"
00138                 "lwz r6, %1\n"
00139                 "stwcx. r6, 0, %0\n"
00140                 "bne- 1b\n"
00141                 "sync"
00142 #else
00143                 "1:"
00144                 "lwarx 6, 0, %0\n"
00145                 "lwz 6, %1\n"
00146                 "stwcx. 6, 0, %0\n"
00147                 "bne- 1b\n"
00148                 "sync"
00149 #endif
00150                 :
00151                 : "r"(p), "m"(val)
00152                 : "r6", "memory"
00153                 );
00154 }
00155 
00156 static inline isc_int32_t
00157 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
00158         isc_int32_t orig;
00159 
00160         __asm__ volatile (
00161 #ifdef ISC_PLATFORM_USEMACASM
00162                 "1:"
00163                 "lwarx r6, 0, %1\n"
00164                 "mr %0,r6\n"
00165                 "cmpw r6, %2\n"
00166                 "bne 2f\n"
00167                 "mr r6, %3\n"
00168                 "stwcx. r6, 0, %1\n"
00169                 "bne- 1b\n"
00170                 "2:\n"
00171                 "sync"
00172 #else
00173                 "1:"
00174                 "lwarx 6, 0, %1\n"
00175                 "mr %0,6\n"
00176                 "cmpw 6, %2\n"
00177                 "bne 2f\n"
00178                 "mr 6, %3\n"
00179                 "stwcx. 6, 0, %1\n"
00180                 "bne- 1b\n"
00181                 "2:\n"
00182                 "sync"
00183 #endif
00184                 : "=&r" (orig)
00185                 : "r"(p), "r"(cmpval), "r"(val)
00186                 : "r6", "memory"
00187                 );
00188 
00189         return (orig);
00190 }
00191 
00192 #else
00193 
00194 #error "unsupported compiler.  disable atomic ops by --disable-atomic"
00195 
00196 #endif
00197 #endif /* ISC_ATOMIC_H */

Generated on Tue Apr 28 17:41:03 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha