xref: /openbsd-src/sys/arch/sparc64/include/atomic.h (revision 8c1f099f62a7b9af775435bb74542244248200f2)
1*8c1f099fSmpi /*	$OpenBSD: atomic.h,v 1.15 2017/07/04 09:00:12 mpi Exp $	*/
29d2a4093Sart /*
39d2a4093Sart  * Copyright (c) 2007 Artur Grabowski <art@openbsd.org>
49d2a4093Sart  *
59d2a4093Sart  * Permission to use, copy, modify, and distribute this software for any
69d2a4093Sart  * purpose with or without fee is hereby granted, provided that the above
79d2a4093Sart  * copyright notice and this permission notice appear in all copies.
89d2a4093Sart  *
99d2a4093Sart  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
109d2a4093Sart  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
119d2a4093Sart  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
129d2a4093Sart  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
139d2a4093Sart  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
149d2a4093Sart  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
159d2a4093Sart  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
169d2a4093Sart  */
17f57756c9Sart 
182fa72412Spirofti #ifndef _MACHINE_ATOMIC_H_
192fa72412Spirofti #define _MACHINE_ATOMIC_H_
20f57756c9Sart 
215edb0f83Sdlg static inline unsigned int
_atomic_cas_uint(volatile unsigned int * p,unsigned int e,unsigned int n)225edb0f83Sdlg _atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n)
23f57756c9Sart {
242df76cc2Sguenther 	__asm volatile("cas [%2], %3, %0"
255edb0f83Sdlg 	    : "+r" (n), "=m" (*p)
265edb0f83Sdlg 	    : "r" (p), "r" (e), "m" (*p));
279d2a4093Sart 
285edb0f83Sdlg 	return (n);
29f57756c9Sart }
305edb0f83Sdlg #define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n))
31f57756c9Sart 
325edb0f83Sdlg static inline unsigned long
_atomic_cas_ulong(volatile unsigned long * p,unsigned long e,unsigned long n)335edb0f83Sdlg _atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n)
34d40386ccSkettenis {
352df76cc2Sguenther 	__asm volatile("casx [%2], %3, %0"
365edb0f83Sdlg 	    : "+r" (n), "=m" (*p)
375edb0f83Sdlg 	    : "r" (p), "r" (e), "m" (*p));
38d40386ccSkettenis 
395edb0f83Sdlg 	return (n);
40d40386ccSkettenis }
415edb0f83Sdlg #define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n))
425edb0f83Sdlg 
435edb0f83Sdlg static inline void *
_atomic_cas_ptr(volatile void * p,void * e,void * n)44b6a8cdecSdlg _atomic_cas_ptr(volatile void *p, void *e, void *n)
455edb0f83Sdlg {
462df76cc2Sguenther 	__asm volatile("casx [%2], %3, %0"
47b6a8cdecSdlg 	    : "+r" (n), "=m" (*(volatile unsigned long *)p)
48b6a8cdecSdlg 	    : "r" (p), "r" (e), "m" (*(volatile unsigned long *)p));
495edb0f83Sdlg 
505edb0f83Sdlg 	return (n);
515edb0f83Sdlg }
525edb0f83Sdlg #define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n))
535edb0f83Sdlg 
54*8c1f099fSmpi #define _def_atomic_swap(_f, _t, _c)					\
555edb0f83Sdlg static inline _t							\
565edb0f83Sdlg _f(volatile _t *p, _t v)						\
575edb0f83Sdlg {									\
585edb0f83Sdlg 	_t e;								\
595edb0f83Sdlg 	_t r;								\
605edb0f83Sdlg 									\
615edb0f83Sdlg 	r = (_t)*p;							\
625edb0f83Sdlg 	do {								\
635edb0f83Sdlg 		e = r;							\
645edb0f83Sdlg 		r = _c(p, e, v);					\
655edb0f83Sdlg 	} while (r != e);						\
665edb0f83Sdlg 									\
675edb0f83Sdlg 	return (r);							\
685edb0f83Sdlg }
695edb0f83Sdlg 
_def_atomic_swap(_atomic_swap_uint,unsigned int,atomic_cas_uint)70*8c1f099fSmpi _def_atomic_swap(_atomic_swap_uint, unsigned int, atomic_cas_uint)
71*8c1f099fSmpi _def_atomic_swap(_atomic_swap_ulong, unsigned long, atomic_cas_ulong)
72*8c1f099fSmpi #undef _def_atomic_swap
735edb0f83Sdlg 
747be48f09Sdlg static inline void *
757be48f09Sdlg _atomic_swap_ptr(volatile void *p, void *v)
767be48f09Sdlg {
777be48f09Sdlg 	void *e, *r;
787be48f09Sdlg 
797be48f09Sdlg 	r = *(void **)p;
807be48f09Sdlg 	do {
817be48f09Sdlg 		e = r;
827be48f09Sdlg 		r = atomic_cas_ptr(p, e, v);
837be48f09Sdlg 	} while (r != e);
847be48f09Sdlg 
857be48f09Sdlg 	return (r);
867be48f09Sdlg }
877be48f09Sdlg 
885edb0f83Sdlg #define atomic_swap_uint(_p, _v)  _atomic_swap_uint(_p, _v)
895edb0f83Sdlg #define atomic_swap_ulong(_p, _v)  _atomic_swap_ulong(_p, _v)
905edb0f83Sdlg #define atomic_swap_ptr(_p, _v)  _atomic_swap_ptr(_p, _v)
915edb0f83Sdlg 
92*8c1f099fSmpi #define _def_atomic_op_nv(_f, _t, _c, _op)				\
935edb0f83Sdlg static inline _t							\
945edb0f83Sdlg _f(volatile _t *p, _t v)						\
955edb0f83Sdlg {									\
965edb0f83Sdlg 	_t e, r, f;							\
975edb0f83Sdlg 									\
985edb0f83Sdlg 	r = *p;								\
995edb0f83Sdlg 	do {								\
1005edb0f83Sdlg 		e = r;							\
1015edb0f83Sdlg 		f = e _op v;						\
1025edb0f83Sdlg 		r = _c(p, e, f);					\
1035edb0f83Sdlg 	} while (r != e);						\
1045edb0f83Sdlg 									\
1055edb0f83Sdlg 	return (f);							\
1065edb0f83Sdlg }
1075edb0f83Sdlg 
108*8c1f099fSmpi _def_atomic_op_nv(_atomic_add_int_nv, unsigned int, atomic_cas_uint, +)
109*8c1f099fSmpi _def_atomic_op_nv(_atomic_add_long_nv, unsigned long, atomic_cas_ulong, +)
110*8c1f099fSmpi _def_atomic_op_nv(_atomic_sub_int_nv, unsigned int, atomic_cas_uint, -)
111*8c1f099fSmpi _def_atomic_op_nv(_atomic_sub_long_nv, unsigned long, atomic_cas_ulong, -)
112*8c1f099fSmpi #undef _def_atomic_op_nv
1135edb0f83Sdlg 
1145edb0f83Sdlg #define atomic_add_int_nv(_p, _v)  _atomic_add_int_nv(_p, _v)
1155edb0f83Sdlg #define atomic_add_long_nv(_p, _v)  _atomic_add_long_nv(_p, _v)
1165edb0f83Sdlg #define atomic_sub_int_nv(_p, _v)  _atomic_sub_int_nv(_p, _v)
1175edb0f83Sdlg #define atomic_sub_long_nv(_p, _v)  _atomic_sub_long_nv(_p, _v)
118d40386ccSkettenis 
119*8c1f099fSmpi #define __membar(_m)		__asm volatile("membar " _m ::: "memory")
120*8c1f099fSmpi 
121*8c1f099fSmpi #define membar_enter()		__membar("#StoreLoad|#StoreStore")
122*8c1f099fSmpi #define membar_exit()		__membar("#LoadStore|#StoreStore")
123*8c1f099fSmpi #define membar_producer()	__membar("#StoreStore")
124*8c1f099fSmpi #define membar_consumer()	__membar("#LoadLoad")
125*8c1f099fSmpi #define membar_sync()		__membar("#Sync")
126*8c1f099fSmpi 
127*8c1f099fSmpi #if defined(_KERNEL)
128*8c1f099fSmpi 
129f57756c9Sart static __inline void
atomic_setbits_int(volatile unsigned int * uip,unsigned int v)1309d2a4093Sart atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
131f57756c9Sart {
1325edb0f83Sdlg 	unsigned int e, r;
1339d2a4093Sart 
1349d2a4093Sart 	r = *uip;
1359d2a4093Sart 	do {
1369d2a4093Sart 		e = r;
1375edb0f83Sdlg 		r = atomic_cas_uint(uip, e, e | v);
1389d2a4093Sart 	} while (r != e);
1399d2a4093Sart }
1409d2a4093Sart 
1419d2a4093Sart static __inline void
atomic_clearbits_int(volatile unsigned int * uip,unsigned int v)1429d2a4093Sart atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
1439d2a4093Sart {
1445edb0f83Sdlg 	unsigned int e, r;
1459d2a4093Sart 
1469d2a4093Sart 	r = *uip;
1479d2a4093Sart 	do {
1489d2a4093Sart 		e = r;
1495edb0f83Sdlg 		r = atomic_cas_uint(uip, e, e & ~v);
1509d2a4093Sart 	} while (r != e);
151f57756c9Sart }
152f57756c9Sart 
1538aa3ef09Sderaadt #endif /* defined(_KERNEL) */
1542fa72412Spirofti #endif /* _MACHINE_ATOMIC_H_ */
155