xref: /openbsd/sys/arch/sh/include/atomic.h (revision 73471bf0)
1 /*	$OpenBSD: atomic.h,v 1.8 2014/11/17 23:51:32 dlg Exp $	*/
2 
3 /* Public Domain */
4 
5 #ifndef _SH_ATOMIC_H_
6 #define _SH_ATOMIC_H_
7 
8 #if defined(_KERNEL)
9 
10 #include <sh/psl.h>
11 
12 static inline unsigned int
13 __atomic_enter(void)
14 {
15 	unsigned int sr;
16 
17 	asm volatile ("stc sr, %0" : "=r"(sr));
18 	asm volatile ("ldc %0, sr" : : "r"(sr | PSL_IMASK));
19 
20 	return (sr);
21 }
22 
23 static inline void
24 __atomic_leave(unsigned int sr)
25 {
26 	asm volatile ("ldc %0, sr" : : "r"(sr));
27 }
28 
29 static inline unsigned int
30 _atomic_cas_uint(volatile unsigned int *uip, unsigned int o, unsigned int n)
31 {
32 	unsigned int sr;
33 	unsigned int rv;
34 
35 	sr = __atomic_enter();
36 	rv = *uip;
37 	if (rv == o)
38 		*uip = n;
39 	__atomic_leave(sr);
40 
41 	return (rv);
42 }
43 #define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n))
44 
45 static inline unsigned long
46 _atomic_cas_ulong(volatile unsigned long *uip, unsigned long o, unsigned long n)
47 {
48 	unsigned int sr;
49 	unsigned long rv;
50 
51 	sr = __atomic_enter();
52 	rv = *uip;
53 	if (rv == o)
54 		*uip = n;
55 	__atomic_leave(sr);
56 
57 	return (rv);
58 }
59 #define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n))
60 
61 static inline void *
62 _atomic_cas_ptr(volatile void *uip, void *o, void *n)
63 {
64 	unsigned int sr;
65 	void * volatile *uipp = (void * volatile *)uip;
66 	void *rv;
67 
68 	sr = __atomic_enter();
69 	rv = *uipp;
70 	if (rv == o)
71 		*uipp = n;
72 	__atomic_leave(sr);
73 
74 	return (rv);
75 }
76 #define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n))
77 
78 static inline unsigned int
79 _atomic_swap_uint(volatile unsigned int *uip, unsigned int n)
80 {
81 	unsigned int sr;
82 	unsigned int rv;
83 
84 	sr = __atomic_enter();
85 	rv = *uip;
86 	*uip = n;
87 	__atomic_leave(sr);
88 
89 	return (rv);
90 }
91 #define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n))
92 
93 static inline unsigned long
94 _atomic_swap_ulong(volatile unsigned long *uip, unsigned long n)
95 {
96 	unsigned int sr;
97 	unsigned long rv;
98 
99 	sr = __atomic_enter();
100 	rv = *uip;
101 	*uip = n;
102 	__atomic_leave(sr);
103 
104 	return (rv);
105 }
106 #define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n))
107 
108 static inline void *
109 _atomic_swap_ptr(volatile void *uip, void *n)
110 {
111 	unsigned int sr;
112 	void * volatile *uipp = (void * volatile *)uip;
113 	void *rv;
114 
115 	sr = __atomic_enter();
116 	rv = *uipp;
117 	*uipp = n;
118 	__atomic_leave(sr);
119 
120 	return (rv);
121 }
122 #define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n))
123 
124 static inline unsigned int
125 _atomic_add_int_nv(volatile unsigned int *uip, unsigned int v)
126 {
127 	unsigned int sr;
128 	unsigned int rv;
129 
130 	sr = __atomic_enter();
131 	rv = *uip + v;
132 	*uip = rv;
133 	__atomic_leave(sr);
134 
135 	return (rv);
136 }
137 #define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v))
138 
139 static inline unsigned long
140 _atomic_add_long_nv(volatile unsigned long *uip, unsigned long v)
141 {
142 	unsigned int sr;
143 	unsigned long rv;
144 
145 	sr = __atomic_enter();
146 	rv = *uip + v;
147 	*uip = rv;
148 	__atomic_leave(sr);
149 
150 	return (rv);
151 }
152 #define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v))
153 
154 static inline unsigned int
155 _atomic_sub_int_nv(volatile unsigned int *uip, unsigned int v)
156 {
157 	unsigned int sr;
158 	unsigned int rv;
159 
160 	sr = __atomic_enter();
161 	rv = *uip - v;
162 	*uip = rv;
163 	__atomic_leave(sr);
164 
165 	return (rv);
166 }
167 #define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v))
168 
169 static inline unsigned long
170 _atomic_sub_long_nv(volatile unsigned long *uip, unsigned long v)
171 {
172 	unsigned int sr;
173 	unsigned long rv;
174 
175 	sr = __atomic_enter();
176 	rv = *uip - v;
177 	*uip = rv;
178 	__atomic_leave(sr);
179 
180 	return (rv);
181 }
182 #define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v))
183 
184 static inline void
185 atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
186 {
187 	unsigned int sr;
188 
189 	sr = __atomic_enter();
190 	*uip |= v;
191 	__atomic_leave(sr);
192 }
193 
194 static inline void
195 atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
196 {
197 	unsigned int sr;
198 
199 	sr = __atomic_enter();
200 	*uip &= ~v;
201 	__atomic_leave(sr);
202 }
203 
204 #endif /* defined(_KERNEL) */
205 #endif /* _SH_ATOMIC_H_ */
206