00001 /* 00002 * Copyright (C) 2005, 2007, 2013 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: atomic.h,v 1.5 2007/06/19 23:47:18 tbox Exp $ */ 00018 00019 /* 00020 * This code was written based on FreeBSD's kernel source whose copyright 00021 * follows: 00022 */ 00023 00024 /*- 00025 * Copyright (c) 1998 Doug Rabson. 00026 * Copyright (c) 2001 Jake Burkholder. 00027 * All rights reserved. 00028 * 00029 * Redistribution and use in source and binary forms, with or without 00030 * modification, are permitted provided that the following conditions 00031 * are met: 00032 * 1. Redistributions of source code must retain the above copyright 00033 * notice, this list of conditions and the following disclaimer. 00034 * 2. Redistributions in binary form must reproduce the above copyright 00035 * notice, this list of conditions and the following disclaimer in the 00036 * documentation and/or other materials provided with the distribution. 00037 * 00038 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 00039 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00040 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00041 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 00042 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00043 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00044 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00045 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00046 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00047 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00048 * SUCH DAMAGE. 00049 * 00050 * from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11 00051 * $FreeBSD: src/sys/sparc64/include/atomic.h,v 1.8 2004/05/22 00:52:16 marius Exp $ 00052 */ 00053 00054 #ifndef ISC_ATOMIC_H 00055 #define ISC_ATOMIC_H 1 00056 00057 #include <isc/platform.h> 00058 #include <isc/types.h> 00059 00060 #define ASI_P 0x80 /* Primary Address Space Identifier */ 00061 00062 #ifdef ISC_PLATFORM_USEGCCASM 00063 00064 /* 00065 * This routine atomically increments the value stored in 'p' by 'val', and 00066 * returns the previous value. 00067 */ 00068 static inline isc_int32_t 00069 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 00070 isc_int32_t prev, swapped; 00071 00072 for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) { 00073 swapped = prev + val; 00074 __asm__ volatile( 00075 "casa [%2] %3, %4, %0" 00076 : "+r"(swapped), "=m"(*p) 00077 : "r"(p), "n"(ASI_P), "r"(prev), "m"(*p)); 00078 if (swapped == prev) 00079 break; 00080 } 00081 00082 return (prev); 00083 } 00084 00085 /* 00086 * This routine atomically stores the value 'val' in 'p'. 00087 */ 00088 static inline void 00089 isc_atomic_store(isc_int32_t *p, isc_int32_t val) { 00090 isc_int32_t prev, swapped; 00091 00092 for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) { 00093 swapped = val; 00094 __asm__ volatile( 00095 "casa [%2] %3, %4, %0" 00096 : "+r"(swapped), "=m"(*p) 00097 : "r"(p), "n"(ASI_P), "r"(prev), "m"(*p)); 00098 if (swapped == prev) 00099 break; 00100 } 00101 } 00102 00103 /* 00104 * This routine atomically replaces the value in 'p' with 'val', if the 00105 * original value is equal to 'cmpval'. The original value is returned in any 00106 * case. 00107 */ 00108 static inline isc_int32_t 00109 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { 00110 isc_int32_t temp = val; 00111 00112 __asm__ volatile( 00113 "casa [%2] %3, %4, %0" 00114 : "+r"(temp), "=m"(*p) 00115 : "r"(p), "n"(ASI_P), "r"(cmpval), "m"(*p)); 00116 00117 return (temp); 00118 } 00119 00120 #else /* ISC_PLATFORM_USEGCCASM */ 00121 00122 #error "unsupported compiler. disable atomic ops by --disable-atomic" 00123 00124 #endif /* ISC_PLATFORM_USEGCCASM */ 00125 00126 #endif /* ISC_ATOMIC_H */