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