1 /* $NetBSD: atomic.h,v 1.7 2014/12/10 04:38:00 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* Id */ 20 21 #ifndef ISC_ATOMIC_H 22 #define ISC_ATOMIC_H 1 23 24 #include <isc/platform.h> 25 #include <isc/types.h> 26 27 /*!\file 28 * static inline isc_int32_t 29 * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val); 30 * 31 * This routine atomically increments the value stored in 'p' by 'val', and 32 * returns the previous value. 33 * 34 * static inline void 35 * isc_atomic_store(void *p, isc_int32_t val); 36 * 37 * This routine atomically stores the value 'val' in 'p'. 38 * 39 * static inline isc_int32_t 40 * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val); 41 * 42 * This routine atomically replaces the value in 'p' with 'val', if the 43 * original value is equal to 'cmpval'. The original value is returned in any 44 * case. 45 */ 46 47 #if defined(_AIX) 48 49 #include <sys/atomic_op.h> 50 51 #define isc_atomic_store(p, v) _clear_lock(p, v) 52 53 #ifdef __GNUC__ 54 static __inline isc_int32_t 55 #else 56 static isc_int32_t 57 #endif 58 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 59 int ret; 60 61 #ifdef __GNUC__ 62 asm("ics"); 63 #else 64 __isync(); 65 #endif 66 67 ret = fetch_and_add((atomic_p)p, (int)val); 68 69 #ifdef __GNUC__ 70 asm("ics"); 71 #else 72 __isync(); 73 #endif 74 75 return (ret); 76 } 77 78 #ifdef __GNUC__ 79 static __inline int 80 #else 81 static int 82 #endif 83 isc_atomic_cmpxchg(atomic_p p, int old, int new) { 84 int orig = old; 85 86 #ifdef __GNUC__ 87 asm("ics"); 88 #else 89 __isync(); 90 #endif 91 if (compare_and_swap(p, &orig, new)) 92 orig = old; 93 94 #ifdef __GNUC__ 95 asm("ics"); 96 #else 97 __isync(); 98 #endif 99 100 return (orig); 101 } 102 103 #elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM) 104 static __inline isc_int32_t 105 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 106 isc_int32_t orig; 107 108 __asm__ volatile ( 109 #ifdef ISC_PLATFORM_USEMACASM 110 "1:" 111 "lwarx r6, 0, %1\n" 112 "mr %0, r6\n" 113 "add r6, r6, %2\n" 114 "stwcx. r6, 0, %1\n" 115 "bne- 1b\n" 116 "sync" 117 #else 118 "1:" 119 "lwarx 6, 0, %1\n" 120 "mr %0, 6\n" 121 "add 6, 6, %2\n" 122 "stwcx. 6, 0, %1\n" 123 "bne- 1b\n" 124 "sync" 125 #endif 126 : "=&r"(orig) 127 : "r"(p), "r"(val) 128 : "r6", "memory" 129 ); 130 131 return (orig); 132 } 133 134 static __inline void 135 isc_atomic_store(void *p, isc_int32_t val) { 136 __asm__ volatile ( 137 #ifdef ISC_PLATFORM_USEMACASM 138 "1:" 139 "lwarx r6, 0, %0\n" 140 "lwz r6, %1\n" 141 "stwcx. r6, 0, %0\n" 142 "bne- 1b\n" 143 "sync" 144 #else 145 "1:" 146 "lwarx 6, 0, %0\n" 147 "lwz 6, %1\n" 148 "stwcx. 6, 0, %0\n" 149 "bne- 1b\n" 150 "sync" 151 #endif 152 : 153 : "r"(p), "m"(val) 154 : "r6", "memory" 155 ); 156 } 157 158 static __inline isc_int32_t 159 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { 160 isc_int32_t orig; 161 162 __asm__ volatile ( 163 #ifdef ISC_PLATFORM_USEMACASM 164 "1:" 165 "lwarx r6, 0, %1\n" 166 "mr %0,r6\n" 167 "cmpw r6, %2\n" 168 "bne 2f\n" 169 "mr r6, %3\n" 170 "stwcx. r6, 0, %1\n" 171 "bne- 1b\n" 172 "2:\n" 173 "sync" 174 #else 175 "1:" 176 "lwarx 6, 0, %1\n" 177 "mr %0,6\n" 178 "cmpw 6, %2\n" 179 "bne 2f\n" 180 "mr 6, %3\n" 181 "stwcx. 6, 0, %1\n" 182 "bne- 1b\n" 183 "2:\n" 184 "sync" 185 #endif 186 : "=&r" (orig) 187 : "r"(p), "r"(cmpval), "r"(val) 188 : "r6", "memory" 189 ); 190 191 return (orig); 192 } 193 194 #else 195 196 #error "unsupported compiler. disable atomic ops by --disable-atomic" 197 198 #endif 199 #endif /* ISC_ATOMIC_H */ 200