atomic.h revision 100251
138517Sdfr/*- 238517Sdfr * Copyright (c) 1998 Doug Rabson 338517Sdfr * All rights reserved. 438517Sdfr * 538517Sdfr * Redistribution and use in source and binary forms, with or without 638517Sdfr * modification, are permitted provided that the following conditions 738517Sdfr * are met: 838517Sdfr * 1. Redistributions of source code must retain the above copyright 938517Sdfr * notice, this list of conditions and the following disclaimer. 1038517Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1138517Sdfr * notice, this list of conditions and the following disclaimer in the 1238517Sdfr * documentation and/or other materials provided with the distribution. 1338517Sdfr * 1438517Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538517Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638517Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738517Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838517Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938517Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038517Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138517Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238517Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338517Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438517Sdfr * SUCH DAMAGE. 2538517Sdfr * 2650477Speter * $FreeBSD: head/sys/i386/include/atomic.h 100251 2002-07-17 16:19:37Z markm $ 2738517Sdfr */ 2838517Sdfr#ifndef _MACHINE_ATOMIC_H_ 2938517Sdfr#define _MACHINE_ATOMIC_H_ 3038517Sdfr 31100251Smarkm#ifndef __GNUC__ 32100251Smarkm#ifndef lint 33100251Smarkm#error "This file must be compiled with GCC or lint" 34100251Smarkm#endif /* lint */ 35100251Smarkm#endif /* __GNUC__ */ 36100251Smarkm 3738517Sdfr/* 3838517Sdfr * Various simple arithmetic on memory which is atomic in the presence 3948797Salc * of interrupts and multiple processors. 4038517Sdfr * 4148797Salc * atomic_set_char(P, V) (*(u_char*)(P) |= (V)) 4248797Salc * atomic_clear_char(P, V) (*(u_char*)(P) &= ~(V)) 4348797Salc * atomic_add_char(P, V) (*(u_char*)(P) += (V)) 4448797Salc * atomic_subtract_char(P, V) (*(u_char*)(P) -= (V)) 4548797Salc * 4648797Salc * atomic_set_short(P, V) (*(u_short*)(P) |= (V)) 4748797Salc * atomic_clear_short(P, V) (*(u_short*)(P) &= ~(V)) 4848797Salc * atomic_add_short(P, V) (*(u_short*)(P) += (V)) 4948797Salc * atomic_subtract_short(P, V) (*(u_short*)(P) -= (V)) 5048797Salc * 5148797Salc * atomic_set_int(P, V) (*(u_int*)(P) |= (V)) 5248797Salc * atomic_clear_int(P, V) (*(u_int*)(P) &= ~(V)) 5348797Salc * atomic_add_int(P, V) (*(u_int*)(P) += (V)) 5448797Salc * atomic_subtract_int(P, V) (*(u_int*)(P) -= (V)) 5566695Sjhb * atomic_readandclear_int(P) (return *(u_int*)P; *(u_int*)P = 0;) 5648797Salc * 5748797Salc * atomic_set_long(P, V) (*(u_long*)(P) |= (V)) 5848797Salc * atomic_clear_long(P, V) (*(u_long*)(P) &= ~(V)) 5948797Salc * atomic_add_long(P, V) (*(u_long*)(P) += (V)) 6048797Salc * atomic_subtract_long(P, V) (*(u_long*)(P) -= (V)) 6166695Sjhb * atomic_readandclear_long(P) (return *(u_long*)P; *(u_long*)P = 0;) 6238517Sdfr */ 6338517Sdfr 6448797Salc/* 6549999Salc * The above functions are expanded inline in the statically-linked 6649999Salc * kernel. Lock prefixes are generated if an SMP kernel is being 6749999Salc * built. 6849999Salc * 6949999Salc * Kernel modules call real functions which are built into the kernel. 7049999Salc * This allows kernel modules to be portable between UP and SMP systems. 7148797Salc */ 7249999Salc#if defined(KLD_MODULE) 7388117Sjhb#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 74100251Smarkmvoid atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 7549999Salc 7666695Sjhbint atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); 7765514Sphk 7871085Sjhb#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 7971085Sjhbu_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 80100251Smarkmvoid atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 8171085Sjhb 8249999Salc#else /* !KLD_MODULE */ 8372358Smarkm 8484679Sjhb/* 8584679Sjhb * For userland, assume the SMP case and use lock prefixes so that 8684679Sjhb * the binaries will run on both types of systems. 8784679Sjhb */ 8884679Sjhb#if defined(SMP) || !defined(_KERNEL) 8991469Sbmilekic#define MPLOCKED lock ; 9090515Sbde#else 9148797Salc#define MPLOCKED 9290515Sbde#endif 9338517Sdfr 9448797Salc/* 9548797Salc * The assembly is volatilized to demark potential before-and-after side 9648797Salc * effects if an interrupt or SMP collision were to occur. 9748797Salc */ 98100251Smarkm#ifdef __GNUC__ 9988117Sjhb#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 10048797Salcstatic __inline void \ 10149043Salcatomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 10248797Salc{ \ 10391469Sbmilekic __asm __volatile(__XSTRING(MPLOCKED) OP \ 10486301Sjhb : "+m" (*p) \ 10588117Sjhb : CONS (V)); \ 10648797Salc} 107100251Smarkm#else /* !__GNUC__ */ 108100251Smarkm#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 109100251Smarkmvoid atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 110100251Smarkm#endif /* __GNUC__ */ 11151938Speter 11265514Sphk/* 11365514Sphk * Atomic compare and set, used by the mutex functions 11465514Sphk * 11565514Sphk * if (*dst == exp) *dst = src (all 32 bit words) 11665514Sphk * 11765514Sphk * Returns 0 on failure, non-zero on success 11865514Sphk */ 11965514Sphk 120100251Smarkm#if defined(__GNUC__) 12165514Sphk#if defined(I386_CPU) 12265514Sphkstatic __inline int 12365514Sphkatomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 12465514Sphk{ 12565514Sphk int res = exp; 12665514Sphk 12765514Sphk __asm __volatile( 12865514Sphk " pushfl ; " 12965514Sphk " cli ; " 13086303Sjhb " cmpl %0,%2 ; " 13165514Sphk " jne 1f ; " 13286303Sjhb " movl %1,%2 ; " 13365514Sphk "1: " 13465514Sphk " sete %%al; " 13565514Sphk " movzbl %%al,%0 ; " 13665514Sphk " popfl ; " 13765514Sphk "# atomic_cmpset_int" 13886303Sjhb : "+a" (res) /* 0 (result) */ 13986303Sjhb : "r" (src), /* 1 */ 14086303Sjhb "m" (*(dst)) /* 2 */ 14165514Sphk : "memory"); 14265514Sphk 14365514Sphk return (res); 14465514Sphk} 14565514Sphk#else /* defined(I386_CPU) */ 14665514Sphkstatic __inline int 14765514Sphkatomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 14865514Sphk{ 14965514Sphk int res = exp; 15065514Sphk 15165514Sphk __asm __volatile ( 15291469Sbmilekic " " __XSTRING(MPLOCKED) " " 15386303Sjhb " cmpxchgl %1,%2 ; " 15465514Sphk " setz %%al ; " 15565514Sphk " movzbl %%al,%0 ; " 15665514Sphk "1: " 15765514Sphk "# atomic_cmpset_int" 15886303Sjhb : "+a" (res) /* 0 (result) */ 15986303Sjhb : "r" (src), /* 1 */ 16086303Sjhb "m" (*(dst)) /* 2 */ 16165514Sphk : "memory"); 16265514Sphk 16365514Sphk return (res); 16465514Sphk} 16565514Sphk#endif /* defined(I386_CPU) */ 166100251Smarkm#else /* !defined(__GNUC__) */ 167100251Smarkmstatic __inline int 168100251Smarkmatomic_cmpset_int(volatile u_int *dst __unused, u_int exp __unused, 169100251Smarkm u_int src __unused) 170100251Smarkm{ 171100251Smarkm} 172100251Smarkm#endif /* defined(__GNUC__) */ 17365514Sphk 174100251Smarkm#if defined(__GNUC__) 17571023Sjhb#if defined(I386_CPU) 17667351Sjhb/* 17767351Sjhb * We assume that a = b will do atomic loads and stores. 17871023Sjhb * 17971023Sjhb * XXX: This is _NOT_ safe on a P6 or higher because it does not guarantee 18071023Sjhb * memory ordering. These should only be used on a 386. 18167351Sjhb */ 18271023Sjhb#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 18367351Sjhbstatic __inline u_##TYPE \ 18467351Sjhbatomic_load_acq_##TYPE(volatile u_##TYPE *p) \ 18567351Sjhb{ \ 18667351Sjhb return (*p); \ 18767351Sjhb} \ 18867351Sjhb \ 18967351Sjhbstatic __inline void \ 19067351Sjhbatomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 19167351Sjhb{ \ 19267351Sjhb *p = v; \ 19367351Sjhb __asm __volatile("" : : : "memory"); \ 19467351Sjhb} 195100251Smarkm#else /* !defined(I386_CPU) */ 19667351Sjhb 19771023Sjhb#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 19871023Sjhbstatic __inline u_##TYPE \ 19971023Sjhbatomic_load_acq_##TYPE(volatile u_##TYPE *p) \ 20071023Sjhb{ \ 20171023Sjhb u_##TYPE res; \ 20271023Sjhb \ 20391469Sbmilekic __asm __volatile(__XSTRING(MPLOCKED) LOP \ 20471141Sjhb : "=a" (res), /* 0 (result) */\ 20571023Sjhb "+m" (*p) /* 1 */ \ 20688117Sjhb : : "memory"); \ 20771023Sjhb \ 20871023Sjhb return (res); \ 20971023Sjhb} \ 21071023Sjhb \ 21171023Sjhb/* \ 21271023Sjhb * The XCHG instruction asserts LOCK automagically. \ 21371023Sjhb */ \ 21471023Sjhbstatic __inline void \ 21571023Sjhbatomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 21671023Sjhb{ \ 21771023Sjhb __asm __volatile(SOP \ 21871023Sjhb : "+m" (*p), /* 0 */ \ 21971023Sjhb "+r" (v) /* 1 */ \ 22071023Sjhb : : "memory"); \ 22171023Sjhb} 22271023Sjhb#endif /* defined(I386_CPU) */ 223100251Smarkm#else /* !defined(__GNUC__) */ 224100251Smarkm 225100251Smarkm/* 226100251Smarkm * XXXX: Dummy functions!! 227100251Smarkm */ 228100251Smarkm#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 229100251Smarkmu_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p __unused); \ 230100251Smarkmvoid atomic_store_rel_##TYPE(volatile u_##TYPE *p __unused, \ 231100251Smarkm u_##TYPE v __unused) 232100251Smarkm 233100251Smarkm#endif /* defined(__GNUC__) */ 23471085Sjhb#endif /* KLD_MODULE */ 23567351Sjhb 236100251SmarkmATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); 237100251SmarkmATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); 238100251SmarkmATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); 239100251SmarkmATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); 24071085Sjhb 241100251SmarkmATOMIC_ASM(set, short, "orw %w1,%0", "ir", v); 242100251SmarkmATOMIC_ASM(clear, short, "andw %w1,%0", "ir", ~v); 243100251SmarkmATOMIC_ASM(add, short, "addw %w1,%0", "ir", v); 244100251SmarkmATOMIC_ASM(subtract, short, "subw %w1,%0", "ir", v); 24571085Sjhb 246100251SmarkmATOMIC_ASM(set, int, "orl %1,%0", "ir", v); 247100251SmarkmATOMIC_ASM(clear, int, "andl %1,%0", "ir", ~v); 248100251SmarkmATOMIC_ASM(add, int, "addl %1,%0", "ir", v); 249100251SmarkmATOMIC_ASM(subtract, int, "subl %1,%0", "ir", v); 25071085Sjhb 251100251SmarkmATOMIC_ASM(set, long, "orl %1,%0", "ir", v); 252100251SmarkmATOMIC_ASM(clear, long, "andl %1,%0", "ir", ~v); 253100251SmarkmATOMIC_ASM(add, long, "addl %1,%0", "ir", v); 254100251SmarkmATOMIC_ASM(subtract, long, "subl %1,%0", "ir", v); 25571085Sjhb 256100251SmarkmATOMIC_STORE_LOAD(char, "cmpxchgb %b0,%1", "xchgb %b1,%0"); 257100251SmarkmATOMIC_STORE_LOAD(short,"cmpxchgw %w0,%1", "xchgw %w1,%0"); 258100251SmarkmATOMIC_STORE_LOAD(int, "cmpxchgl %0,%1", "xchgl %1,%0"); 259100251SmarkmATOMIC_STORE_LOAD(long, "cmpxchgl %0,%1", "xchgl %1,%0"); 26071023Sjhb 26171085Sjhb#undef ATOMIC_ASM 26267351Sjhb#undef ATOMIC_STORE_LOAD 26367351Sjhb 26471085Sjhb#define atomic_set_acq_char atomic_set_char 26571085Sjhb#define atomic_set_rel_char atomic_set_char 26671085Sjhb#define atomic_clear_acq_char atomic_clear_char 26771085Sjhb#define atomic_clear_rel_char atomic_clear_char 26871085Sjhb#define atomic_add_acq_char atomic_add_char 26971085Sjhb#define atomic_add_rel_char atomic_add_char 27071085Sjhb#define atomic_subtract_acq_char atomic_subtract_char 27171085Sjhb#define atomic_subtract_rel_char atomic_subtract_char 27271085Sjhb 27371085Sjhb#define atomic_set_acq_short atomic_set_short 27471085Sjhb#define atomic_set_rel_short atomic_set_short 27571085Sjhb#define atomic_clear_acq_short atomic_clear_short 27671085Sjhb#define atomic_clear_rel_short atomic_clear_short 27771085Sjhb#define atomic_add_acq_short atomic_add_short 27871085Sjhb#define atomic_add_rel_short atomic_add_short 27971085Sjhb#define atomic_subtract_acq_short atomic_subtract_short 28071085Sjhb#define atomic_subtract_rel_short atomic_subtract_short 28171085Sjhb 28271085Sjhb#define atomic_set_acq_int atomic_set_int 28371085Sjhb#define atomic_set_rel_int atomic_set_int 28471085Sjhb#define atomic_clear_acq_int atomic_clear_int 28571085Sjhb#define atomic_clear_rel_int atomic_clear_int 28671085Sjhb#define atomic_add_acq_int atomic_add_int 28771085Sjhb#define atomic_add_rel_int atomic_add_int 28871085Sjhb#define atomic_subtract_acq_int atomic_subtract_int 28971085Sjhb#define atomic_subtract_rel_int atomic_subtract_int 29071085Sjhb#define atomic_cmpset_acq_int atomic_cmpset_int 29171085Sjhb#define atomic_cmpset_rel_int atomic_cmpset_int 29271085Sjhb 29371085Sjhb#define atomic_set_acq_long atomic_set_long 29471085Sjhb#define atomic_set_rel_long atomic_set_long 29571085Sjhb#define atomic_clear_acq_long atomic_clear_long 29671085Sjhb#define atomic_clear_rel_long atomic_clear_long 29771085Sjhb#define atomic_add_acq_long atomic_add_long 29871085Sjhb#define atomic_add_rel_long atomic_add_long 29971085Sjhb#define atomic_subtract_acq_long atomic_subtract_long 30071085Sjhb#define atomic_subtract_rel_long atomic_subtract_long 30171085Sjhb#define atomic_cmpset_long atomic_cmpset_int 30271085Sjhb#define atomic_cmpset_acq_long atomic_cmpset_acq_int 30371085Sjhb#define atomic_cmpset_rel_long atomic_cmpset_rel_int 30471085Sjhb 30571085Sjhb#define atomic_cmpset_acq_ptr atomic_cmpset_ptr 30671085Sjhb#define atomic_cmpset_rel_ptr atomic_cmpset_ptr 30771085Sjhb 30871085Sjhb#define atomic_set_8 atomic_set_char 30971085Sjhb#define atomic_set_acq_8 atomic_set_acq_char 31071085Sjhb#define atomic_set_rel_8 atomic_set_rel_char 31171085Sjhb#define atomic_clear_8 atomic_clear_char 31271085Sjhb#define atomic_clear_acq_8 atomic_clear_acq_char 31371085Sjhb#define atomic_clear_rel_8 atomic_clear_rel_char 31471085Sjhb#define atomic_add_8 atomic_add_char 31571085Sjhb#define atomic_add_acq_8 atomic_add_acq_char 31671085Sjhb#define atomic_add_rel_8 atomic_add_rel_char 31771085Sjhb#define atomic_subtract_8 atomic_subtract_char 31871085Sjhb#define atomic_subtract_acq_8 atomic_subtract_acq_char 31971085Sjhb#define atomic_subtract_rel_8 atomic_subtract_rel_char 32071085Sjhb#define atomic_load_acq_8 atomic_load_acq_char 32171085Sjhb#define atomic_store_rel_8 atomic_store_rel_char 32271085Sjhb 32371085Sjhb#define atomic_set_16 atomic_set_short 32471085Sjhb#define atomic_set_acq_16 atomic_set_acq_short 32571085Sjhb#define atomic_set_rel_16 atomic_set_rel_short 32671085Sjhb#define atomic_clear_16 atomic_clear_short 32771085Sjhb#define atomic_clear_acq_16 atomic_clear_acq_short 32871085Sjhb#define atomic_clear_rel_16 atomic_clear_rel_short 32971085Sjhb#define atomic_add_16 atomic_add_short 33071085Sjhb#define atomic_add_acq_16 atomic_add_acq_short 33171085Sjhb#define atomic_add_rel_16 atomic_add_rel_short 33271085Sjhb#define atomic_subtract_16 atomic_subtract_short 33371085Sjhb#define atomic_subtract_acq_16 atomic_subtract_acq_short 33471085Sjhb#define atomic_subtract_rel_16 atomic_subtract_rel_short 33571085Sjhb#define atomic_load_acq_16 atomic_load_acq_short 33671085Sjhb#define atomic_store_rel_16 atomic_store_rel_short 33771085Sjhb 33871085Sjhb#define atomic_set_32 atomic_set_int 33971085Sjhb#define atomic_set_acq_32 atomic_set_acq_int 34071085Sjhb#define atomic_set_rel_32 atomic_set_rel_int 34171085Sjhb#define atomic_clear_32 atomic_clear_int 34271085Sjhb#define atomic_clear_acq_32 atomic_clear_acq_int 34371085Sjhb#define atomic_clear_rel_32 atomic_clear_rel_int 34471085Sjhb#define atomic_add_32 atomic_add_int 34571085Sjhb#define atomic_add_acq_32 atomic_add_acq_int 34671085Sjhb#define atomic_add_rel_32 atomic_add_rel_int 34771085Sjhb#define atomic_subtract_32 atomic_subtract_int 34871085Sjhb#define atomic_subtract_acq_32 atomic_subtract_acq_int 34971085Sjhb#define atomic_subtract_rel_32 atomic_subtract_rel_int 35071085Sjhb#define atomic_load_acq_32 atomic_load_acq_int 35171085Sjhb#define atomic_store_rel_32 atomic_store_rel_int 35271085Sjhb#define atomic_cmpset_32 atomic_cmpset_int 35371085Sjhb#define atomic_cmpset_acq_32 atomic_cmpset_acq_int 35471085Sjhb#define atomic_cmpset_rel_32 atomic_cmpset_rel_int 35571085Sjhb#define atomic_readandclear_32 atomic_readandclear_int 35671085Sjhb 35771085Sjhb#if !defined(WANT_FUNCTIONS) 35865514Sphkstatic __inline int 35965514Sphkatomic_cmpset_ptr(volatile void *dst, void *exp, void *src) 36065514Sphk{ 36165514Sphk 36271085Sjhb return (atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, 36371085Sjhb (u_int)src)); 36465514Sphk} 36566695Sjhb 36667351Sjhbstatic __inline void * 36767351Sjhbatomic_load_acq_ptr(volatile void *p) 36867351Sjhb{ 36967351Sjhb return (void *)atomic_load_acq_int((volatile u_int *)p); 37067351Sjhb} 37167351Sjhb 37267351Sjhbstatic __inline void 37367351Sjhbatomic_store_rel_ptr(volatile void *p, void *v) 37467351Sjhb{ 37567351Sjhb atomic_store_rel_int((volatile u_int *)p, (u_int)v); 37667351Sjhb} 37767351Sjhb 37867351Sjhb#define ATOMIC_PTR(NAME) \ 37967351Sjhbstatic __inline void \ 38067351Sjhbatomic_##NAME##_ptr(volatile void *p, uintptr_t v) \ 38167351Sjhb{ \ 38267351Sjhb atomic_##NAME##_int((volatile u_int *)p, v); \ 38367351Sjhb} \ 38467351Sjhb \ 38567351Sjhbstatic __inline void \ 38667351Sjhbatomic_##NAME##_acq_ptr(volatile void *p, uintptr_t v) \ 38767351Sjhb{ \ 38867351Sjhb atomic_##NAME##_acq_int((volatile u_int *)p, v);\ 38967351Sjhb} \ 39067351Sjhb \ 39167351Sjhbstatic __inline void \ 39267351Sjhbatomic_##NAME##_rel_ptr(volatile void *p, uintptr_t v) \ 39367351Sjhb{ \ 39467351Sjhb atomic_##NAME##_rel_int((volatile u_int *)p, v);\ 39567351Sjhb} 39667351Sjhb 39767351SjhbATOMIC_PTR(set) 39867351SjhbATOMIC_PTR(clear) 39967351SjhbATOMIC_PTR(add) 40067351SjhbATOMIC_PTR(subtract) 40167351Sjhb 40267351Sjhb#undef ATOMIC_PTR 40367351Sjhb 404100251Smarkm#if defined(__GNUC__) 40566695Sjhbstatic __inline u_int 40666695Sjhbatomic_readandclear_int(volatile u_int *addr) 40766695Sjhb{ 40866695Sjhb u_int result; 40966695Sjhb 41066695Sjhb __asm __volatile ( 41166695Sjhb " xorl %0,%0 ; " 41266695Sjhb " xchgl %1,%0 ; " 41366695Sjhb "# atomic_readandclear_int" 41466695Sjhb : "=&r" (result) /* 0 (result) */ 41566695Sjhb : "m" (*addr)); /* 1 (addr) */ 41666695Sjhb 41766695Sjhb return (result); 41866695Sjhb} 419100251Smarkm#else /* !defined(__GNUC__) */ 420100251Smarkm/* 421100251Smarkm * XXXX: Dummy! 422100251Smarkm */ 423100251Smarkmstatic __inline u_int 424100251Smarkmatomic_readandclear_int(volatile u_int *addr __unused) 425100251Smarkm{ 426100251Smarkm} 427100251Smarkm#endif /* defined(__GNUC__) */ 42866695Sjhb 429100251Smarkm#if defined(__GNUC__) 43066695Sjhbstatic __inline u_long 43166695Sjhbatomic_readandclear_long(volatile u_long *addr) 43266695Sjhb{ 43366695Sjhb u_long result; 43466695Sjhb 43566695Sjhb __asm __volatile ( 43666695Sjhb " xorl %0,%0 ; " 43766695Sjhb " xchgl %1,%0 ; " 43866695Sjhb "# atomic_readandclear_int" 43966695Sjhb : "=&r" (result) /* 0 (result) */ 44066695Sjhb : "m" (*addr)); /* 1 (addr) */ 44166695Sjhb 44266695Sjhb return (result); 44366695Sjhb} 444100251Smarkm#else /* !defined(__GNUC__) */ 445100251Smarkm/* 446100251Smarkm * XXXX: Dummy! 447100251Smarkm */ 448100251Smarkmstatic __inline u_long 449100251Smarkmatomic_readandclear_long(volatile u_long *addr __unused) 450100251Smarkm{ 451100251Smarkm} 452100251Smarkm#endif /* defined(__GNUC__) */ 45371085Sjhb#endif /* !defined(WANT_FUNCTIONS) */ 45438517Sdfr#endif /* ! _MACHINE_ATOMIC_H_ */ 455