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) 67e4e991e1SJohn Baldwin #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 688306a37bSMark Murray 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 728a6b1c8fSJohn Baldwin #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 738a6b1c8fSJohn Baldwin u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 748306a37bSMark Murray void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 758a6b1c8fSJohn Baldwin 7608c40841SAlan Cox #else /* !KLD_MODULE */ 77d888fc4eSMark Murray 784c5aee92SMark Murray #ifdef __GNUC__ 794c5aee92SMark Murray 802a89a48fSJohn Baldwin /* 812a89a48fSJohn Baldwin * For userland, assume the SMP case and use lock prefixes so that 822a89a48fSJohn Baldwin * the binaries will run on both types of systems. 832a89a48fSJohn Baldwin */ 842a89a48fSJohn Baldwin #if defined(SMP) || !defined(_KERNEL) 8571acb247SBosko Milekic #define MPLOCKED lock ; 86d2f22d70SBruce Evans #else 8747b8bc92SAlan Cox #define MPLOCKED 88d2f22d70SBruce Evans #endif 89069e9bc1SDoug Rabson 9047b8bc92SAlan Cox /* 9147b8bc92SAlan Cox * The assembly is volatilized to demark potential before-and-after side 9247b8bc92SAlan Cox * effects if an interrupt or SMP collision were to occur. 9347b8bc92SAlan Cox */ 94e4e991e1SJohn Baldwin #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 9547b8bc92SAlan Cox static __inline void \ 9603e3bc8eSAlan Cox atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 9747b8bc92SAlan Cox { \ 9871acb247SBosko Milekic __asm __volatile(__XSTRING(MPLOCKED) OP \ 9920a2016aSJohn Baldwin : "+m" (*p) \ 100e4e991e1SJohn Baldwin : CONS (V)); \ 1016d800f89SBruce Evans } \ 1026d800f89SBruce Evans struct __hack 1034c5aee92SMark Murray 1048306a37bSMark Murray #else /* !__GNUC__ */ 1054c5aee92SMark Murray 1068306a37bSMark Murray #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 1074c5aee92SMark Murray extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 1084c5aee92SMark Murray 1098306a37bSMark Murray #endif /* __GNUC__ */ 110693612ebSPeter Wemm 111819e370cSPoul-Henning Kamp /* 112819e370cSPoul-Henning Kamp * Atomic compare and set, used by the mutex functions 113819e370cSPoul-Henning Kamp * 114819e370cSPoul-Henning Kamp * if (*dst == exp) *dst = src (all 32 bit words) 115819e370cSPoul-Henning Kamp * 116819e370cSPoul-Henning Kamp * Returns 0 on failure, non-zero on success 117819e370cSPoul-Henning Kamp */ 118819e370cSPoul-Henning Kamp 1198306a37bSMark Murray #if defined(__GNUC__) 1204c5aee92SMark Murray 12177e83412SJim Pirzyk #if defined(I386_CPU) || defined(CPU_DISABLE_CMPXCHG) 1224c5aee92SMark Murray 123819e370cSPoul-Henning Kamp static __inline int 124819e370cSPoul-Henning Kamp atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 125819e370cSPoul-Henning Kamp { 126819e370cSPoul-Henning Kamp int res = exp; 127819e370cSPoul-Henning Kamp 128819e370cSPoul-Henning Kamp __asm __volatile( 129819e370cSPoul-Henning Kamp " pushfl ; " 130819e370cSPoul-Henning Kamp " cli ; " 131d9009094SJohn Baldwin " cmpl %0,%2 ; " 132819e370cSPoul-Henning Kamp " jne 1f ; " 133d9009094SJohn Baldwin " movl %1,%2 ; " 134819e370cSPoul-Henning Kamp "1: " 135819e370cSPoul-Henning Kamp " sete %%al; " 136819e370cSPoul-Henning Kamp " movzbl %%al,%0 ; " 137819e370cSPoul-Henning Kamp " popfl ; " 138819e370cSPoul-Henning Kamp "# atomic_cmpset_int" 139d9009094SJohn Baldwin : "+a" (res) /* 0 (result) */ 140d9009094SJohn Baldwin : "r" (src), /* 1 */ 141d9009094SJohn Baldwin "m" (*(dst)) /* 2 */ 142819e370cSPoul-Henning Kamp : "memory"); 143819e370cSPoul-Henning Kamp 144819e370cSPoul-Henning Kamp return (res); 145819e370cSPoul-Henning Kamp } 1464c5aee92SMark Murray 147819e370cSPoul-Henning Kamp #else /* defined(I386_CPU) */ 1484c5aee92SMark Murray 149819e370cSPoul-Henning Kamp static __inline int 150819e370cSPoul-Henning Kamp atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 151819e370cSPoul-Henning Kamp { 152819e370cSPoul-Henning Kamp int res = exp; 153819e370cSPoul-Henning Kamp 154819e370cSPoul-Henning Kamp __asm __volatile ( 15571acb247SBosko Milekic " " __XSTRING(MPLOCKED) " " 156d9009094SJohn Baldwin " cmpxchgl %1,%2 ; " 157819e370cSPoul-Henning Kamp " setz %%al ; " 158819e370cSPoul-Henning Kamp " movzbl %%al,%0 ; " 159819e370cSPoul-Henning Kamp "1: " 160819e370cSPoul-Henning Kamp "# atomic_cmpset_int" 161d9009094SJohn Baldwin : "+a" (res) /* 0 (result) */ 162d9009094SJohn Baldwin : "r" (src), /* 1 */ 163d9009094SJohn Baldwin "m" (*(dst)) /* 2 */ 164819e370cSPoul-Henning Kamp : "memory"); 165819e370cSPoul-Henning Kamp 166819e370cSPoul-Henning Kamp return (res); 167819e370cSPoul-Henning Kamp } 1684c5aee92SMark Murray 169819e370cSPoul-Henning Kamp #endif /* defined(I386_CPU) */ 1704c5aee92SMark Murray 1718306a37bSMark Murray #endif /* defined(__GNUC__) */ 172819e370cSPoul-Henning Kamp 1738306a37bSMark Murray #if defined(__GNUC__) 1744c5aee92SMark Murray 1759d979d89SJohn Baldwin #if defined(I386_CPU) 1764c5aee92SMark Murray 177ccbdd9eeSJohn Baldwin /* 178ccbdd9eeSJohn Baldwin * We assume that a = b will do atomic loads and stores. 1799d979d89SJohn Baldwin * 1809d979d89SJohn Baldwin * XXX: This is _NOT_ safe on a P6 or higher because it does not guarantee 1819d979d89SJohn Baldwin * memory ordering. These should only be used on a 386. 182ccbdd9eeSJohn Baldwin */ 1839d979d89SJohn Baldwin #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 184ccbdd9eeSJohn Baldwin static __inline u_##TYPE \ 185ccbdd9eeSJohn Baldwin atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ 186ccbdd9eeSJohn Baldwin { \ 187ccbdd9eeSJohn Baldwin return (*p); \ 188ccbdd9eeSJohn Baldwin } \ 189ccbdd9eeSJohn Baldwin \ 190ccbdd9eeSJohn Baldwin static __inline void \ 191ccbdd9eeSJohn Baldwin atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 192ccbdd9eeSJohn Baldwin { \ 193ccbdd9eeSJohn Baldwin *p = v; \ 194ccbdd9eeSJohn Baldwin __asm __volatile("" : : : "memory"); \ 1956d800f89SBruce Evans } \ 1966d800f89SBruce Evans struct __hack 1974c5aee92SMark Murray 1988306a37bSMark Murray #else /* !defined(I386_CPU) */ 199ccbdd9eeSJohn Baldwin 2009d979d89SJohn Baldwin #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 2019d979d89SJohn Baldwin static __inline u_##TYPE \ 2029d979d89SJohn Baldwin atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ 2039d979d89SJohn Baldwin { \ 2049d979d89SJohn Baldwin u_##TYPE res; \ 2059d979d89SJohn Baldwin \ 20671acb247SBosko Milekic __asm __volatile(__XSTRING(MPLOCKED) LOP \ 207324fffaeSJohn Baldwin : "=a" (res), /* 0 (result) */\ 2089d979d89SJohn Baldwin "+m" (*p) /* 1 */ \ 209e4e991e1SJohn Baldwin : : "memory"); \ 2109d979d89SJohn Baldwin \ 2119d979d89SJohn Baldwin return (res); \ 2129d979d89SJohn Baldwin } \ 2139d979d89SJohn Baldwin \ 2149d979d89SJohn Baldwin /* \ 2159d979d89SJohn Baldwin * The XCHG instruction asserts LOCK automagically. \ 2169d979d89SJohn Baldwin */ \ 2179d979d89SJohn Baldwin static __inline void \ 2189d979d89SJohn Baldwin atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 2199d979d89SJohn Baldwin { \ 2209d979d89SJohn Baldwin __asm __volatile(SOP \ 2219d979d89SJohn Baldwin : "+m" (*p), /* 0 */ \ 2229d979d89SJohn Baldwin "+r" (v) /* 1 */ \ 2239d979d89SJohn Baldwin : : "memory"); \ 2246d800f89SBruce Evans } \ 2256d800f89SBruce Evans struct __hack 2264c5aee92SMark Murray 2279d979d89SJohn Baldwin #endif /* defined(I386_CPU) */ 2284c5aee92SMark Murray 2298306a37bSMark Murray #else /* !defined(__GNUC__) */ 2308306a37bSMark Murray 2314c5aee92SMark Murray extern int atomic_cmpset_int(volatile u_int *, u_int, u_int); 2324c5aee92SMark Murray 2338306a37bSMark Murray #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 2344c5aee92SMark Murray extern u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 2354c5aee92SMark Murray extern void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 2368306a37bSMark Murray 2378306a37bSMark Murray #endif /* defined(__GNUC__) */ 2384c5aee92SMark Murray 2398a6b1c8fSJohn Baldwin #endif /* KLD_MODULE */ 2408a6b1c8fSJohn Baldwin 2418306a37bSMark Murray ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); 2428306a37bSMark Murray ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); 2438306a37bSMark Murray ATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); 2448306a37bSMark Murray ATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); 2458a6b1c8fSJohn Baldwin 2468306a37bSMark Murray ATOMIC_ASM(set, short, "orw %w1,%0", "ir", v); 2478306a37bSMark Murray ATOMIC_ASM(clear, short, "andw %w1,%0", "ir", ~v); 2488306a37bSMark Murray ATOMIC_ASM(add, short, "addw %w1,%0", "ir", v); 2498306a37bSMark Murray ATOMIC_ASM(subtract, short, "subw %w1,%0", "ir", v); 2508a6b1c8fSJohn Baldwin 2518306a37bSMark Murray ATOMIC_ASM(set, int, "orl %1,%0", "ir", v); 2528306a37bSMark Murray ATOMIC_ASM(clear, int, "andl %1,%0", "ir", ~v); 2538306a37bSMark Murray ATOMIC_ASM(add, int, "addl %1,%0", "ir", v); 2548306a37bSMark Murray ATOMIC_ASM(subtract, int, "subl %1,%0", "ir", v); 2558a6b1c8fSJohn Baldwin 2568306a37bSMark Murray ATOMIC_ASM(set, long, "orl %1,%0", "ir", v); 2578306a37bSMark Murray ATOMIC_ASM(clear, long, "andl %1,%0", "ir", ~v); 2588306a37bSMark Murray ATOMIC_ASM(add, long, "addl %1,%0", "ir", v); 2598306a37bSMark Murray ATOMIC_ASM(subtract, long, "subl %1,%0", "ir", v); 2609d979d89SJohn Baldwin 2618306a37bSMark Murray ATOMIC_STORE_LOAD(char, "cmpxchgb %b0,%1", "xchgb %b1,%0"); 2628306a37bSMark Murray ATOMIC_STORE_LOAD(short,"cmpxchgw %w0,%1", "xchgw %w1,%0"); 2638306a37bSMark Murray ATOMIC_STORE_LOAD(int, "cmpxchgl %0,%1", "xchgl %1,%0"); 2648306a37bSMark Murray ATOMIC_STORE_LOAD(long, "cmpxchgl %0,%1", "xchgl %1,%0"); 265ccbdd9eeSJohn Baldwin 2668a6b1c8fSJohn Baldwin #undef ATOMIC_ASM 267ccbdd9eeSJohn Baldwin #undef ATOMIC_STORE_LOAD 268ccbdd9eeSJohn Baldwin 2698a6b1c8fSJohn Baldwin #define atomic_set_acq_char atomic_set_char 2708a6b1c8fSJohn Baldwin #define atomic_set_rel_char atomic_set_char 2718a6b1c8fSJohn Baldwin #define atomic_clear_acq_char atomic_clear_char 2728a6b1c8fSJohn Baldwin #define atomic_clear_rel_char atomic_clear_char 2738a6b1c8fSJohn Baldwin #define atomic_add_acq_char atomic_add_char 2748a6b1c8fSJohn Baldwin #define atomic_add_rel_char atomic_add_char 2758a6b1c8fSJohn Baldwin #define atomic_subtract_acq_char atomic_subtract_char 2768a6b1c8fSJohn Baldwin #define atomic_subtract_rel_char atomic_subtract_char 2778a6b1c8fSJohn Baldwin 2788a6b1c8fSJohn Baldwin #define atomic_set_acq_short atomic_set_short 2798a6b1c8fSJohn Baldwin #define atomic_set_rel_short atomic_set_short 2808a6b1c8fSJohn Baldwin #define atomic_clear_acq_short atomic_clear_short 2818a6b1c8fSJohn Baldwin #define atomic_clear_rel_short atomic_clear_short 2828a6b1c8fSJohn Baldwin #define atomic_add_acq_short atomic_add_short 2838a6b1c8fSJohn Baldwin #define atomic_add_rel_short atomic_add_short 2848a6b1c8fSJohn Baldwin #define atomic_subtract_acq_short atomic_subtract_short 2858a6b1c8fSJohn Baldwin #define atomic_subtract_rel_short atomic_subtract_short 2868a6b1c8fSJohn Baldwin 2878a6b1c8fSJohn Baldwin #define atomic_set_acq_int atomic_set_int 2888a6b1c8fSJohn Baldwin #define atomic_set_rel_int atomic_set_int 2898a6b1c8fSJohn Baldwin #define atomic_clear_acq_int atomic_clear_int 2908a6b1c8fSJohn Baldwin #define atomic_clear_rel_int atomic_clear_int 2918a6b1c8fSJohn Baldwin #define atomic_add_acq_int atomic_add_int 2928a6b1c8fSJohn Baldwin #define atomic_add_rel_int atomic_add_int 2938a6b1c8fSJohn Baldwin #define atomic_subtract_acq_int atomic_subtract_int 2948a6b1c8fSJohn Baldwin #define atomic_subtract_rel_int atomic_subtract_int 2958a6b1c8fSJohn Baldwin #define atomic_cmpset_acq_int atomic_cmpset_int 2968a6b1c8fSJohn Baldwin #define atomic_cmpset_rel_int atomic_cmpset_int 2978a6b1c8fSJohn Baldwin 2988a6b1c8fSJohn Baldwin #define atomic_set_acq_long atomic_set_long 2998a6b1c8fSJohn Baldwin #define atomic_set_rel_long atomic_set_long 3008a6b1c8fSJohn Baldwin #define atomic_clear_acq_long atomic_clear_long 3018a6b1c8fSJohn Baldwin #define atomic_clear_rel_long atomic_clear_long 3028a6b1c8fSJohn Baldwin #define atomic_add_acq_long atomic_add_long 3038a6b1c8fSJohn Baldwin #define atomic_add_rel_long atomic_add_long 3048a6b1c8fSJohn Baldwin #define atomic_subtract_acq_long atomic_subtract_long 3058a6b1c8fSJohn Baldwin #define atomic_subtract_rel_long atomic_subtract_long 3068a6b1c8fSJohn Baldwin #define atomic_cmpset_long atomic_cmpset_int 3078a6b1c8fSJohn Baldwin #define atomic_cmpset_acq_long atomic_cmpset_acq_int 3088a6b1c8fSJohn Baldwin #define atomic_cmpset_rel_long atomic_cmpset_rel_int 3098a6b1c8fSJohn Baldwin 3108a6b1c8fSJohn Baldwin #define atomic_cmpset_acq_ptr atomic_cmpset_ptr 3118a6b1c8fSJohn Baldwin #define atomic_cmpset_rel_ptr atomic_cmpset_ptr 3128a6b1c8fSJohn Baldwin 3138a6b1c8fSJohn Baldwin #define atomic_set_8 atomic_set_char 3148a6b1c8fSJohn Baldwin #define atomic_set_acq_8 atomic_set_acq_char 3158a6b1c8fSJohn Baldwin #define atomic_set_rel_8 atomic_set_rel_char 3168a6b1c8fSJohn Baldwin #define atomic_clear_8 atomic_clear_char 3178a6b1c8fSJohn Baldwin #define atomic_clear_acq_8 atomic_clear_acq_char 3188a6b1c8fSJohn Baldwin #define atomic_clear_rel_8 atomic_clear_rel_char 3198a6b1c8fSJohn Baldwin #define atomic_add_8 atomic_add_char 3208a6b1c8fSJohn Baldwin #define atomic_add_acq_8 atomic_add_acq_char 3218a6b1c8fSJohn Baldwin #define atomic_add_rel_8 atomic_add_rel_char 3228a6b1c8fSJohn Baldwin #define atomic_subtract_8 atomic_subtract_char 3238a6b1c8fSJohn Baldwin #define atomic_subtract_acq_8 atomic_subtract_acq_char 3248a6b1c8fSJohn Baldwin #define atomic_subtract_rel_8 atomic_subtract_rel_char 3258a6b1c8fSJohn Baldwin #define atomic_load_acq_8 atomic_load_acq_char 3268a6b1c8fSJohn Baldwin #define atomic_store_rel_8 atomic_store_rel_char 3278a6b1c8fSJohn Baldwin 3288a6b1c8fSJohn Baldwin #define atomic_set_16 atomic_set_short 3298a6b1c8fSJohn Baldwin #define atomic_set_acq_16 atomic_set_acq_short 3308a6b1c8fSJohn Baldwin #define atomic_set_rel_16 atomic_set_rel_short 3318a6b1c8fSJohn Baldwin #define atomic_clear_16 atomic_clear_short 3328a6b1c8fSJohn Baldwin #define atomic_clear_acq_16 atomic_clear_acq_short 3338a6b1c8fSJohn Baldwin #define atomic_clear_rel_16 atomic_clear_rel_short 3348a6b1c8fSJohn Baldwin #define atomic_add_16 atomic_add_short 3358a6b1c8fSJohn Baldwin #define atomic_add_acq_16 atomic_add_acq_short 3368a6b1c8fSJohn Baldwin #define atomic_add_rel_16 atomic_add_rel_short 3378a6b1c8fSJohn Baldwin #define atomic_subtract_16 atomic_subtract_short 3388a6b1c8fSJohn Baldwin #define atomic_subtract_acq_16 atomic_subtract_acq_short 3398a6b1c8fSJohn Baldwin #define atomic_subtract_rel_16 atomic_subtract_rel_short 3408a6b1c8fSJohn Baldwin #define atomic_load_acq_16 atomic_load_acq_short 3418a6b1c8fSJohn Baldwin #define atomic_store_rel_16 atomic_store_rel_short 3428a6b1c8fSJohn Baldwin 3438a6b1c8fSJohn Baldwin #define atomic_set_32 atomic_set_int 3448a6b1c8fSJohn Baldwin #define atomic_set_acq_32 atomic_set_acq_int 3458a6b1c8fSJohn Baldwin #define atomic_set_rel_32 atomic_set_rel_int 3468a6b1c8fSJohn Baldwin #define atomic_clear_32 atomic_clear_int 3478a6b1c8fSJohn Baldwin #define atomic_clear_acq_32 atomic_clear_acq_int 3488a6b1c8fSJohn Baldwin #define atomic_clear_rel_32 atomic_clear_rel_int 3498a6b1c8fSJohn Baldwin #define atomic_add_32 atomic_add_int 3508a6b1c8fSJohn Baldwin #define atomic_add_acq_32 atomic_add_acq_int 3518a6b1c8fSJohn Baldwin #define atomic_add_rel_32 atomic_add_rel_int 3528a6b1c8fSJohn Baldwin #define atomic_subtract_32 atomic_subtract_int 3538a6b1c8fSJohn Baldwin #define atomic_subtract_acq_32 atomic_subtract_acq_int 3548a6b1c8fSJohn Baldwin #define atomic_subtract_rel_32 atomic_subtract_rel_int 3558a6b1c8fSJohn Baldwin #define atomic_load_acq_32 atomic_load_acq_int 3568a6b1c8fSJohn Baldwin #define atomic_store_rel_32 atomic_store_rel_int 3578a6b1c8fSJohn Baldwin #define atomic_cmpset_32 atomic_cmpset_int 3588a6b1c8fSJohn Baldwin #define atomic_cmpset_acq_32 atomic_cmpset_acq_int 3598a6b1c8fSJohn Baldwin #define atomic_cmpset_rel_32 atomic_cmpset_rel_int 3608a6b1c8fSJohn Baldwin #define atomic_readandclear_32 atomic_readandclear_int 3618a6b1c8fSJohn Baldwin 3628a6b1c8fSJohn Baldwin #if !defined(WANT_FUNCTIONS) 363819e370cSPoul-Henning Kamp static __inline int 364819e370cSPoul-Henning Kamp atomic_cmpset_ptr(volatile void *dst, void *exp, void *src) 365819e370cSPoul-Henning Kamp { 366819e370cSPoul-Henning Kamp 3678a6b1c8fSJohn Baldwin return (atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, 3688a6b1c8fSJohn Baldwin (u_int)src)); 369819e370cSPoul-Henning Kamp } 370b4645202SJohn Baldwin 371ccbdd9eeSJohn Baldwin static __inline void * 372ccbdd9eeSJohn Baldwin atomic_load_acq_ptr(volatile void *p) 373ccbdd9eeSJohn Baldwin { 374ed9800b4SBruce Evans /* 375ed9800b4SBruce Evans * The apparently-bogus cast to intptr_t in the following is to 376ed9800b4SBruce Evans * avoid a warning from "gcc -Wbad-function-cast". 377ed9800b4SBruce Evans */ 378ed9800b4SBruce Evans return ((void *)(intptr_t)atomic_load_acq_int((volatile u_int *)p)); 379ccbdd9eeSJohn Baldwin } 380ccbdd9eeSJohn Baldwin 381ccbdd9eeSJohn Baldwin static __inline void 382ccbdd9eeSJohn Baldwin atomic_store_rel_ptr(volatile void *p, void *v) 383ccbdd9eeSJohn Baldwin { 384ccbdd9eeSJohn Baldwin atomic_store_rel_int((volatile u_int *)p, (u_int)v); 385ccbdd9eeSJohn Baldwin } 386ccbdd9eeSJohn Baldwin 387ccbdd9eeSJohn Baldwin #define ATOMIC_PTR(NAME) \ 388ccbdd9eeSJohn Baldwin static __inline void \ 389ccbdd9eeSJohn Baldwin atomic_##NAME##_ptr(volatile void *p, uintptr_t v) \ 390ccbdd9eeSJohn Baldwin { \ 391ccbdd9eeSJohn Baldwin atomic_##NAME##_int((volatile u_int *)p, v); \ 392ccbdd9eeSJohn Baldwin } \ 393ccbdd9eeSJohn Baldwin \ 394ccbdd9eeSJohn Baldwin static __inline void \ 395ccbdd9eeSJohn Baldwin atomic_##NAME##_acq_ptr(volatile void *p, uintptr_t v) \ 396ccbdd9eeSJohn Baldwin { \ 397ccbdd9eeSJohn Baldwin atomic_##NAME##_acq_int((volatile u_int *)p, v);\ 398ccbdd9eeSJohn Baldwin } \ 399ccbdd9eeSJohn Baldwin \ 400ccbdd9eeSJohn Baldwin static __inline void \ 401ccbdd9eeSJohn Baldwin atomic_##NAME##_rel_ptr(volatile void *p, uintptr_t v) \ 402ccbdd9eeSJohn Baldwin { \ 403ccbdd9eeSJohn Baldwin atomic_##NAME##_rel_int((volatile u_int *)p, v);\ 404ccbdd9eeSJohn Baldwin } 405ccbdd9eeSJohn Baldwin 406ccbdd9eeSJohn Baldwin ATOMIC_PTR(set) 407ccbdd9eeSJohn Baldwin ATOMIC_PTR(clear) 408ccbdd9eeSJohn Baldwin ATOMIC_PTR(add) 409ccbdd9eeSJohn Baldwin ATOMIC_PTR(subtract) 410ccbdd9eeSJohn Baldwin 411ccbdd9eeSJohn Baldwin #undef ATOMIC_PTR 412ccbdd9eeSJohn Baldwin 4138306a37bSMark Murray #if defined(__GNUC__) 4144c5aee92SMark Murray 415b4645202SJohn Baldwin static __inline u_int 416b4645202SJohn Baldwin atomic_readandclear_int(volatile u_int *addr) 417b4645202SJohn Baldwin { 418b4645202SJohn Baldwin u_int result; 419b4645202SJohn Baldwin 420b4645202SJohn Baldwin __asm __volatile ( 421b4645202SJohn Baldwin " xorl %0,%0 ; " 422b4645202SJohn Baldwin " xchgl %1,%0 ; " 423b4645202SJohn Baldwin "# atomic_readandclear_int" 424b4645202SJohn Baldwin : "=&r" (result) /* 0 (result) */ 425b4645202SJohn Baldwin : "m" (*addr)); /* 1 (addr) */ 426b4645202SJohn Baldwin 427b4645202SJohn Baldwin return (result); 428b4645202SJohn Baldwin } 429b4645202SJohn Baldwin 430b4645202SJohn Baldwin static __inline u_long 431b4645202SJohn Baldwin atomic_readandclear_long(volatile u_long *addr) 432b4645202SJohn Baldwin { 433b4645202SJohn Baldwin u_long result; 434b4645202SJohn Baldwin 435b4645202SJohn Baldwin __asm __volatile ( 436b4645202SJohn Baldwin " xorl %0,%0 ; " 437b4645202SJohn Baldwin " xchgl %1,%0 ; " 438b4645202SJohn Baldwin "# atomic_readandclear_int" 439b4645202SJohn Baldwin : "=&r" (result) /* 0 (result) */ 440b4645202SJohn Baldwin : "m" (*addr)); /* 1 (addr) */ 441b4645202SJohn Baldwin 442b4645202SJohn Baldwin return (result); 443b4645202SJohn Baldwin } 4444c5aee92SMark Murray 4458306a37bSMark Murray #else /* !defined(__GNUC__) */ 4464c5aee92SMark Murray 4474c5aee92SMark Murray extern u_long atomic_readandclear_long(volatile u_long *); 4484c5aee92SMark Murray extern u_int atomic_readandclear_int(volatile u_int *); 4494c5aee92SMark Murray 4508306a37bSMark Murray #endif /* defined(__GNUC__) */ 4514c5aee92SMark Murray 4528a6b1c8fSJohn Baldwin #endif /* !defined(WANT_FUNCTIONS) */ 453069e9bc1SDoug Rabson #endif /* ! _MACHINE_ATOMIC_H_ */ 454