xref: /openbsd-src/sys/arch/sh/include/atomic.h (revision 819f0be94114611f9b6d03cc78303c0e5dbf0726)
1*819f0be9Sdlg /*	$OpenBSD: atomic.h,v 1.8 2014/11/17 23:51:32 dlg Exp $	*/
2f57756c9Sart 
3f57756c9Sart /* Public Domain */
4f57756c9Sart 
52fa72412Spirofti #ifndef _SH_ATOMIC_H_
62fa72412Spirofti #define _SH_ATOMIC_H_
7f57756c9Sart 
88aa3ef09Sderaadt #if defined(_KERNEL)
98aa3ef09Sderaadt 
1032f529edSmiod #include <sh/psl.h>
1132f529edSmiod 
123c62c4c0Sdlg static inline unsigned int
__atomic_enter(void)133c62c4c0Sdlg __atomic_enter(void)
143c62c4c0Sdlg {
153c62c4c0Sdlg 	unsigned int sr;
163c62c4c0Sdlg 
173c62c4c0Sdlg 	asm volatile ("stc sr, %0" : "=r"(sr));
183c62c4c0Sdlg 	asm volatile ("ldc %0, sr" : : "r"(sr | PSL_IMASK));
193c62c4c0Sdlg 
203c62c4c0Sdlg 	return (sr);
213c62c4c0Sdlg }
223c62c4c0Sdlg 
233c62c4c0Sdlg static inline void
__atomic_leave(unsigned int sr)243c62c4c0Sdlg __atomic_leave(unsigned int sr)
253c62c4c0Sdlg {
263c62c4c0Sdlg 	asm volatile ("ldc %0, sr" : : "r"(sr));
273c62c4c0Sdlg }
283c62c4c0Sdlg 
293c62c4c0Sdlg static inline unsigned int
_atomic_cas_uint(volatile unsigned int * uip,unsigned int o,unsigned int n)30*819f0be9Sdlg _atomic_cas_uint(volatile unsigned int *uip, unsigned int o, unsigned int n)
313c62c4c0Sdlg {
323c62c4c0Sdlg 	unsigned int sr;
333c62c4c0Sdlg 	unsigned int rv;
343c62c4c0Sdlg 
353c62c4c0Sdlg 	sr = __atomic_enter();
363c62c4c0Sdlg 	rv = *uip;
373c62c4c0Sdlg 	if (rv == o)
383c62c4c0Sdlg 		*uip = n;
393c62c4c0Sdlg 	__atomic_leave(sr);
403c62c4c0Sdlg 
413c62c4c0Sdlg 	return (rv);
423c62c4c0Sdlg }
43*819f0be9Sdlg #define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n))
44*819f0be9Sdlg 
45*819f0be9Sdlg static inline unsigned long
_atomic_cas_ulong(volatile unsigned long * uip,unsigned long o,unsigned long n)46*819f0be9Sdlg _atomic_cas_ulong(volatile unsigned long *uip, unsigned long o, unsigned long n)
47*819f0be9Sdlg {
48*819f0be9Sdlg 	unsigned int sr;
49*819f0be9Sdlg 	unsigned long rv;
50*819f0be9Sdlg 
51*819f0be9Sdlg 	sr = __atomic_enter();
52*819f0be9Sdlg 	rv = *uip;
53*819f0be9Sdlg 	if (rv == o)
54*819f0be9Sdlg 		*uip = n;
55*819f0be9Sdlg 	__atomic_leave(sr);
56*819f0be9Sdlg 
57*819f0be9Sdlg 	return (rv);
58*819f0be9Sdlg }
59*819f0be9Sdlg #define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n))
603c62c4c0Sdlg 
613c62c4c0Sdlg static inline void *
_atomic_cas_ptr(volatile void * uip,void * o,void * n)623c62c4c0Sdlg _atomic_cas_ptr(volatile void *uip, void *o, void *n)
633c62c4c0Sdlg {
643c62c4c0Sdlg 	unsigned int sr;
653c62c4c0Sdlg 	void * volatile *uipp = (void * volatile *)uip;
663c62c4c0Sdlg 	void *rv;
673c62c4c0Sdlg 
683c62c4c0Sdlg 	sr = __atomic_enter();
693c62c4c0Sdlg 	rv = *uipp;
703c62c4c0Sdlg 	if (rv == o)
713c62c4c0Sdlg 		*uipp = n;
723c62c4c0Sdlg 	__atomic_leave(sr);
733c62c4c0Sdlg 
743c62c4c0Sdlg 	return (rv);
753c62c4c0Sdlg }
763c62c4c0Sdlg #define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n))
773c62c4c0Sdlg 
783c62c4c0Sdlg static inline unsigned int
_atomic_swap_uint(volatile unsigned int * uip,unsigned int n)79*819f0be9Sdlg _atomic_swap_uint(volatile unsigned int *uip, unsigned int n)
803c62c4c0Sdlg {
813c62c4c0Sdlg 	unsigned int sr;
823c62c4c0Sdlg 	unsigned int rv;
833c62c4c0Sdlg 
843c62c4c0Sdlg 	sr = __atomic_enter();
853c62c4c0Sdlg 	rv = *uip;
863c62c4c0Sdlg 	*uip = n;
873c62c4c0Sdlg 	__atomic_leave(sr);
883c62c4c0Sdlg 
893c62c4c0Sdlg 	return (rv);
903c62c4c0Sdlg }
91*819f0be9Sdlg #define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n))
92*819f0be9Sdlg 
93*819f0be9Sdlg static inline unsigned long
_atomic_swap_ulong(volatile unsigned long * uip,unsigned long n)94*819f0be9Sdlg _atomic_swap_ulong(volatile unsigned long *uip, unsigned long n)
95*819f0be9Sdlg {
96*819f0be9Sdlg 	unsigned int sr;
97*819f0be9Sdlg 	unsigned long rv;
98*819f0be9Sdlg 
99*819f0be9Sdlg 	sr = __atomic_enter();
100*819f0be9Sdlg 	rv = *uip;
101*819f0be9Sdlg 	*uip = n;
102*819f0be9Sdlg 	__atomic_leave(sr);
103*819f0be9Sdlg 
104*819f0be9Sdlg 	return (rv);
105*819f0be9Sdlg }
106*819f0be9Sdlg #define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n))
1073c62c4c0Sdlg 
1083c62c4c0Sdlg static inline void *
_atomic_swap_ptr(volatile void * uip,void * n)1093c62c4c0Sdlg _atomic_swap_ptr(volatile void *uip, void *n)
1103c62c4c0Sdlg {
1113c62c4c0Sdlg 	unsigned int sr;
1123c62c4c0Sdlg 	void * volatile *uipp = (void * volatile *)uip;
1133c62c4c0Sdlg 	void *rv;
1143c62c4c0Sdlg 
1153c62c4c0Sdlg 	sr = __atomic_enter();
1163c62c4c0Sdlg 	rv = *uipp;
1173c62c4c0Sdlg 	*uipp = n;
1183c62c4c0Sdlg 	__atomic_leave(sr);
1193c62c4c0Sdlg 
1203c62c4c0Sdlg 	return (rv);
1213c62c4c0Sdlg }
122bf00727dSdlg #define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n))
1233c62c4c0Sdlg 
1243c62c4c0Sdlg static inline unsigned int
_atomic_add_int_nv(volatile unsigned int * uip,unsigned int v)125*819f0be9Sdlg _atomic_add_int_nv(volatile unsigned int *uip, unsigned int v)
1263c62c4c0Sdlg {
1273c62c4c0Sdlg 	unsigned int sr;
1283c62c4c0Sdlg 	unsigned int rv;
1293c62c4c0Sdlg 
1303c62c4c0Sdlg 	sr = __atomic_enter();
1313c62c4c0Sdlg 	rv = *uip + v;
1323c62c4c0Sdlg 	*uip = rv;
1333c62c4c0Sdlg 	__atomic_leave(sr);
1343c62c4c0Sdlg 
1353c62c4c0Sdlg 	return (rv);
1363c62c4c0Sdlg }
137*819f0be9Sdlg #define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v))
138*819f0be9Sdlg 
139*819f0be9Sdlg static inline unsigned long
_atomic_add_long_nv(volatile unsigned long * uip,unsigned long v)140*819f0be9Sdlg _atomic_add_long_nv(volatile unsigned long *uip, unsigned long v)
141*819f0be9Sdlg {
142*819f0be9Sdlg 	unsigned int sr;
143*819f0be9Sdlg 	unsigned long rv;
144*819f0be9Sdlg 
145*819f0be9Sdlg 	sr = __atomic_enter();
146*819f0be9Sdlg 	rv = *uip + v;
147*819f0be9Sdlg 	*uip = rv;
148*819f0be9Sdlg 	__atomic_leave(sr);
149*819f0be9Sdlg 
150*819f0be9Sdlg 	return (rv);
151*819f0be9Sdlg }
152*819f0be9Sdlg #define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v))
1533c62c4c0Sdlg 
1543c62c4c0Sdlg static inline unsigned int
_atomic_sub_int_nv(volatile unsigned int * uip,unsigned int v)155*819f0be9Sdlg _atomic_sub_int_nv(volatile unsigned int *uip, unsigned int v)
1563c62c4c0Sdlg {
1573c62c4c0Sdlg 	unsigned int sr;
1583c62c4c0Sdlg 	unsigned int rv;
1593c62c4c0Sdlg 
1603c62c4c0Sdlg 	sr = __atomic_enter();
1613c62c4c0Sdlg 	rv = *uip - v;
1623c62c4c0Sdlg 	*uip = rv;
1633c62c4c0Sdlg 	__atomic_leave(sr);
1643c62c4c0Sdlg 
1653c62c4c0Sdlg 	return (rv);
1663c62c4c0Sdlg }
167*819f0be9Sdlg #define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v))
168*819f0be9Sdlg 
169*819f0be9Sdlg static inline unsigned long
_atomic_sub_long_nv(volatile unsigned long * uip,unsigned long v)170*819f0be9Sdlg _atomic_sub_long_nv(volatile unsigned long *uip, unsigned long v)
171*819f0be9Sdlg {
172*819f0be9Sdlg 	unsigned int sr;
173*819f0be9Sdlg 	unsigned long rv;
174*819f0be9Sdlg 
175*819f0be9Sdlg 	sr = __atomic_enter();
176*819f0be9Sdlg 	rv = *uip - v;
177*819f0be9Sdlg 	*uip = rv;
178*819f0be9Sdlg 	__atomic_leave(sr);
179*819f0be9Sdlg 
180*819f0be9Sdlg 	return (rv);
181*819f0be9Sdlg }
182*819f0be9Sdlg #define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v))
1833c62c4c0Sdlg 
1843c62c4c0Sdlg static inline void
atomic_setbits_int(volatile unsigned int * uip,unsigned int v)1852df76cc2Sguenther atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
186f57756c9Sart {
18732f529edSmiod 	unsigned int sr;
18832f529edSmiod 
1893c62c4c0Sdlg 	sr = __atomic_enter();
190f57756c9Sart 	*uip |= v;
1913c62c4c0Sdlg 	__atomic_leave(sr);
192f57756c9Sart }
193f57756c9Sart 
1943c62c4c0Sdlg static inline void
atomic_clearbits_int(volatile unsigned int * uip,unsigned int v)1952df76cc2Sguenther atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
196f57756c9Sart {
19732f529edSmiod 	unsigned int sr;
19832f529edSmiod 
1993c62c4c0Sdlg 	sr = __atomic_enter();
200f57756c9Sart 	*uip &= ~v;
2013c62c4c0Sdlg 	__atomic_leave(sr);
202f57756c9Sart }
203f57756c9Sart 
2048aa3ef09Sderaadt #endif /* defined(_KERNEL) */
2052fa72412Spirofti #endif /* _SH_ATOMIC_H_ */
206