xref: /openbsd/sys/arch/alpha/include/atomic.h (revision 2df76cc2)
1 /*	$OpenBSD: atomic.h,v 1.12 2014/03/29 18:09:28 guenther Exp $	*/
2 /* $NetBSD: atomic.h,v 1.7 2001/12/17 23:34:57 thorpej Exp $ */
3 
4 /*-
5  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Misc. `atomic' operations.
36  */
37 
38 #ifndef _MACHINE_ATOMIC_H_
39 #define	_MACHINE_ATOMIC_H_
40 
41 #if defined(_KERNEL)
42 
43 /*
44  * atomic_setbits_ulong:
45  *
46  *	Atomically set bits in a `unsigned long'.
47  */
48 static __inline void
atomic_setbits_ulong(volatile unsigned long * ulp,unsigned long v)49 atomic_setbits_ulong(volatile unsigned long *ulp, unsigned long v)
50 {
51 	unsigned long t0;
52 
53 	__asm volatile(
54 		"# BEGIN atomic_setbits_ulong\n"
55 		"1:	ldq_l	%0, %1		\n"
56 		"	or	%0, %2, %0	\n"
57 		"	stq_c	%0, %1		\n"
58 		"	beq	%0, 2f		\n"
59 		"	mb			\n"
60 		"	br	3f		\n"
61 		"2:	br	1b		\n"
62 		"3:				\n"
63 		"	# END atomic_setbits_ulong"
64 		: "=&r" (t0), "=m" (*ulp)
65 		: "r" (v)
66 		: "memory");
67 }
68 
69 /*
70  * atomic_clearbits_ulong:
71  *
72  *	Atomically clear bits in a `unsigned long'.
73  */
74 static __inline void
atomic_clearbits_ulong(volatile unsigned long * ulp,unsigned long v)75 atomic_clearbits_ulong(volatile unsigned long *ulp, unsigned long v)
76 {
77 	unsigned long t0;
78 
79 	__asm volatile(
80 		"# BEGIN atomic_clearbits_ulong\n"
81 		"1:	ldq_l	%0, %1		\n"
82 		"	and	%0, %2, %0	\n"
83 		"	stq_c	%0, %1		\n"
84 		"	beq	%0, 2f		\n"
85 		"	mb			\n"
86 		"	br	3f		\n"
87 		"2:	br	1b		\n"
88 		"3:				\n"
89 		"	# END atomic_clearbits_ulong"
90 		: "=&r" (t0), "=m" (*ulp)
91 		: "r" (~v)
92 		: "memory");
93 }
94 
95 /*
96  * atomic_add_ulong:
97  *
98  *	Atomically add a value to a `unsigned long'.
99  */
100 static __inline void
atomic_add_ulong(volatile unsigned long * ulp,unsigned long v)101 atomic_add_ulong(volatile unsigned long *ulp, unsigned long v)
102 {
103 	unsigned long t0;
104 
105 	__asm volatile(
106 		"# BEGIN atomic_add_ulong\n"
107 		"1:	ldq_l	%0, %1		\n"
108 		"	addq	%0, %2, %0	\n"
109 		"	stq_c	%0, %1		\n"
110 		"	beq	%0, 2f		\n"
111 		"	mb			\n"
112 		"	br	3f		\n"
113 		"2:	br	1b		\n"
114 		"3:				\n"
115 		"	# END atomic_add_ulong"
116 		: "=&r" (t0), "=m" (*ulp)
117 		: "r" (v)
118 		: "memory");
119 }
120 
121 /*
122  * atomic_sub_ulong:
123  *
124  *	Atomically subtract a value from a `unsigned long'.
125  */
126 static __inline void
atomic_sub_ulong(volatile unsigned long * ulp,unsigned long v)127 atomic_sub_ulong(volatile unsigned long *ulp, unsigned long v)
128 {
129 	unsigned long t0;
130 
131 	__asm volatile(
132 		"# BEGIN atomic_sub_ulong\n"
133 		"1:	ldq_l	%0, %1		\n"
134 		"	subq	%0, %2, %0	\n"
135 		"	stq_c	%0, %1		\n"
136 		"	beq	%0, 2f		\n"
137 		"	mb			\n"
138 		"	br	3f		\n"
139 		"2:	br	1b		\n"
140 		"3:				\n"
141 		"	# END atomic_sub_ulong"
142 		: "=&r" (t0), "=m" (*ulp)
143 		: "r" (v)
144 		: "memory");
145 }
146 
147 /*
148  * atomic_loadlatch_ulong:
149  *
150  *	Atomically load and latch a `unsigned long' value.
151  */
152 static __inline unsigned long
atomic_loadlatch_ulong(volatile unsigned long * ulp,unsigned long v)153 atomic_loadlatch_ulong(volatile unsigned long *ulp, unsigned long v)
154 {
155 	unsigned long t0, v0;
156 
157 	__asm volatile(
158 		"# BEGIN atomic_loadlatch_ulong\n"
159 		"1:	mov	%3, %0		\n"
160 		"	ldq_l	%1, %2		\n"
161 		"	stq_c	%0, %2		\n"
162 		"	beq	%0, 2f		\n"
163 		"	mb			\n"
164 		"	br	3f		\n"
165 		"2:	br	1b		\n"
166 		"3:				\n"
167 		"	# END atomic_loadlatch_ulong"
168 		: "=&r" (t0), "=r" (v0), "=m" (*ulp)
169 		: "r" (v)
170 		: "memory");
171 
172 	return (v0);
173 }
174 
175 /*
176  * atomic_setbits_int:
177  *
178  *	Atomically set bits in a `unsigned int'.
179  */
180 static __inline void
atomic_setbits_int(volatile unsigned int * uip,unsigned int v)181 atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
182 {
183 	unsigned int t0;
184 
185 	__asm volatile(
186 		"# BEGIN atomic_setbits_ulong\n"
187 		"1:	ldl_l	%0, %1		\n"
188 		"	or	%0, %2, %0	\n"
189 		"	stl_c	%0, %1		\n"
190 		"	beq	%0, 2f		\n"
191 		"	mb			\n"
192 		"	br	3f		\n"
193 		"2:	br	1b		\n"
194 		"3:				\n"
195 		"	# END atomic_setbits_int"
196 		: "=&r" (t0), "=m" (*uip)
197 		: "r" (v)
198 		: "memory");
199 }
200 
201 /*
202  * atomic_clearbits_int:
203  *
204  *	Atomically clear bits in a `unsigned int'.
205  */
206 static __inline void
atomic_clearbits_int(volatile unsigned int * uip,unsigned int v)207 atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
208 {
209 	unsigned int t0;
210 
211 	__asm volatile(
212 		"# BEGIN atomic_clearbits_int\n"
213 		"1:	ldl_l	%0, %1		\n"
214 		"	and	%0, %2, %0	\n"
215 		"	stl_c	%0, %1		\n"
216 		"	beq	%0, 2f		\n"
217 		"	mb			\n"
218 		"	br	3f		\n"
219 		"2:	br	1b		\n"
220 		"3:				\n"
221 		"	# END atomic_clearbits_int"
222 		: "=&r" (t0), "=m" (*uip)
223 		: "r" (~v)
224 		: "memory");
225 }
226 
227 /*
228  * atomic_add_int:
229  *
230  *	Atomically add a value to an `int'.
231  */
232 static __inline void
atomic_add_int(volatile int * ulp,int v)233 atomic_add_int(volatile int *ulp, int v)
234 {
235 	unsigned long t0;
236 
237 	__asm volatile(
238 		"# BEGIN atomic_add_int\n"
239 		"1:	ldl_l	%0, %1		\n"
240 		"	addl	%0, %2, %0	\n"
241 		"	stl_c	%0, %1		\n"
242 		"	beq	%0, 2f		\n"
243 		"	mb			\n"
244 		"	br	3f		\n"
245 		"2:	br	1b		\n"
246 		"3:				\n"
247 		"	# END atomic_add_ulong"
248 		: "=&r" (t0), "=m" (*ulp)
249 		: "r" (v)
250 		: "memory");
251 }
252 
253 #endif /* defined(_KERNEL) */
254 #endif /* _MACHINE_ATOMIC_H_ */
255