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
__atomic_enter(void)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
__atomic_leave(unsigned int sr)24 __atomic_leave(unsigned int sr)
25 {
26 asm volatile ("ldc %0, sr" : : "r"(sr));
27 }
28
29 static inline unsigned int
_atomic_cas_uint(volatile unsigned int * uip,unsigned int o,unsigned int n)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
_atomic_cas_ulong(volatile unsigned long * uip,unsigned long o,unsigned long n)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 *
_atomic_cas_ptr(volatile void * uip,void * o,void * n)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
_atomic_swap_uint(volatile unsigned int * uip,unsigned int n)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
_atomic_swap_ulong(volatile unsigned long * uip,unsigned long n)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 *
_atomic_swap_ptr(volatile void * uip,void * n)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
_atomic_add_int_nv(volatile unsigned int * uip,unsigned int v)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
_atomic_add_long_nv(volatile unsigned long * uip,unsigned long v)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
_atomic_sub_int_nv(volatile unsigned int * uip,unsigned int v)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
_atomic_sub_long_nv(volatile unsigned long * uip,unsigned long v)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
atomic_setbits_int(volatile unsigned int * uip,unsigned int v)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
atomic_clearbits_int(volatile unsigned int * uip,unsigned int v)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