1290001Sglebius/* 2290001Sglebius * Copyright (C) 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3290001Sglebius * 4290001Sglebius * Permission to use, copy, modify, and/or distribute this software for any 5290001Sglebius * purpose with or without fee is hereby granted, provided that the above 6290001Sglebius * copyright notice and this permission notice appear in all copies. 7290001Sglebius * 8290001Sglebius * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9290001Sglebius * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10290001Sglebius * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11290001Sglebius * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12290001Sglebius * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13290001Sglebius * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14290001Sglebius * PERFORMANCE OF THIS SOFTWARE. 15290001Sglebius */ 16290001Sglebius 17290001Sglebius/* $Id$ */ 18290001Sglebius 19290001Sglebius#ifndef ISC_ATOMIC_H 20290001Sglebius#define ISC_ATOMIC_H 1 21290001Sglebius 22290001Sglebius#include <isc/platform.h> 23290001Sglebius#include <isc/types.h> 24290001Sglebius 25290001Sglebius/*!\file 26290001Sglebius * static inline isc_int32_t 27290001Sglebius * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val); 28290001Sglebius * 29290001Sglebius * This routine atomically increments the value stored in 'p' by 'val', and 30290001Sglebius * returns the previous value. 31290001Sglebius * 32290001Sglebius * static inline void 33290001Sglebius * isc_atomic_store(void *p, isc_int32_t val); 34290001Sglebius * 35290001Sglebius * This routine atomically stores the value 'val' in 'p'. 36290001Sglebius * 37290001Sglebius * static inline isc_int32_t 38290001Sglebius * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val); 39290001Sglebius * 40290001Sglebius * This routine atomically replaces the value in 'p' with 'val', if the 41290001Sglebius * original value is equal to 'cmpval'. The original value is returned in any 42290001Sglebius * case. 43290001Sglebius */ 44290001Sglebius 45290001Sglebius#if defined(_AIX) 46290001Sglebius 47290001Sglebius#include <sys/atomic_op.h> 48290001Sglebius 49290001Sglebius#define isc_atomic_store(p, v) _clear_lock(p, v) 50290001Sglebius 51290001Sglebius#ifdef __GNUC__ 52290001Sglebiusstatic inline isc_int32_t 53290001Sglebius#else 54290001Sglebiusstatic isc_int32_t 55290001Sglebius#endif 56290001Sglebiusisc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 57290001Sglebius int ret; 58290001Sglebius 59290001Sglebius#ifdef __GNUC__ 60290001Sglebius asm("ics"); 61290001Sglebius#else 62290001Sglebius __isync(); 63290001Sglebius#endif 64290001Sglebius 65290001Sglebius ret = fetch_and_add((atomic_p)p, (int)val); 66290001Sglebius 67290001Sglebius#ifdef __GNUC__ 68290001Sglebius asm("ics"); 69290001Sglebius#else 70290001Sglebius __isync(); 71290001Sglebius#endif 72290001Sglebius 73290001Sglebius return (ret); 74290001Sglebius} 75290001Sglebius 76290001Sglebius#ifdef __GNUC__ 77290001Sglebiusstatic inline int 78290001Sglebius#else 79290001Sglebiusstatic int 80290001Sglebius#endif 81290001Sglebiusisc_atomic_cmpxchg(atomic_p p, int old, int new) { 82290001Sglebius int orig = old; 83290001Sglebius 84290001Sglebius#ifdef __GNUC__ 85290001Sglebius asm("ics"); 86290001Sglebius#else 87290001Sglebius __isync(); 88290001Sglebius#endif 89290001Sglebius if (compare_and_swap(p, &orig, new)) 90290001Sglebius orig = old; 91290001Sglebius 92290001Sglebius#ifdef __GNUC__ 93290001Sglebius asm("ics"); 94290001Sglebius#else 95290001Sglebius __isync(); 96290001Sglebius#endif 97290001Sglebius 98290001Sglebius return (orig); 99290001Sglebius} 100290001Sglebius 101290001Sglebius#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM) 102290001Sglebiusstatic inline isc_int32_t 103290001Sglebiusisc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 104290001Sglebius isc_int32_t orig; 105290001Sglebius 106290001Sglebius __asm__ volatile ( 107290001Sglebius#ifdef ISC_PLATFORM_USEMACASM 108290001Sglebius "1:" 109290001Sglebius "lwarx r6, 0, %1\n" 110290001Sglebius "mr %0, r6\n" 111290001Sglebius "add r6, r6, %2\n" 112290001Sglebius "stwcx. r6, 0, %1\n" 113290001Sglebius "bne- 1b\n" 114290001Sglebius "sync" 115290001Sglebius#else 116290001Sglebius "1:" 117290001Sglebius "lwarx 6, 0, %1\n" 118290001Sglebius "mr %0, 6\n" 119290001Sglebius "add 6, 6, %2\n" 120290001Sglebius "stwcx. 6, 0, %1\n" 121290001Sglebius "bne- 1b\n" 122290001Sglebius "sync" 123290001Sglebius#endif 124290001Sglebius : "=&r"(orig) 125290001Sglebius : "r"(p), "r"(val) 126290001Sglebius : "r6", "memory" 127290001Sglebius ); 128290001Sglebius 129290001Sglebius return (orig); 130290001Sglebius} 131290001Sglebius 132290001Sglebiusstatic inline void 133290001Sglebiusisc_atomic_store(void *p, isc_int32_t val) { 134290001Sglebius __asm__ volatile ( 135290001Sglebius#ifdef ISC_PLATFORM_USEMACASM 136290001Sglebius "1:" 137290001Sglebius "lwarx r6, 0, %0\n" 138290001Sglebius "lwz r6, %1\n" 139290001Sglebius "stwcx. r6, 0, %0\n" 140290001Sglebius "bne- 1b\n" 141290001Sglebius "sync" 142290001Sglebius#else 143290001Sglebius "1:" 144290001Sglebius "lwarx 6, 0, %0\n" 145290001Sglebius "lwz 6, %1\n" 146290001Sglebius "stwcx. 6, 0, %0\n" 147290001Sglebius "bne- 1b\n" 148290001Sglebius "sync" 149290001Sglebius#endif 150290001Sglebius : 151290001Sglebius : "r"(p), "m"(val) 152290001Sglebius : "r6", "memory" 153290001Sglebius ); 154290001Sglebius} 155290001Sglebius 156290001Sglebiusstatic inline isc_int32_t 157290001Sglebiusisc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { 158290001Sglebius isc_int32_t orig; 159290001Sglebius 160290001Sglebius __asm__ volatile ( 161290001Sglebius#ifdef ISC_PLATFORM_USEMACASM 162290001Sglebius "1:" 163290001Sglebius "lwarx r6, 0, %1\n" 164290001Sglebius "mr %0,r6\n" 165290001Sglebius "cmpw r6, %2\n" 166290001Sglebius "bne 2f\n" 167290001Sglebius "mr r6, %3\n" 168290001Sglebius "stwcx. r6, 0, %1\n" 169290001Sglebius "bne- 1b\n" 170290001Sglebius "2:\n" 171290001Sglebius "sync" 172290001Sglebius#else 173290001Sglebius "1:" 174290001Sglebius "lwarx 6, 0, %1\n" 175290001Sglebius "mr %0,6\n" 176290001Sglebius "cmpw 6, %2\n" 177290001Sglebius "bne 2f\n" 178290001Sglebius "mr 6, %3\n" 179290001Sglebius "stwcx. 6, 0, %1\n" 180290001Sglebius "bne- 1b\n" 181290001Sglebius "2:\n" 182290001Sglebius "sync" 183290001Sglebius#endif 184290001Sglebius : "=&r" (orig) 185290001Sglebius : "r"(p), "r"(cmpval), "r"(val) 186290001Sglebius : "r6", "memory" 187290001Sglebius ); 188290001Sglebius 189290001Sglebius return (orig); 190290001Sglebius} 191290001Sglebius 192290001Sglebius#else 193290001Sglebius 194290001Sglebius#error "unsupported compiler. disable atomic ops by --disable-atomic" 195290001Sglebius 196290001Sglebius#endif 197290001Sglebius#endif /* ISC_ATOMIC_H */ 198