1069e9bc1SDoug Rabson /*- 2069e9bc1SDoug Rabson * Copyright (c) 1998 Doug Rabson 3069e9bc1SDoug Rabson * All rights reserved. 4069e9bc1SDoug Rabson * 5069e9bc1SDoug Rabson * Redistribution and use in source and binary forms, with or without 6069e9bc1SDoug Rabson * modification, are permitted provided that the following conditions 7069e9bc1SDoug Rabson * are met: 8069e9bc1SDoug Rabson * 1. Redistributions of source code must retain the above copyright 9069e9bc1SDoug Rabson * notice, this list of conditions and the following disclaimer. 10069e9bc1SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 11069e9bc1SDoug Rabson * notice, this list of conditions and the following disclaimer in the 12069e9bc1SDoug Rabson * documentation and/or other materials provided with the distribution. 13069e9bc1SDoug Rabson * 14069e9bc1SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15069e9bc1SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16069e9bc1SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17069e9bc1SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18069e9bc1SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19069e9bc1SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20069e9bc1SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21069e9bc1SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22069e9bc1SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23069e9bc1SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24069e9bc1SDoug Rabson * SUCH DAMAGE. 25069e9bc1SDoug Rabson * 26c3aac50fSPeter Wemm * $FreeBSD$ 27069e9bc1SDoug Rabson */ 28069e9bc1SDoug Rabson #ifndef _MACHINE_ATOMIC_H_ 29069e9bc1SDoug Rabson #define _MACHINE_ATOMIC_H_ 30069e9bc1SDoug Rabson 31069e9bc1SDoug Rabson /* 32069e9bc1SDoug Rabson * Various simple arithmetic on memory which is atomic in the presence 3347b8bc92SAlan Cox * of interrupts and multiple processors. 34069e9bc1SDoug Rabson * 3547b8bc92SAlan Cox * atomic_set_char(P, V) (*(u_char*)(P) |= (V)) 3647b8bc92SAlan Cox * atomic_clear_char(P, V) (*(u_char*)(P) &= ~(V)) 3747b8bc92SAlan Cox * atomic_add_char(P, V) (*(u_char*)(P) += (V)) 3847b8bc92SAlan Cox * atomic_subtract_char(P, V) (*(u_char*)(P) -= (V)) 3947b8bc92SAlan Cox * 4047b8bc92SAlan Cox * atomic_set_short(P, V) (*(u_short*)(P) |= (V)) 4147b8bc92SAlan Cox * atomic_clear_short(P, V) (*(u_short*)(P) &= ~(V)) 4247b8bc92SAlan Cox * atomic_add_short(P, V) (*(u_short*)(P) += (V)) 4347b8bc92SAlan Cox * atomic_subtract_short(P, V) (*(u_short*)(P) -= (V)) 4447b8bc92SAlan Cox * 4547b8bc92SAlan Cox * atomic_set_int(P, V) (*(u_int*)(P) |= (V)) 4647b8bc92SAlan Cox * atomic_clear_int(P, V) (*(u_int*)(P) &= ~(V)) 4747b8bc92SAlan Cox * atomic_add_int(P, V) (*(u_int*)(P) += (V)) 4847b8bc92SAlan Cox * atomic_subtract_int(P, V) (*(u_int*)(P) -= (V)) 49b4645202SJohn Baldwin * atomic_readandclear_int(P) (return *(u_int*)P; *(u_int*)P = 0;) 5047b8bc92SAlan Cox * 5147b8bc92SAlan Cox * atomic_set_long(P, V) (*(u_long*)(P) |= (V)) 5247b8bc92SAlan Cox * atomic_clear_long(P, V) (*(u_long*)(P) &= ~(V)) 5347b8bc92SAlan Cox * atomic_add_long(P, V) (*(u_long*)(P) += (V)) 5447b8bc92SAlan Cox * atomic_subtract_long(P, V) (*(u_long*)(P) -= (V)) 55b4645202SJohn Baldwin * atomic_readandclear_long(P) (return *(u_long*)P; *(u_long*)P = 0;) 56069e9bc1SDoug Rabson */ 57069e9bc1SDoug Rabson 5847b8bc92SAlan Cox /* 5908c40841SAlan Cox * The above functions are expanded inline in the statically-linked 6008c40841SAlan Cox * kernel. Lock prefixes are generated if an SMP kernel is being 6108c40841SAlan Cox * built. 6208c40841SAlan Cox * 6308c40841SAlan Cox * Kernel modules call real functions which are built into the kernel. 6408c40841SAlan Cox * This allows kernel modules to be portable between UP and SMP systems. 6547b8bc92SAlan Cox */ 6608c40841SAlan Cox #if defined(KLD_MODULE) 6708c40841SAlan Cox #define ATOMIC_ASM(NAME, TYPE, OP, V) \ 68b4645202SJohn Baldwin void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); 6908c40841SAlan Cox 70b4645202SJohn Baldwin int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); 71819e370cSPoul-Henning Kamp 7208c40841SAlan Cox #else /* !KLD_MODULE */ 7308c40841SAlan Cox #if defined(SMP) 74819e370cSPoul-Henning Kamp #if defined(LOCORE) 75819e370cSPoul-Henning Kamp #define MPLOCKED lock ; 76819e370cSPoul-Henning Kamp #else 7747b8bc92SAlan Cox #define MPLOCKED "lock ; " 78819e370cSPoul-Henning Kamp #endif 79e58bb1c4SAlan Cox #else 8047b8bc92SAlan Cox #define MPLOCKED 81e58bb1c4SAlan Cox #endif 82069e9bc1SDoug Rabson 8347b8bc92SAlan Cox /* 8447b8bc92SAlan Cox * The assembly is volatilized to demark potential before-and-after side 8547b8bc92SAlan Cox * effects if an interrupt or SMP collision were to occur. 8647b8bc92SAlan Cox */ 87693612ebSPeter Wemm #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 9) 88693612ebSPeter Wemm /* egcs 1.1.2+ version */ 8947b8bc92SAlan Cox #define ATOMIC_ASM(NAME, TYPE, OP, V) \ 9047b8bc92SAlan Cox static __inline void \ 9103e3bc8eSAlan Cox atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 9247b8bc92SAlan Cox { \ 9347b8bc92SAlan Cox __asm __volatile(MPLOCKED OP \ 9403e3bc8eSAlan Cox : "=m" (*p) \ 9503e3bc8eSAlan Cox : "0" (*p), "ir" (V)); \ 9647b8bc92SAlan Cox } 97693612ebSPeter Wemm 98819e370cSPoul-Henning Kamp /* 99819e370cSPoul-Henning Kamp * Atomic compare and set, used by the mutex functions 100819e370cSPoul-Henning Kamp * 101819e370cSPoul-Henning Kamp * if (*dst == exp) *dst = src (all 32 bit words) 102819e370cSPoul-Henning Kamp * 103819e370cSPoul-Henning Kamp * Returns 0 on failure, non-zero on success 104819e370cSPoul-Henning Kamp */ 105819e370cSPoul-Henning Kamp 106819e370cSPoul-Henning Kamp #if defined(I386_CPU) 107819e370cSPoul-Henning Kamp static __inline int 108819e370cSPoul-Henning Kamp atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 109819e370cSPoul-Henning Kamp { 110819e370cSPoul-Henning Kamp int res = exp; 111819e370cSPoul-Henning Kamp 112819e370cSPoul-Henning Kamp __asm __volatile( 113819e370cSPoul-Henning Kamp " pushfl ; " 114819e370cSPoul-Henning Kamp " cli ; " 115819e370cSPoul-Henning Kamp " cmpl %1,%3 ; " 116819e370cSPoul-Henning Kamp " jne 1f ; " 117819e370cSPoul-Henning Kamp " movl %2,%3 ; " 118819e370cSPoul-Henning Kamp "1: " 119819e370cSPoul-Henning Kamp " sete %%al; " 120819e370cSPoul-Henning Kamp " movzbl %%al,%0 ; " 121819e370cSPoul-Henning Kamp " popfl ; " 122819e370cSPoul-Henning Kamp "# atomic_cmpset_int" 123819e370cSPoul-Henning Kamp : "=a" (res) /* 0 (result) */ 124819e370cSPoul-Henning Kamp : "0" (exp), /* 1 */ 125819e370cSPoul-Henning Kamp "r" (src), /* 2 */ 126819e370cSPoul-Henning Kamp "m" (*(dst)) /* 3 */ 127819e370cSPoul-Henning Kamp : "memory"); 128819e370cSPoul-Henning Kamp 129819e370cSPoul-Henning Kamp return (res); 130819e370cSPoul-Henning Kamp } 131819e370cSPoul-Henning Kamp #else /* defined(I386_CPU) */ 132819e370cSPoul-Henning Kamp static __inline int 133819e370cSPoul-Henning Kamp atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 134819e370cSPoul-Henning Kamp { 135819e370cSPoul-Henning Kamp int res = exp; 136819e370cSPoul-Henning Kamp 137819e370cSPoul-Henning Kamp __asm __volatile ( 138819e370cSPoul-Henning Kamp " " MPLOCKED " " 139819e370cSPoul-Henning Kamp " cmpxchgl %2,%3 ; " 140819e370cSPoul-Henning Kamp " setz %%al ; " 141819e370cSPoul-Henning Kamp " movzbl %%al,%0 ; " 142819e370cSPoul-Henning Kamp "1: " 143819e370cSPoul-Henning Kamp "# atomic_cmpset_int" 144819e370cSPoul-Henning Kamp : "=a" (res) /* 0 (result) */ 145819e370cSPoul-Henning Kamp : "0" (exp), /* 1 */ 146819e370cSPoul-Henning Kamp "r" (src), /* 2 */ 147819e370cSPoul-Henning Kamp "m" (*(dst)) /* 3 */ 148819e370cSPoul-Henning Kamp : "memory"); 149819e370cSPoul-Henning Kamp 150819e370cSPoul-Henning Kamp return (res); 151819e370cSPoul-Henning Kamp } 152819e370cSPoul-Henning Kamp #endif /* defined(I386_CPU) */ 153819e370cSPoul-Henning Kamp 154ee8f2f37SJohn Baldwin #define atomic_cmpset_long atomic_cmpset_int 155ccbdd9eeSJohn Baldwin #define atomic_cmpset_acq_int atomic_cmpset_int 156ccbdd9eeSJohn Baldwin #define atomic_cmpset_rel_int atomic_cmpset_int 157ee8f2f37SJohn Baldwin #define atomic_cmpset_acq_long atomic_cmpset_acq_int 158ee8f2f37SJohn Baldwin #define atomic_cmpset_rel_long atomic_cmpset_rel_int 159ccbdd9eeSJohn Baldwin 160693612ebSPeter Wemm #else 161693612ebSPeter Wemm /* gcc <= 2.8 version */ 162693612ebSPeter Wemm #define ATOMIC_ASM(NAME, TYPE, OP, V) \ 163693612ebSPeter Wemm static __inline void \ 164693612ebSPeter Wemm atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 165693612ebSPeter Wemm { \ 166693612ebSPeter Wemm __asm __volatile(MPLOCKED OP \ 167693612ebSPeter Wemm : "=m" (*p) \ 168693612ebSPeter Wemm : "ir" (V)); \ 169ccbdd9eeSJohn Baldwin } \ 170ccbdd9eeSJohn Baldwin \ 171ccbdd9eeSJohn Baldwin 172693612ebSPeter Wemm #endif 17308c40841SAlan Cox #endif /* KLD_MODULE */ 174069e9bc1SDoug Rabson 175b8710473SPeter Wemm #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 9) 176693612ebSPeter Wemm 177693612ebSPeter Wemm /* egcs 1.1.2+ version */ 17825f01030SDavid E. O'Brien ATOMIC_ASM(set, char, "orb %b2,%0", v) 17925f01030SDavid E. O'Brien ATOMIC_ASM(clear, char, "andb %b2,%0", ~v) 18025f01030SDavid E. O'Brien ATOMIC_ASM(add, char, "addb %b2,%0", v) 18125f01030SDavid E. O'Brien ATOMIC_ASM(subtract, char, "subb %b2,%0", v) 182069e9bc1SDoug Rabson 18325f01030SDavid E. O'Brien ATOMIC_ASM(set, short, "orw %w2,%0", v) 18425f01030SDavid E. O'Brien ATOMIC_ASM(clear, short, "andw %w2,%0", ~v) 18525f01030SDavid E. O'Brien ATOMIC_ASM(add, short, "addw %w2,%0", v) 18625f01030SDavid E. O'Brien ATOMIC_ASM(subtract, short, "subw %w2,%0", v) 187e58bb1c4SAlan Cox 18847b8bc92SAlan Cox ATOMIC_ASM(set, int, "orl %2,%0", v) 18947b8bc92SAlan Cox ATOMIC_ASM(clear, int, "andl %2,%0", ~v) 19047b8bc92SAlan Cox ATOMIC_ASM(add, int, "addl %2,%0", v) 19147b8bc92SAlan Cox ATOMIC_ASM(subtract, int, "subl %2,%0", v) 192e58bb1c4SAlan Cox 19347b8bc92SAlan Cox ATOMIC_ASM(set, long, "orl %2,%0", v) 19447b8bc92SAlan Cox ATOMIC_ASM(clear, long, "andl %2,%0", ~v) 19547b8bc92SAlan Cox ATOMIC_ASM(add, long, "addl %2,%0", v) 19647b8bc92SAlan Cox ATOMIC_ASM(subtract, long, "subl %2,%0", v) 197069e9bc1SDoug Rabson 198181d2137SEivind Eklund #else 199181d2137SEivind Eklund 200693612ebSPeter Wemm /* gcc <= 2.8 version */ 201693612ebSPeter Wemm ATOMIC_ASM(set, char, "orb %1,%0", v) 202693612ebSPeter Wemm ATOMIC_ASM(clear, char, "andb %1,%0", ~v) 203693612ebSPeter Wemm ATOMIC_ASM(add, char, "addb %1,%0", v) 204693612ebSPeter Wemm ATOMIC_ASM(subtract, char, "subb %1,%0", v) 205181d2137SEivind Eklund 206693612ebSPeter Wemm ATOMIC_ASM(set, short, "orw %1,%0", v) 207693612ebSPeter Wemm ATOMIC_ASM(clear, short, "andw %1,%0", ~v) 208693612ebSPeter Wemm ATOMIC_ASM(add, short, "addw %1,%0", v) 209693612ebSPeter Wemm ATOMIC_ASM(subtract, short, "subw %1,%0", v) 210181d2137SEivind Eklund 211693612ebSPeter Wemm ATOMIC_ASM(set, int, "orl %1,%0", v) 212693612ebSPeter Wemm ATOMIC_ASM(clear, int, "andl %1,%0", ~v) 213693612ebSPeter Wemm ATOMIC_ASM(add, int, "addl %1,%0", v) 214693612ebSPeter Wemm ATOMIC_ASM(subtract, int, "subl %1,%0", v) 215693612ebSPeter Wemm 216693612ebSPeter Wemm ATOMIC_ASM(set, long, "orl %1,%0", v) 217693612ebSPeter Wemm ATOMIC_ASM(clear, long, "andl %1,%0", ~v) 218693612ebSPeter Wemm ATOMIC_ASM(add, long, "addl %1,%0", v) 219693612ebSPeter Wemm ATOMIC_ASM(subtract, long, "subl %1,%0", v) 220693612ebSPeter Wemm 221181d2137SEivind Eklund #endif 222181d2137SEivind Eklund 223ccbdd9eeSJohn Baldwin #undef ATOMIC_ASM 224ccbdd9eeSJohn Baldwin 225819e370cSPoul-Henning Kamp #ifndef WANT_FUNCTIONS 226ccbdd9eeSJohn Baldwin #define ATOMIC_ACQ_REL(NAME, TYPE) \ 227ccbdd9eeSJohn Baldwin static __inline void \ 228ccbdd9eeSJohn Baldwin atomic_##NAME##_acq_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 229ccbdd9eeSJohn Baldwin { \ 230ccbdd9eeSJohn Baldwin atomic_##NAME##_##TYPE(p, v); \ 231ccbdd9eeSJohn Baldwin } \ 232ccbdd9eeSJohn Baldwin \ 233ccbdd9eeSJohn Baldwin static __inline void \ 234ccbdd9eeSJohn Baldwin atomic_##NAME##_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 235ccbdd9eeSJohn Baldwin { \ 236ccbdd9eeSJohn Baldwin atomic_##NAME##_##TYPE(p, v); \ 237ccbdd9eeSJohn Baldwin } 238ccbdd9eeSJohn Baldwin 239ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(set, char) 240ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(clear, char) 241ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(add, char) 242ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(subtract, char) 243ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(set, short) 244ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(clear, short) 245ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(add, short) 246ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(subtract, short) 247ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(set, int) 248ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(clear, int) 249ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(add, int) 250ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(subtract, int) 251ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(set, long) 252ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(clear, long) 253ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(add, long) 254ccbdd9eeSJohn Baldwin ATOMIC_ACQ_REL(subtract, long) 255ccbdd9eeSJohn Baldwin 256ccbdd9eeSJohn Baldwin #undef ATOMIC_ACQ_REL 257ccbdd9eeSJohn Baldwin 2589d979d89SJohn Baldwin #if defined(KLD_MODULE) 2599d979d89SJohn Baldwin #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 2609d979d89SJohn Baldwin u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 2619d979d89SJohn Baldwin void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v); 2629d979d89SJohn Baldwin #else 2639d979d89SJohn Baldwin #if defined(I386_CPU) 264ccbdd9eeSJohn Baldwin /* 265ccbdd9eeSJohn Baldwin * We assume that a = b will do atomic loads and stores. 2669d979d89SJohn Baldwin * 2679d979d89SJohn Baldwin * XXX: This is _NOT_ safe on a P6 or higher because it does not guarantee 2689d979d89SJohn Baldwin * memory ordering. These should only be used on a 386. 269ccbdd9eeSJohn Baldwin */ 2709d979d89SJohn Baldwin #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 271ccbdd9eeSJohn Baldwin static __inline u_##TYPE \ 272ccbdd9eeSJohn Baldwin atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ 273ccbdd9eeSJohn Baldwin { \ 274ccbdd9eeSJohn Baldwin return (*p); \ 275ccbdd9eeSJohn Baldwin } \ 276ccbdd9eeSJohn Baldwin \ 277ccbdd9eeSJohn Baldwin static __inline void \ 278ccbdd9eeSJohn Baldwin atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 279ccbdd9eeSJohn Baldwin { \ 280ccbdd9eeSJohn Baldwin *p = v; \ 281ccbdd9eeSJohn Baldwin __asm __volatile("" : : : "memory"); \ 282ccbdd9eeSJohn Baldwin } 2839d979d89SJohn Baldwin #else 284ccbdd9eeSJohn Baldwin 2859d979d89SJohn Baldwin #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 2869d979d89SJohn Baldwin static __inline u_##TYPE \ 2879d979d89SJohn Baldwin atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ 2889d979d89SJohn Baldwin { \ 2899d979d89SJohn Baldwin u_##TYPE res; \ 2909d979d89SJohn Baldwin \ 2919d979d89SJohn Baldwin __asm __volatile(MPLOCKED LOP \ 2929d979d89SJohn Baldwin : "+a" (res), /* 0 (result) */\ 2939d979d89SJohn Baldwin "+m" (*p) /* 1 */ \ 2949d979d89SJohn Baldwin : : "memory"); \ 2959d979d89SJohn Baldwin \ 2969d979d89SJohn Baldwin return (res); \ 2979d979d89SJohn Baldwin } \ 2989d979d89SJohn Baldwin \ 2999d979d89SJohn Baldwin /* \ 3009d979d89SJohn Baldwin * The XCHG instruction asserts LOCK automagically. \ 3019d979d89SJohn Baldwin */ \ 3029d979d89SJohn Baldwin static __inline void \ 3039d979d89SJohn Baldwin atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 3049d979d89SJohn Baldwin { \ 3059d979d89SJohn Baldwin __asm __volatile(SOP \ 3069d979d89SJohn Baldwin : "+m" (*p), /* 0 */ \ 3079d979d89SJohn Baldwin "+r" (v) /* 1 */ \ 3089d979d89SJohn Baldwin : : "memory"); \ 3099d979d89SJohn Baldwin } 3109d979d89SJohn Baldwin #endif /* defined(I386_CPU) */ 3119d979d89SJohn Baldwin #endif /* defined(KLD_MODULE) */ 3129d979d89SJohn Baldwin 3139d979d89SJohn Baldwin ATOMIC_STORE_LOAD(char, "cmpxchgb %b0,%1", "xchgb %b1,%0") 3149d979d89SJohn Baldwin ATOMIC_STORE_LOAD(short,"cmpxchgw %w0,%1", "xchgw %w1,%0") 3159d979d89SJohn Baldwin ATOMIC_STORE_LOAD(int, "cmpxchgl %0,%1", "xchgl %1,%0") 3169d979d89SJohn Baldwin ATOMIC_STORE_LOAD(long, "cmpxchgl %0,%1", "xchgl %1,%0") 317ccbdd9eeSJohn Baldwin 318ccbdd9eeSJohn Baldwin #undef ATOMIC_STORE_LOAD 319ccbdd9eeSJohn Baldwin 320819e370cSPoul-Henning Kamp static __inline int 321819e370cSPoul-Henning Kamp atomic_cmpset_ptr(volatile void *dst, void *exp, void *src) 322819e370cSPoul-Henning Kamp { 323819e370cSPoul-Henning Kamp 324819e370cSPoul-Henning Kamp return ( 325819e370cSPoul-Henning Kamp atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, (u_int)src)); 326819e370cSPoul-Henning Kamp } 327b4645202SJohn Baldwin 328ccbdd9eeSJohn Baldwin #define atomic_cmpset_acq_ptr atomic_cmpset_ptr 329ccbdd9eeSJohn Baldwin #define atomic_cmpset_rel_ptr atomic_cmpset_ptr 330ccbdd9eeSJohn Baldwin 331ccbdd9eeSJohn Baldwin static __inline void * 332ccbdd9eeSJohn Baldwin atomic_load_acq_ptr(volatile void *p) 333ccbdd9eeSJohn Baldwin { 334ccbdd9eeSJohn Baldwin return (void *)atomic_load_acq_int((volatile u_int *)p); 335ccbdd9eeSJohn Baldwin } 336ccbdd9eeSJohn Baldwin 337ccbdd9eeSJohn Baldwin static __inline void 338ccbdd9eeSJohn Baldwin atomic_store_rel_ptr(volatile void *p, void *v) 339ccbdd9eeSJohn Baldwin { 340ccbdd9eeSJohn Baldwin atomic_store_rel_int((volatile u_int *)p, (u_int)v); 341ccbdd9eeSJohn Baldwin } 342ccbdd9eeSJohn Baldwin 343ccbdd9eeSJohn Baldwin #define ATOMIC_PTR(NAME) \ 344ccbdd9eeSJohn Baldwin static __inline void \ 345ccbdd9eeSJohn Baldwin atomic_##NAME##_ptr(volatile void *p, uintptr_t v) \ 346ccbdd9eeSJohn Baldwin { \ 347ccbdd9eeSJohn Baldwin atomic_##NAME##_int((volatile u_int *)p, v); \ 348ccbdd9eeSJohn Baldwin } \ 349ccbdd9eeSJohn Baldwin \ 350ccbdd9eeSJohn Baldwin static __inline void \ 351ccbdd9eeSJohn Baldwin atomic_##NAME##_acq_ptr(volatile void *p, uintptr_t v) \ 352ccbdd9eeSJohn Baldwin { \ 353ccbdd9eeSJohn Baldwin atomic_##NAME##_acq_int((volatile u_int *)p, v);\ 354ccbdd9eeSJohn Baldwin } \ 355ccbdd9eeSJohn Baldwin \ 356ccbdd9eeSJohn Baldwin static __inline void \ 357ccbdd9eeSJohn Baldwin atomic_##NAME##_rel_ptr(volatile void *p, uintptr_t v) \ 358ccbdd9eeSJohn Baldwin { \ 359ccbdd9eeSJohn Baldwin atomic_##NAME##_rel_int((volatile u_int *)p, v);\ 360ccbdd9eeSJohn Baldwin } 361ccbdd9eeSJohn Baldwin 362ccbdd9eeSJohn Baldwin ATOMIC_PTR(set) 363ccbdd9eeSJohn Baldwin ATOMIC_PTR(clear) 364ccbdd9eeSJohn Baldwin ATOMIC_PTR(add) 365ccbdd9eeSJohn Baldwin ATOMIC_PTR(subtract) 366ccbdd9eeSJohn Baldwin 367ccbdd9eeSJohn Baldwin #undef ATOMIC_PTR 368ccbdd9eeSJohn Baldwin 369b4645202SJohn Baldwin static __inline u_int 370b4645202SJohn Baldwin atomic_readandclear_int(volatile u_int *addr) 371b4645202SJohn Baldwin { 372b4645202SJohn Baldwin u_int result; 373b4645202SJohn Baldwin 374b4645202SJohn Baldwin __asm __volatile ( 375b4645202SJohn Baldwin " xorl %0,%0 ; " 376b4645202SJohn Baldwin " xchgl %1,%0 ; " 377b4645202SJohn Baldwin "# atomic_readandclear_int" 378b4645202SJohn Baldwin : "=&r" (result) /* 0 (result) */ 379b4645202SJohn Baldwin : "m" (*addr)); /* 1 (addr) */ 380b4645202SJohn Baldwin 381b4645202SJohn Baldwin return (result); 382b4645202SJohn Baldwin } 383b4645202SJohn Baldwin 384b4645202SJohn Baldwin static __inline u_long 385b4645202SJohn Baldwin atomic_readandclear_long(volatile u_long *addr) 386b4645202SJohn Baldwin { 387b4645202SJohn Baldwin u_long result; 388b4645202SJohn Baldwin 389b4645202SJohn Baldwin __asm __volatile ( 390b4645202SJohn Baldwin " xorl %0,%0 ; " 391b4645202SJohn Baldwin " xchgl %1,%0 ; " 392b4645202SJohn Baldwin "# atomic_readandclear_int" 393b4645202SJohn Baldwin : "=&r" (result) /* 0 (result) */ 394b4645202SJohn Baldwin : "m" (*addr)); /* 1 (addr) */ 395b4645202SJohn Baldwin 396b4645202SJohn Baldwin return (result); 397b4645202SJohn Baldwin } 398819e370cSPoul-Henning Kamp #endif 399819e370cSPoul-Henning Kamp 400ee8f2f37SJohn Baldwin #define atomic_set_8 atomic_set_char 401ee8f2f37SJohn Baldwin #define atomic_set_acq_8 atomic_set_acq_char 402ee8f2f37SJohn Baldwin #define atomic_set_rel_8 atomic_set_rel_char 403ee8f2f37SJohn Baldwin #define atomic_clear_8 atomic_clear_char 404ee8f2f37SJohn Baldwin #define atomic_clear_acq_8 atomic_clear_acq_char 405ee8f2f37SJohn Baldwin #define atomic_clear_rel_8 atomic_clear_rel_char 406ee8f2f37SJohn Baldwin #define atomic_add_8 atomic_add_char 407ee8f2f37SJohn Baldwin #define atomic_add_acq_8 atomic_add_acq_char 408ee8f2f37SJohn Baldwin #define atomic_add_rel_8 atomic_add_rel_char 409ee8f2f37SJohn Baldwin #define atomic_subtract_8 atomic_subtract_char 410ee8f2f37SJohn Baldwin #define atomic_subtract_acq_8 atomic_subtract_acq_char 411ee8f2f37SJohn Baldwin #define atomic_subtract_rel_8 atomic_subtract_rel_char 412ee8f2f37SJohn Baldwin #define atomic_load_acq_8 atomic_load_acq_char 413ee8f2f37SJohn Baldwin #define atomic_store_rel_8 atomic_store_rel_char 414ee8f2f37SJohn Baldwin 415ee8f2f37SJohn Baldwin #define atomic_set_16 atomic_set_short 416ee8f2f37SJohn Baldwin #define atomic_set_acq_16 atomic_set_acq_short 417ee8f2f37SJohn Baldwin #define atomic_set_rel_16 atomic_set_rel_short 418ee8f2f37SJohn Baldwin #define atomic_clear_16 atomic_clear_short 419ee8f2f37SJohn Baldwin #define atomic_clear_acq_16 atomic_clear_acq_short 420ee8f2f37SJohn Baldwin #define atomic_clear_rel_16 atomic_clear_rel_short 421ee8f2f37SJohn Baldwin #define atomic_add_16 atomic_add_short 422ee8f2f37SJohn Baldwin #define atomic_add_acq_16 atomic_add_acq_short 423ee8f2f37SJohn Baldwin #define atomic_add_rel_16 atomic_add_rel_short 424ee8f2f37SJohn Baldwin #define atomic_subtract_16 atomic_subtract_short 425ee8f2f37SJohn Baldwin #define atomic_subtract_acq_16 atomic_subtract_acq_short 426ee8f2f37SJohn Baldwin #define atomic_subtract_rel_16 atomic_subtract_rel_short 427ee8f2f37SJohn Baldwin #define atomic_load_acq_16 atomic_load_acq_short 428ee8f2f37SJohn Baldwin #define atomic_store_rel_16 atomic_store_rel_short 429ee8f2f37SJohn Baldwin 430ee8f2f37SJohn Baldwin #define atomic_set_32 atomic_set_int 431ee8f2f37SJohn Baldwin #define atomic_set_acq_32 atomic_set_acq_int 432ee8f2f37SJohn Baldwin #define atomic_set_rel_32 atomic_set_rel_int 433ee8f2f37SJohn Baldwin #define atomic_clear_32 atomic_clear_int 434ee8f2f37SJohn Baldwin #define atomic_clear_acq_32 atomic_clear_acq_int 435ee8f2f37SJohn Baldwin #define atomic_clear_rel_32 atomic_clear_rel_int 436ee8f2f37SJohn Baldwin #define atomic_add_32 atomic_add_int 437ee8f2f37SJohn Baldwin #define atomic_add_acq_32 atomic_add_acq_int 438ee8f2f37SJohn Baldwin #define atomic_add_rel_32 atomic_add_rel_int 439ee8f2f37SJohn Baldwin #define atomic_subtract_32 atomic_subtract_int 440ee8f2f37SJohn Baldwin #define atomic_subtract_acq_32 atomic_subtract_acq_int 441ee8f2f37SJohn Baldwin #define atomic_subtract_rel_32 atomic_subtract_rel_int 442ee8f2f37SJohn Baldwin #define atomic_load_acq_32 atomic_load_acq_int 443ee8f2f37SJohn Baldwin #define atomic_store_rel_32 atomic_store_rel_int 444ee8f2f37SJohn Baldwin #define atomic_cmpset_32 atomic_cmpset_int 445ee8f2f37SJohn Baldwin #define atomic_cmpset_acq_32 atomic_cmpset_acq_int 446ee8f2f37SJohn Baldwin #define atomic_cmpset_rel_32 atomic_cmpset_rel_int 447ee8f2f37SJohn Baldwin #define atomic_readandclear_32 atomic_readandclear_int 448ee8f2f37SJohn Baldwin 449069e9bc1SDoug Rabson #endif /* ! _MACHINE_ATOMIC_H_ */ 450