atomic.h (137784) | atomic.h (143063) |
---|---|
1/*- 2 * Copyright (c) 1998 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 1998 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/i386/include/atomic.h 137784 2004-11-16 20:42:32Z jhb $ | 26 * $FreeBSD: head/sys/i386/include/atomic.h 143063 2005-03-02 21:33:29Z joerg $ |
27 */ 28#ifndef _MACHINE_ATOMIC_H_ 29#define _MACHINE_ATOMIC_H_ 30 | 27 */ 28#ifndef _MACHINE_ATOMIC_H_ 29#define _MACHINE_ATOMIC_H_ 30 |
31#ifndef _SYS_CDEFS_H_ 32#error this file needs sys/cdefs.h as a prerequisite 33#endif 34 |
|
31/* 32 * Various simple arithmetic on memory which is atomic in the presence 33 * of interrupts and multiple processors. 34 * 35 * atomic_set_char(P, V) (*(u_char*)(P) |= (V)) 36 * atomic_clear_char(P, V) (*(u_char*)(P) &= ~(V)) 37 * atomic_add_char(P, V) (*(u_char*)(P) += (V)) 38 * atomic_subtract_char(P, V) (*(u_char*)(P) -= (V)) --- 31 unchanged lines hidden (view full) --- 70int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); 71 72#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 73u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 74void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 75 76#else /* !KLD_MODULE */ 77 | 35/* 36 * Various simple arithmetic on memory which is atomic in the presence 37 * of interrupts and multiple processors. 38 * 39 * atomic_set_char(P, V) (*(u_char*)(P) |= (V)) 40 * atomic_clear_char(P, V) (*(u_char*)(P) &= ~(V)) 41 * atomic_add_char(P, V) (*(u_char*)(P) += (V)) 42 * atomic_subtract_char(P, V) (*(u_char*)(P) -= (V)) --- 31 unchanged lines hidden (view full) --- 74int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); 75 76#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 77u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 78void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 79 80#else /* !KLD_MODULE */ 81 |
78#if defined(__GNUC__) || defined(__INTEL_COMPILER) | 82#ifdef __GNUCLIKE_ASM |
79 80/* 81 * For userland, assume the SMP case and use lock prefixes so that 82 * the binaries will run on both types of systems. 83 */ 84#if defined(SMP) || !defined(_KERNEL) 85#define MPLOCKED lock ; 86#else --- 9 unchanged lines hidden (view full) --- 96atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 97{ \ 98 __asm __volatile(__XSTRING(MPLOCKED) OP \ 99 : "+m" (*p) \ 100 : CONS (V)); \ 101} \ 102struct __hack 103 | 83 84/* 85 * For userland, assume the SMP case and use lock prefixes so that 86 * the binaries will run on both types of systems. 87 */ 88#if defined(SMP) || !defined(_KERNEL) 89#define MPLOCKED lock ; 90#else --- 9 unchanged lines hidden (view full) --- 100atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ 101{ \ 102 __asm __volatile(__XSTRING(MPLOCKED) OP \ 103 : "+m" (*p) \ 104 : CONS (V)); \ 105} \ 106struct __hack 107 |
104#else /* !(__GNUC__ || __INTEL_COMPILER) */ | 108#else /* !__GNUCLIKE_ASM */ |
105 106#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 107extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 108 | 109 110#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ 111extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 112 |
109#endif /* __GNUC__ || __INTEL_COMPILER */ | 113#endif /* __GNUCLIKE_ASM */ |
110 111/* 112 * Atomic compare and set, used by the mutex functions 113 * 114 * if (*dst == exp) *dst = src (all 32 bit words) 115 * 116 * Returns 0 on failure, non-zero on success 117 */ 118 | 114 115/* 116 * Atomic compare and set, used by the mutex functions 117 * 118 * if (*dst == exp) *dst = src (all 32 bit words) 119 * 120 * Returns 0 on failure, non-zero on success 121 */ 122 |
119#if defined(__GNUC__) || defined(__INTEL_COMPILER) | 123#ifdef __GNUCLIKE_ASM |
120 121#if defined(CPU_DISABLE_CMPXCHG) 122 123static __inline int 124atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 125{ 126 int res = exp; 127 --- 35 unchanged lines hidden (view full) --- 163 "m" (*(dst)) /* 2 */ 164 : "memory"); 165 166 return (res); 167} 168 169#endif /* defined(CPU_DISABLE_CMPXCHG) */ 170 | 124 125#if defined(CPU_DISABLE_CMPXCHG) 126 127static __inline int 128atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 129{ 130 int res = exp; 131 --- 35 unchanged lines hidden (view full) --- 167 "m" (*(dst)) /* 2 */ 168 : "memory"); 169 170 return (res); 171} 172 173#endif /* defined(CPU_DISABLE_CMPXCHG) */ 174 |
171#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */ | 175#endif /* __GNUCLIKE_ASM */ |
172 | 176 |
173#if defined(__GNUC__) || defined(__INTEL_COMPILER) | 177#ifdef __GNUCLIKE_ASM |
174 175#if defined(_KERNEL) && !defined(SMP) 176 177/* 178 * We assume that a = b will do atomic loads and stores. However, on a 179 * PentiumPro or higher, reads may pass writes, so for that case we have 180 * to use a serializing instruction (i.e. with LOCK) to do the load in 181 * SMP kernels. For UP kernels, however, the cache of the single processor --- 39 unchanged lines hidden (view full) --- 221 : "+m" (*p), /* 0 */ \ 222 "+r" (v) /* 1 */ \ 223 : : "memory"); \ 224} \ 225struct __hack 226 227#endif /* !defined(SMP) */ 228 | 178 179#if defined(_KERNEL) && !defined(SMP) 180 181/* 182 * We assume that a = b will do atomic loads and stores. However, on a 183 * PentiumPro or higher, reads may pass writes, so for that case we have 184 * to use a serializing instruction (i.e. with LOCK) to do the load in 185 * SMP kernels. For UP kernels, however, the cache of the single processor --- 39 unchanged lines hidden (view full) --- 225 : "+m" (*p), /* 0 */ \ 226 "+r" (v) /* 1 */ \ 227 : : "memory"); \ 228} \ 229struct __hack 230 231#endif /* !defined(SMP) */ 232 |
229#else /* !(defined(__GNUC__) || defined(__INTEL_COMPILER)) */ | 233#else /* !__GNUCLIKE_ASM */ |
230 231extern int atomic_cmpset_int(volatile u_int *, u_int, u_int); 232 233#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 234extern u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 235extern void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 236 | 234 235extern int atomic_cmpset_int(volatile u_int *, u_int, u_int); 236 237#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ 238extern u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ 239extern void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) 240 |
237#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */ | 241#endif /* __GNUCLIKE_ASM */ |
238 239#endif /* KLD_MODULE */ 240 241ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); 242ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); 243ATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); 244ATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); 245 --- 159 unchanged lines hidden (view full) --- 405 406ATOMIC_PTR(set) 407ATOMIC_PTR(clear) 408ATOMIC_PTR(add) 409ATOMIC_PTR(subtract) 410 411#undef ATOMIC_PTR 412 | 242 243#endif /* KLD_MODULE */ 244 245ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); 246ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); 247ATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); 248ATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); 249 --- 159 unchanged lines hidden (view full) --- 409 410ATOMIC_PTR(set) 411ATOMIC_PTR(clear) 412ATOMIC_PTR(add) 413ATOMIC_PTR(subtract) 414 415#undef ATOMIC_PTR 416 |
413#if defined(__GNUC__) || defined(__INTEL_COMPILER) | 417#ifdef __GNUCLIKE_ASM |
414 415static __inline u_int 416atomic_readandclear_int(volatile u_int *addr) 417{ 418 u_int result; 419 420 __asm __volatile ( 421 " xorl %0,%0 ; " --- 15 unchanged lines hidden (view full) --- 437 " xchgl %1,%0 ; " 438 "# atomic_readandclear_int" 439 : "=&r" (result) /* 0 (result) */ 440 : "m" (*addr)); /* 1 (addr) */ 441 442 return (result); 443} 444 | 418 419static __inline u_int 420atomic_readandclear_int(volatile u_int *addr) 421{ 422 u_int result; 423 424 __asm __volatile ( 425 " xorl %0,%0 ; " --- 15 unchanged lines hidden (view full) --- 441 " xchgl %1,%0 ; " 442 "# atomic_readandclear_int" 443 : "=&r" (result) /* 0 (result) */ 444 : "m" (*addr)); /* 1 (addr) */ 445 446 return (result); 447} 448 |
445#else /* !(defined(__GNUC__) || defined(__INTEL_COMPILER)) */ | 449#else /* !__GNUCLIKE_ASM */ |
446 447extern u_long atomic_readandclear_long(volatile u_long *); 448extern u_int atomic_readandclear_int(volatile u_int *); 449 | 450 451extern u_long atomic_readandclear_long(volatile u_long *); 452extern u_int atomic_readandclear_int(volatile u_int *); 453 |
450#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */ | 454#endif /* __GNUCLIKE_ASM */ |
451 452#endif /* !defined(WANT_FUNCTIONS) */ 453#endif /* ! _MACHINE_ATOMIC_H_ */ | 455 456#endif /* !defined(WANT_FUNCTIONS) */ 457#endif /* ! _MACHINE_ATOMIC_H_ */ |