xref: /openbsd-src/sys/arch/hppa/include/atomic.h (revision 9bec9e437814d912a96fbd6178318d8771001434)
1*9bec9e43Sjsg /*	$OpenBSD: atomic.h,v 1.12 2023/04/10 04:21:20 jsg Exp $	*/
2f57756c9Sart 
3f57756c9Sart /* Public Domain */
4f57756c9Sart 
52fa72412Spirofti #ifndef _MACHINE_ATOMIC_H_
62fa72412Spirofti #define _MACHINE_ATOMIC_H_
7f57756c9Sart 
88aa3ef09Sderaadt #if defined(_KERNEL)
98aa3ef09Sderaadt 
108bf031b6Sdlg typedef volatile u_int __cpu_simple_lock_t __attribute__((__aligned__(16)));
118bf031b6Sdlg 
128bf031b6Sdlg #define __SIMPLELOCK_LOCKED	0
138bf031b6Sdlg #define __SIMPLELOCK_UNLOCKED	1
148bf031b6Sdlg 
158bf031b6Sdlg static inline void
__cpu_simple_lock_init(__cpu_simple_lock_t * l)168bf031b6Sdlg __cpu_simple_lock_init(__cpu_simple_lock_t *l)
178bf031b6Sdlg {
188bf031b6Sdlg 	*l = __SIMPLELOCK_UNLOCKED;
198bf031b6Sdlg }
208bf031b6Sdlg 
218bf031b6Sdlg static inline unsigned int
__cpu_simple_lock_ldcws(__cpu_simple_lock_t * l)228bf031b6Sdlg __cpu_simple_lock_ldcws(__cpu_simple_lock_t *l)
238bf031b6Sdlg {
248bf031b6Sdlg 	unsigned int o;
258bf031b6Sdlg 
268bf031b6Sdlg 	asm volatile("ldcws 0(%2), %0" : "=&r" (o), "+m" (l) : "r" (l));
278bf031b6Sdlg 
288bf031b6Sdlg 	return (o);
298bf031b6Sdlg }
308bf031b6Sdlg 
318bf031b6Sdlg static inline int
__cpu_simple_lock_try(__cpu_simple_lock_t * l)328bf031b6Sdlg __cpu_simple_lock_try(__cpu_simple_lock_t *l)
338bf031b6Sdlg {
348bf031b6Sdlg 	return (__cpu_simple_lock_ldcws(l) == __SIMPLELOCK_UNLOCKED);
358bf031b6Sdlg }
368bf031b6Sdlg 
378bf031b6Sdlg static inline void
__cpu_simple_lock(__cpu_simple_lock_t * l)38219fa113Sdlg __cpu_simple_lock(__cpu_simple_lock_t *l)
39219fa113Sdlg {
40219fa113Sdlg 	while (!__cpu_simple_lock_ldcws(l))
41219fa113Sdlg 		;
42219fa113Sdlg }
43219fa113Sdlg 
44219fa113Sdlg static inline void
__cpu_simple_unlock(__cpu_simple_lock_t * l)458bf031b6Sdlg __cpu_simple_unlock(__cpu_simple_lock_t *l)
468bf031b6Sdlg {
478bf031b6Sdlg 	*l = __SIMPLELOCK_UNLOCKED;
488bf031b6Sdlg }
497dda6ca7Sjsing 
507dda6ca7Sjsing #ifdef MULTIPROCESSOR
518bf031b6Sdlg extern __cpu_simple_lock_t atomic_lock;
528bf031b6Sdlg #define ATOMIC_LOCK	__cpu_simple_lock(&atomic_lock);
538bf031b6Sdlg #define ATOMIC_UNLOCK	__cpu_simple_unlock(&atomic_lock);
547dda6ca7Sjsing #else
557dda6ca7Sjsing #define ATOMIC_LOCK
567dda6ca7Sjsing #define ATOMIC_UNLOCK
577dda6ca7Sjsing #endif
587dda6ca7Sjsing 
598bf031b6Sdlg static inline register_t
atomic_enter(void)608bf031b6Sdlg atomic_enter(void)
61f57756c9Sart {
62f8b1aca5Smiod 	register_t eiem;
63f8b1aca5Smiod 
642df76cc2Sguenther 	__asm volatile("mfctl	%%cr15, %0": "=r" (eiem));
652df76cc2Sguenther 	__asm volatile("mtctl	%r0, %cr15");
667dda6ca7Sjsing 	ATOMIC_LOCK;
678bf031b6Sdlg 
688bf031b6Sdlg 	return (eiem);
698bf031b6Sdlg }
708bf031b6Sdlg 
718bf031b6Sdlg static inline void
atomic_leave(register_t eiem)728bf031b6Sdlg atomic_leave(register_t eiem)
738bf031b6Sdlg {
747dda6ca7Sjsing 	ATOMIC_UNLOCK;
752df76cc2Sguenther 	__asm volatile("mtctl	%0, %%cr15":: "r" (eiem));
76f57756c9Sart }
77f57756c9Sart 
788bf031b6Sdlg static inline unsigned int
_atomic_cas_uint(volatile unsigned int * uip,unsigned int o,unsigned int n)798bf031b6Sdlg _atomic_cas_uint(volatile unsigned int *uip, unsigned int o, unsigned int n)
808bf031b6Sdlg {
818bf031b6Sdlg 	register_t eiem;
828bf031b6Sdlg 	unsigned int rv;
838bf031b6Sdlg 
848bf031b6Sdlg 	eiem = atomic_enter();
858bf031b6Sdlg 	rv = *uip;
868bf031b6Sdlg 	if (rv == o)
878bf031b6Sdlg 		*uip = n;
888bf031b6Sdlg 	atomic_leave(eiem);
898bf031b6Sdlg 
908bf031b6Sdlg 	return (rv);
918bf031b6Sdlg }
928bf031b6Sdlg #define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n))
938bf031b6Sdlg 
948bf031b6Sdlg static inline unsigned long
_atomic_cas_ulong(volatile unsigned long * uip,unsigned long o,unsigned long n)958bf031b6Sdlg _atomic_cas_ulong(volatile unsigned long *uip, unsigned long o, unsigned long n)
968bf031b6Sdlg {
978bf031b6Sdlg 	register_t eiem;
988bf031b6Sdlg 	unsigned long rv;
998bf031b6Sdlg 
1008bf031b6Sdlg 	eiem = atomic_enter();
1018bf031b6Sdlg 	rv = *uip;
1028bf031b6Sdlg 	if (rv == o)
1038bf031b6Sdlg 		*uip = n;
1048bf031b6Sdlg 	atomic_leave(eiem);
1058bf031b6Sdlg 
1068bf031b6Sdlg 	return (rv);
1078bf031b6Sdlg }
1088bf031b6Sdlg #define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n))
1098bf031b6Sdlg 
1108bf031b6Sdlg static inline void *
_atomic_cas_ptr(volatile void * uip,void * o,void * n)1118bf031b6Sdlg _atomic_cas_ptr(volatile void *uip, void *o, void *n)
1128bf031b6Sdlg {
1138bf031b6Sdlg 	register_t eiem;
1148bf031b6Sdlg 	void * volatile *uipp = (void * volatile *)uip;
1158bf031b6Sdlg 	void *rv;
1168bf031b6Sdlg 
1178bf031b6Sdlg 	eiem = atomic_enter();
1188bf031b6Sdlg 	rv = *uipp;
1198bf031b6Sdlg 	if (rv == o)
1208bf031b6Sdlg 		*uipp = n;
1218bf031b6Sdlg 	atomic_leave(eiem);
1228bf031b6Sdlg 
1238bf031b6Sdlg 	return (rv);
1248bf031b6Sdlg }
1258bf031b6Sdlg #define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n))
1268bf031b6Sdlg 
1278bf031b6Sdlg static inline unsigned int
_atomic_swap_uint(volatile unsigned int * uip,unsigned int n)1288bf031b6Sdlg _atomic_swap_uint(volatile unsigned int *uip, unsigned int n)
1298bf031b6Sdlg {
1308bf031b6Sdlg 	register_t eiem;
1318bf031b6Sdlg 	unsigned int rv;
1328bf031b6Sdlg 
1338bf031b6Sdlg 	eiem = atomic_enter();
1348bf031b6Sdlg 	rv = *uip;
1358bf031b6Sdlg 	*uip = n;
1368bf031b6Sdlg 	atomic_leave(eiem);
1378bf031b6Sdlg 
1388bf031b6Sdlg 	return (rv);
1398bf031b6Sdlg }
1408bf031b6Sdlg #define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n))
1418bf031b6Sdlg 
1428bf031b6Sdlg static inline unsigned long
_atomic_swap_ulong(volatile unsigned long * uip,unsigned long n)1438bf031b6Sdlg _atomic_swap_ulong(volatile unsigned long *uip, unsigned long n)
1448bf031b6Sdlg {
1458bf031b6Sdlg 	register_t eiem;
1468bf031b6Sdlg 	unsigned long rv;
1478bf031b6Sdlg 
1488bf031b6Sdlg 	eiem = atomic_enter();
1498bf031b6Sdlg 	rv = *uip;
1508bf031b6Sdlg 	*uip = n;
1518bf031b6Sdlg 	atomic_leave(eiem);
1528bf031b6Sdlg 
1538bf031b6Sdlg 	return (rv);
1548bf031b6Sdlg }
1553480ef41Sdlg #define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n))
1568bf031b6Sdlg 
1578bf031b6Sdlg static inline void *
_atomic_swap_ptr(volatile void * uip,void * n)1588bf031b6Sdlg _atomic_swap_ptr(volatile void *uip, void *n)
1598bf031b6Sdlg {
1608bf031b6Sdlg 	register_t eiem;
1618bf031b6Sdlg 	void * volatile *uipp = (void * volatile *)uip;
1628bf031b6Sdlg 	void *rv;
1638bf031b6Sdlg 
1648bf031b6Sdlg 	eiem = atomic_enter();
1658bf031b6Sdlg 	rv = *uipp;
1668bf031b6Sdlg 	*uipp = n;
1678bf031b6Sdlg 	atomic_leave(eiem);
1688bf031b6Sdlg 
1698bf031b6Sdlg 	return (rv);
1708bf031b6Sdlg }
1713480ef41Sdlg #define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n))
1728bf031b6Sdlg 
1738bf031b6Sdlg static __inline unsigned int
_atomic_add_int_nv(volatile unsigned int * uip,unsigned int v)1748bf031b6Sdlg _atomic_add_int_nv(volatile unsigned int *uip, unsigned int v)
1758bf031b6Sdlg {
1768bf031b6Sdlg 	register_t eiem;
1778bf031b6Sdlg 	unsigned int rv;
1788bf031b6Sdlg 
1798bf031b6Sdlg 	eiem = atomic_enter();
1808bf031b6Sdlg 	rv = *uip + v;
1818bf031b6Sdlg 	*uip = rv;
1828bf031b6Sdlg 	atomic_leave(eiem);
1838bf031b6Sdlg 
1848bf031b6Sdlg 	return (rv);
1858bf031b6Sdlg }
1868bf031b6Sdlg #define atomic_add_int_nv(_uip, _v) _atomic_add_int_nv((_uip), (_v))
1878bf031b6Sdlg #define atomic_sub_int_nv(_uip, _v) _atomic_add_int_nv((_uip), 0 - (_v))
1888bf031b6Sdlg 
1898bf031b6Sdlg static __inline unsigned long
_atomic_add_long_nv(volatile unsigned long * uip,unsigned long v)1908bf031b6Sdlg _atomic_add_long_nv(volatile unsigned long *uip, unsigned long v)
1918bf031b6Sdlg {
1928bf031b6Sdlg 	register_t eiem;
1938bf031b6Sdlg 	unsigned long rv;
1948bf031b6Sdlg 
1958bf031b6Sdlg 	eiem = atomic_enter();
1968bf031b6Sdlg 	rv = *uip + v;
1978bf031b6Sdlg 	*uip = rv;
1988bf031b6Sdlg 	atomic_leave(eiem);
1998bf031b6Sdlg 
2008bf031b6Sdlg 	return (rv);
2018bf031b6Sdlg }
2028bf031b6Sdlg #define atomic_add_long_nv(_uip, _v) _atomic_add_long_nv((_uip), (_v))
2038bf031b6Sdlg #define atomic_sub_long_nv(_uip, _v) _atomic_add_long_nv((_uip), 0 - (_v))
2048bf031b6Sdlg 
2058bf031b6Sdlg static __inline void
atomic_setbits_int(volatile unsigned int * uip,unsigned int v)2068bf031b6Sdlg atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
2078bf031b6Sdlg {
2088bf031b6Sdlg 	register_t eiem;
2098bf031b6Sdlg 
2108bf031b6Sdlg 	eiem = atomic_enter();
2118bf031b6Sdlg 	*uip |= v;
2128bf031b6Sdlg 	atomic_leave(eiem);
2138bf031b6Sdlg }
2148bf031b6Sdlg 
215f57756c9Sart static __inline void
atomic_clearbits_int(volatile unsigned int * uip,unsigned int v)2162df76cc2Sguenther atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
217f57756c9Sart {
218f8b1aca5Smiod 	register_t eiem;
219f8b1aca5Smiod 
2208bf031b6Sdlg 	eiem = atomic_enter();
221f57756c9Sart 	*uip &= ~v;
2228bf031b6Sdlg 	atomic_leave(eiem);
223f8b1aca5Smiod }
224f8b1aca5Smiod 
225f8b1aca5Smiod static __inline void
atomic_setbits_long(volatile unsigned long * uip,unsigned long v)2262df76cc2Sguenther atomic_setbits_long(volatile unsigned long *uip, unsigned long v)
227f8b1aca5Smiod {
228f8b1aca5Smiod 	register_t eiem;
229f8b1aca5Smiod 
2308bf031b6Sdlg 	eiem = atomic_enter();
231f8b1aca5Smiod 	*uip |= v;
2328bf031b6Sdlg 	atomic_leave(eiem);
233f8b1aca5Smiod }
234f8b1aca5Smiod 
235f8b1aca5Smiod static __inline void
atomic_clearbits_long(volatile unsigned long * uip,unsigned long v)2362df76cc2Sguenther atomic_clearbits_long(volatile unsigned long *uip, unsigned long v)
237f8b1aca5Smiod {
238f8b1aca5Smiod 	register_t eiem;
239f8b1aca5Smiod 
2408bf031b6Sdlg 	eiem = atomic_enter();
241f8b1aca5Smiod 	*uip &= ~v;
2428bf031b6Sdlg 	atomic_leave(eiem);
243f57756c9Sart }
244f57756c9Sart 
245ca950ec4Skettenis #endif /* defined(_KERNEL) */
246ca950ec4Skettenis 
247095af81fSkettenis /*
248095af81fSkettenis  * Although the PA-RISC 2.0 architecture allows an implementation to
249*9bec9e43Sjsg  * be weakly ordered, all PA-RISC processors to date implement a
250095af81fSkettenis  * strong memory ordering model.  So all we need is a compiler
251095af81fSkettenis  * barrier.
252095af81fSkettenis  */
253095af81fSkettenis 
254095af81fSkettenis static inline void
__insn_barrier(void)255095af81fSkettenis __insn_barrier(void)
256095af81fSkettenis {
257095af81fSkettenis 	__asm volatile("" : : : "memory");
258095af81fSkettenis }
259095af81fSkettenis 
260095af81fSkettenis #define membar_enter()		__insn_barrier()
261095af81fSkettenis #define membar_exit()		__insn_barrier()
262095af81fSkettenis #define membar_producer()	__insn_barrier()
263095af81fSkettenis #define membar_consumer()	__insn_barrier()
264095af81fSkettenis #define membar_sync()		__insn_barrier()
265095af81fSkettenis 
2662fa72412Spirofti #endif /* _MACHINE_ATOMIC_H_ */
267