1 /* $NetBSD: atomic.h,v 1.7 2014/12/10 04:38:00 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2005, 2007, 2009 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: atomic.h,v 1.7 2009/04/08 06:48:23 tbox Exp */ 20 21 /* 22 * This code was written based on FreeBSD's kernel source whose copyright 23 * follows: 24 */ 25 26 /*- 27 * Copyright (c) 1998 Doug Rabson 28 * All rights reserved. 29 * 30 * Redistribution and use in source and binary forms, with or without 31 * modification, are permitted provided that the following conditions 32 * are met: 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in the 37 * documentation and/or other materials provided with the distribution. 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 42 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 49 * SUCH DAMAGE. 50 * 51 * $FreeBSD: src/sys/alpha/include/atomic.h,v 1.18.6.1 2004/09/13 21:52:04 wilko Exp $ 52 */ 53 54 #ifndef ISC_ATOMIC_H 55 #define ISC_ATOMIC_H 1 56 57 #include <isc/platform.h> 58 #include <isc/types.h> 59 60 #ifdef ISC_PLATFORM_USEOSFASM 61 #include <c_asm.h> 62 63 #pragma intrinsic(asm) 64 65 /* 66 * This routine atomically increments the value stored in 'p' by 'val', and 67 * returns the previous value. Memory access ordering around this function 68 * can be critical, so we add explicit memory block instructions at the 69 * beginning and the end of it (same for other functions). 70 */ 71 static __inline isc_int32_t 72 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 73 return (asm("mb;" 74 "1:" 75 "ldl_l %t0, 0(%a0);" /* load old value */ 76 "mov %t0, %v0;" /* copy the old value */ 77 "addl %t0, %a1, %t0;" /* calculate new value */ 78 "stl_c %t0, 0(%a0);" /* attempt to store */ 79 "beq %t0, 1b;" /* spin if failed */ 80 "mb;", 81 p, val)); 82 } 83 84 /* 85 * This routine atomically stores the value 'val' in 'p'. 86 */ 87 static __inline void 88 isc_atomic_store(isc_int32_t *p, isc_int32_t val) { 89 (void)asm("mb;" 90 "1:" 91 "ldl_l %t0, 0(%a0);" /* load old value */ 92 "mov %a1, %t0;" /* value to store */ 93 "stl_c %t0, 0(%a0);" /* attempt to store */ 94 "beq %t0, 1b;" /* spin if failed */ 95 "mb;", 96 p, val); 97 } 98 99 /* 100 * This routine atomically replaces the value in 'p' with 'val', if the 101 * original value is equal to 'cmpval'. The original value is returned in any 102 * case. 103 */ 104 static __inline isc_int32_t 105 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { 106 107 return(asm("mb;" 108 "1:" 109 "ldl_l %t0, 0(%a0);" /* load old value */ 110 "mov %t0, %v0;" /* copy the old value */ 111 "cmpeq %t0, %a1, %t0;" /* compare */ 112 "beq %t0, 2f;" /* exit if not equal */ 113 "mov %a2, %t0;" /* value to store */ 114 "stl_c %t0, 0(%a0);" /* attempt to store */ 115 "beq %t0, 1b;" /* if it failed, spin */ 116 "2:" 117 "mb;", 118 p, cmpval, val)); 119 } 120 #elif defined (ISC_PLATFORM_USEGCCASM) 121 static __inline isc_int32_t 122 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { 123 isc_int32_t temp, prev; 124 125 __asm__ volatile( 126 "mb;" 127 "1:" 128 "ldl_l %0, %1;" /* load old value */ 129 "mov %0, %2;" /* copy the old value */ 130 "addl %0, %3, %0;" /* calculate new value */ 131 "stl_c %0, %1;" /* attempt to store */ 132 "beq %0, 1b;" /* spin if failed */ 133 "mb;" 134 : "=&r"(temp), "+m"(*p), "=&r"(prev) 135 : "r"(val) 136 : "memory"); 137 138 return (prev); 139 } 140 141 static __inline void 142 isc_atomic_store(isc_int32_t *p, isc_int32_t val) { 143 isc_int32_t temp; 144 145 __asm__ volatile( 146 "mb;" 147 "1:" 148 "ldl_l %0, %1;" /* load old value */ 149 "mov %2, %0;" /* value to store */ 150 "stl_c %0, %1;" /* attempt to store */ 151 "beq %0, 1b;" /* if it failed, spin */ 152 "mb;" 153 : "=&r"(temp), "+m"(*p) 154 : "r"(val) 155 : "memory"); 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 temp, prev; 161 162 __asm__ volatile( 163 "mb;" 164 "1:" 165 "ldl_l %0, %1;" /* load old value */ 166 "mov %0, %2;" /* copy the old value */ 167 "cmpeq %0, %3, %0;" /* compare */ 168 "beq %0, 2f;" /* exit if not equal */ 169 "mov %4, %0;" /* value to store */ 170 "stl_c %0, %1;" /* attempt to store */ 171 "beq %0, 1b;" /* if it failed, spin */ 172 "2:" 173 "mb;" 174 : "=&r"(temp), "+m"(*p), "=&r"(prev) 175 : "r"(cmpval), "r"(val) 176 : "memory"); 177 178 return (prev); 179 } 180 #else 181 182 #error "unsupported compiler. disable atomic ops by --disable-atomic" 183 184 #endif 185 186 #endif /* ISC_ATOMIC_H */ 187