xref: /openbsd-src/sys/arch/amd64/include/atomic.h (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
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