1170222Sdougb/* 2234010Sdougb * Copyright (C) 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3170222Sdougb * 4174187Sdougb * Permission to use, copy, modify, and/or distribute this software for any 5170222Sdougb * purpose with or without fee is hereby granted, provided that the above 6170222Sdougb * copyright notice and this permission notice appear in all copies. 7170222Sdougb * 8170222Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9170222Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10170222Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11170222Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12170222Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13170222Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14170222Sdougb * PERFORMANCE OF THIS SOFTWARE. 15170222Sdougb */ 16170222Sdougb 17234010Sdougb/* $Id$ */ 18170222Sdougb 19170222Sdougb#ifndef ISC_ATOMIC_H 20170222Sdougb#define ISC_ATOMIC_H 1 21170222Sdougb 22170222Sdougb#include <isc/platform.h> 23170222Sdougb#include <isc/types.h> 24170222Sdougb 25170222Sdougb/*!\file 26170222Sdougb * static inline isc_int32_t 27170222Sdougb * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val); 28170222Sdougb * 29170222Sdougb * This routine atomically increments the value stored in 'p' by 'val', and 30170222Sdougb * returns the previous value. 31170222Sdougb * 32170222Sdougb * static inline void 33170222Sdougb * isc_atomic_store(void *p, isc_int32_t val); 34170222Sdougb * 35170222Sdougb * This routine atomically stores the value 'val' in 'p'. 36170222Sdougb * 37170222Sdougb * static inline isc_int32_t 38170222Sdougb * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val); 39170222Sdougb * 40170222Sdougb * This routine atomically replaces the value in 'p' with 'val', if the 41170222Sdougb * original value is equal to 'cmpval'. The original value is returned in any 42170222Sdougb * case. 43170222Sdougb */ 44170222Sdougb 45170222Sdougb#if defined(_AIX) 46170222Sdougb 47170222Sdougb#include <sys/atomic_op.h> 48170222Sdougb 49170222Sdougb#define isc_atomic_store(p, v) _clear_lock(p, v) 50170222Sdougb 51170222Sdougb#ifdef __GNUC__ 52204619Sdougbstatic inline isc_int32_t 53204619Sdougb#else 54204619Sdougbstatic isc_int32_t 55204619Sdougb#endif 56204619Sdougbisc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 57204619Sdougb int ret; 58204619Sdougb 59204619Sdougb#ifdef __GNUC__ 60204619Sdougb asm("ics"); 61204619Sdougb#else 62204619Sdougb __isync(); 63204619Sdougb#endif 64204619Sdougb 65204619Sdougb ret = fetch_and_add((atomic_p)p, (int)val); 66204619Sdougb 67204619Sdougb#ifdef __GNUC__ 68204619Sdougb asm("ics"); 69204619Sdougb#else 70204619Sdougb __isync(); 71204619Sdougb#endif 72204619Sdougb 73204619Sdougb return (ret); 74204619Sdougb} 75204619Sdougb 76204619Sdougb#ifdef __GNUC__ 77170222Sdougbstatic inline int 78170222Sdougb#else 79170222Sdougbstatic int 80170222Sdougb#endif 81170222Sdougbisc_atomic_cmpxchg(atomic_p p, int old, int new) { 82204619Sdougb int orig = old; 83170222Sdougb 84170222Sdougb#ifdef __GNUC__ 85204619Sdougb asm("ics"); 86170222Sdougb#else 87204619Sdougb __isync(); 88170222Sdougb#endif 89204619Sdougb if (compare_and_swap(p, &orig, new)) 90204619Sdougb orig = old; 91204619Sdougb 92204619Sdougb#ifdef __GNUC__ 93204619Sdougb asm("ics"); 94204619Sdougb#else 95204619Sdougb __isync(); 96204619Sdougb#endif 97204619Sdougb 98204619Sdougb return (orig); 99170222Sdougb} 100170222Sdougb 101170222Sdougb#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM) 102170222Sdougbstatic inline isc_int32_t 103170222Sdougbisc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 104170222Sdougb isc_int32_t orig; 105170222Sdougb 106170222Sdougb __asm__ volatile ( 107170222Sdougb#ifdef ISC_PLATFORM_USEMACASM 108170222Sdougb "1:" 109170222Sdougb "lwarx r6, 0, %1\n" 110204619Sdougb "mr %0, r6\n" 111170222Sdougb "add r6, r6, %2\n" 112170222Sdougb "stwcx. r6, 0, %1\n" 113225361Sdougb "bne- 1b\n" 114225361Sdougb "sync" 115170222Sdougb#else 116170222Sdougb "1:" 117170222Sdougb "lwarx 6, 0, %1\n" 118204619Sdougb "mr %0, 6\n" 119170222Sdougb "add 6, 6, %2\n" 120170222Sdougb "stwcx. 6, 0, %1\n" 121225361Sdougb "bne- 1b\n" 122225361Sdougb "sync" 123170222Sdougb#endif 124170222Sdougb : "=&r"(orig) 125170222Sdougb : "r"(p), "r"(val) 126170222Sdougb : "r6", "memory" 127170222Sdougb ); 128170222Sdougb 129170222Sdougb return (orig); 130170222Sdougb} 131170222Sdougb 132170222Sdougbstatic inline void 133170222Sdougbisc_atomic_store(void *p, isc_int32_t val) { 134170222Sdougb __asm__ volatile ( 135170222Sdougb#ifdef ISC_PLATFORM_USEMACASM 136170222Sdougb "1:" 137170222Sdougb "lwarx r6, 0, %0\n" 138170222Sdougb "lwz r6, %1\n" 139170222Sdougb "stwcx. r6, 0, %0\n" 140225361Sdougb "bne- 1b\n" 141225361Sdougb "sync" 142170222Sdougb#else 143170222Sdougb "1:" 144170222Sdougb "lwarx 6, 0, %0\n" 145170222Sdougb "lwz 6, %1\n" 146170222Sdougb "stwcx. 6, 0, %0\n" 147225361Sdougb "bne- 1b\n" 148225361Sdougb "sync" 149170222Sdougb#endif 150170222Sdougb : 151170222Sdougb : "r"(p), "m"(val) 152170222Sdougb : "r6", "memory" 153170222Sdougb ); 154170222Sdougb} 155170222Sdougb 156170222Sdougbstatic inline isc_int32_t 157170222Sdougbisc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { 158170222Sdougb isc_int32_t orig; 159170222Sdougb 160170222Sdougb __asm__ volatile ( 161170222Sdougb#ifdef ISC_PLATFORM_USEMACASM 162170222Sdougb "1:" 163170222Sdougb "lwarx r6, 0, %1\n" 164170222Sdougb "mr %0,r6\n" 165170222Sdougb "cmpw r6, %2\n" 166170222Sdougb "bne 2f\n" 167170222Sdougb "mr r6, %3\n" 168170222Sdougb "stwcx. r6, 0, %1\n" 169170222Sdougb "bne- 1b\n" 170225361Sdougb "2:\n" 171225361Sdougb "sync" 172170222Sdougb#else 173170222Sdougb "1:" 174170222Sdougb "lwarx 6, 0, %1\n" 175170222Sdougb "mr %0,6\n" 176170222Sdougb "cmpw 6, %2\n" 177170222Sdougb "bne 2f\n" 178170222Sdougb "mr 6, %3\n" 179170222Sdougb "stwcx. 6, 0, %1\n" 180170222Sdougb "bne- 1b\n" 181225361Sdougb "2:\n" 182225361Sdougb "sync" 183170222Sdougb#endif 184170222Sdougb : "=&r" (orig) 185170222Sdougb : "r"(p), "r"(cmpval), "r"(val) 186170222Sdougb : "r6", "memory" 187170222Sdougb ); 188170222Sdougb 189170222Sdougb return (orig); 190170222Sdougb} 191170222Sdougb 192170222Sdougb#else 193170222Sdougb 194170222Sdougb#error "unsupported compiler. disable atomic ops by --disable-atomic" 195170222Sdougb 196170222Sdougb#endif 197170222Sdougb#endif /* ISC_ATOMIC_H */ 198