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