1 /* $OpenBSD: atomic.h,v 1.13 2014/07/18 10:40:14 dlg Exp $ */ 2 /* $NetBSD: atomic.h,v 1.1 2003/04/26 18:39:37 fvdl Exp $ */ 3 4 /* 5 * Copyright 2002 (c) Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Frank van der Linden for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #ifndef _MACHINE_ATOMIC_H_ 40 #define _MACHINE_ATOMIC_H_ 41 42 /* 43 * Perform atomic operations on memory. Should be atomic with respect 44 * to interrupts and multiple processors. 45 * 46 * void atomic_setbits_int(volatile u_int *a, u_int mask) { *a |= mask; } 47 * void atomic_clearbits_int(volatile u_int *a, u_int mas) { *a &= ~mask; } 48 */ 49 50 #if defined(_KERNEL) && !defined(_LOCORE) 51 52 #ifdef MULTIPROCESSOR 53 #define LOCK "lock" 54 #else 55 #define LOCK 56 #endif 57 58 static inline unsigned int 59 _atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) 60 { 61 __asm volatile(LOCK " cmpxchgl %2, %1" 62 : "=a" (n), "=m" (*p) 63 : "r" (n), "a" (e), "m" (*p) 64 : "memory"); 65 66 return (n); 67 } 68 #define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) 69 70 static inline unsigned long 71 _atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) 72 { 73 __asm volatile(LOCK " cmpxchgq %2, %1" 74 : "=a" (n), "=m" (*p) 75 : "r" (n), "a" (e), "m" (*p) 76 : "memory"); 77 78 return (n); 79 } 80 #define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) 81 82 static inline void * 83 _atomic_cas_ptr(volatile void *p, void *e, void *n) 84 { 85 __asm volatile(LOCK " cmpxchgq %2, %1" 86 : "=a" (n), "=m" (*(unsigned long *)p) 87 : "r" (n), "a" (e), "m" (*(unsigned long *)p) 88 : "memory"); 89 90 return (n); 91 } 92 #define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) 93 94 static __inline u_int64_t 95 x86_atomic_testset_u64(volatile u_int64_t *ptr, u_int64_t val) 96 { 97 __asm__ volatile ("xchgq %0,(%2)" :"=r" (val):"0" (val),"r" (ptr)); 98 return val; 99 } 100 101 static __inline u_int32_t 102 x86_atomic_testset_u32(volatile u_int32_t *ptr, u_int32_t val) 103 { 104 __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr)); 105 return val; 106 } 107 108 109 static __inline void 110 x86_atomic_setbits_u32(volatile u_int32_t *ptr, u_int32_t bits) 111 { 112 __asm volatile(LOCK " orl %1,%0" : "=m" (*ptr) : "ir" (bits)); 113 } 114 115 static __inline void 116 x86_atomic_clearbits_u32(volatile u_int32_t *ptr, u_int32_t bits) 117 { 118 __asm volatile(LOCK " andl %1,%0" : "=m" (*ptr) : "ir" (~bits)); 119 } 120 121 /* 122 * XXX XXX XXX 123 * theoretically 64bit cannot be used as 124 * an "i" and thus if we ever try to give 125 * these anything from the high dword there 126 * is an asm error pending 127 */ 128 static __inline void 129 x86_atomic_setbits_u64(volatile u_int64_t *ptr, u_int64_t bits) 130 { 131 __asm volatile(LOCK " orq %1,%0" : "=m" (*ptr) : "ir" (bits)); 132 } 133 134 static __inline void 135 x86_atomic_clearbits_u64(volatile u_int64_t *ptr, u_int64_t bits) 136 { 137 __asm volatile(LOCK " andq %1,%0" : "=m" (*ptr) : "ir" (~bits)); 138 } 139 140 #define x86_atomic_testset_ul x86_atomic_testset_u64 141 #define x86_atomic_setbits_ul x86_atomic_setbits_u64 142 #define x86_atomic_clearbits_ul x86_atomic_clearbits_u64 143 144 #define atomic_setbits_int x86_atomic_setbits_u32 145 #define atomic_clearbits_int x86_atomic_clearbits_u32 146 147 #undef LOCK 148 149 #endif /* defined(_KERNEL) && !defined(_LOCORE) */ 150 #endif /* _MACHINE_ATOMIC_H_ */ 151