/* $OpenBSD: atomic.h,v 1.16 2022/08/29 02:01:18 jsg Exp $ */ /* Public Domain */ #ifndef _M88K_ATOMIC_H_ #define _M88K_ATOMIC_H_ #if defined(_KERNEL) #ifdef MULTIPROCESSOR /* actual implementation is hairy, see atomic.S */ void atomic_setbits_int(volatile unsigned int *, unsigned int); void atomic_clearbits_int(volatile unsigned int *, unsigned int); unsigned int atomic_add_int_nv_mp(volatile unsigned int *, unsigned int); unsigned int atomic_sub_int_nv_mp(volatile unsigned int *, unsigned int); unsigned int atomic_cas_uint_mp(unsigned int *, unsigned int, unsigned int); unsigned int atomic_swap_uint_mp(unsigned int *, unsigned int); #define atomic_add_int_nv atomic_add_int_nv_mp #define atomic_sub_int_nv atomic_sub_int_nv_mp #define atomic_cas_uint atomic_cas_uint_mp #define atomic_swap_uint atomic_swap_uint_mp #else #include #include static __inline void atomic_setbits_int(volatile unsigned int *uip, unsigned int v) { u_int psr; psr = get_psr(); set_psr(psr | PSR_IND); *uip |= v; set_psr(psr); } static __inline void atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) { u_int psr; psr = get_psr(); set_psr(psr | PSR_IND); *uip &= ~v; set_psr(psr); } static __inline unsigned int atomic_add_int_nv_sp(volatile unsigned int *uip, unsigned int v) { u_int psr; unsigned int nv; psr = get_psr(); set_psr(psr | PSR_IND); *uip += v; nv = *uip; set_psr(psr); return nv; } static __inline unsigned int atomic_sub_int_nv_sp(volatile unsigned int *uip, unsigned int v) { u_int psr; unsigned int nv; psr = get_psr(); set_psr(psr | PSR_IND); *uip -= v; nv = *uip; set_psr(psr); return nv; } static inline unsigned int atomic_cas_uint_sp(unsigned int *p, unsigned int o, unsigned int n) { u_int psr; unsigned int ov; psr = get_psr(); set_psr(psr | PSR_IND); ov = *p; if (ov == o) *p = n; set_psr(psr); return ov; } static inline unsigned int atomic_swap_uint_sp(unsigned int *p, unsigned int v) { u_int psr; unsigned int ov; psr = get_psr(); set_psr(psr | PSR_IND); ov = *p; *p = v; set_psr(psr); return ov; } #define atomic_add_int_nv atomic_add_int_nv_sp #define atomic_sub_int_nv atomic_sub_int_nv_sp #define atomic_cas_uint atomic_cas_uint_sp #define atomic_swap_uint atomic_swap_uint_sp #endif /* MULTIPROCESSOR */ static __inline__ unsigned int atomic_clear_int(volatile unsigned int *uip) { u_int oldval; oldval = 0; __asm__ volatile ("xmem %0, %2, %%r0" : "+r"(oldval), "+m"(*uip) : "r"(uip)); return oldval; } #define atomic_add_long_nv(p,v) \ ((unsigned long)atomic_add_int_nv((unsigned int *)p, (unsigned int)v)) #define atomic_sub_long_nv(p,v) \ ((unsigned long)atomic_sub_int_nv((unsigned int *)p, (unsigned int)v)) #define atomic_cas_ulong(p,o,n) \ ((unsigned long)atomic_cas_uint((unsigned int *)p, (unsigned int)o, \ (unsigned int)n)) #define atomic_cas_ptr(p,o,n) \ ((void *)atomic_cas_uint((void *)p, (unsigned int)o, (unsigned int)n)) #define atomic_swap_ulong(p,o) \ ((unsigned long)atomic_swap_uint((unsigned int *)p, (unsigned int)o) #define atomic_swap_ptr(p,o) \ ((void *)atomic_swap_uint((void *)p, (unsigned int)o)) static inline void __sync_synchronize(void) { /* flush_pipeline(); */ __asm__ volatile ("tb1 0, %%r0, 0" ::: "memory"); } #else /* _KERNEL */ #if !defined(__GNUC__) || (__GNUC__ < 4) /* * Atomic routines are not available to userland, but we need to prevent * from declaring them as inline wrappers of __sync_* functions, * which are not available with gcc 3. */ #define atomic_cas_uint UNIMPLEMENTED #define atomic_cas_ulong UNIMPLEMENTED #define atomic_cas_ptr UNIMPLEMENTED #define atomic_swap_uint UNIMPLEMENTED #define atomic_swap_ulong UNIMPLEMENTED #define atomic_swap_ptr UNIMPLEMENTED #define atomic_add_int_nv UNIMPLEMENTED #define atomic_add_long_nv UNIMPLEMENTED #define atomic_add_int UNIMPLEMENTED #define atomic_add_long UNIMPLEMENTED #define atomic_inc_int UNIMPLEMENTED #define atomic_inc_long UNIMPLEMENTED #define atomic_sub_int_nv UNIMPLEMENTED #define atomic_sub_long_nv UNIMPLEMENTED #define atomic_sub_int UNIMPLEMENTED #define atomic_sub_long UNIMPLEMENTED #define atomic_dec_int UNIMPLEMENTED #define atomic_dec_long UNIMPLEMENTED /* trap numbers below 128 would cause a privileged instruction fault */ #define __membar() do { \ __asm volatile("tb1 0, %%r0, 128" ::: "memory"); \ } while (0) #endif /* gcc < 4 */ #define membar_enter() __membar() #define membar_exit() __membar() #define membar_producer() __membar() #define membar_consumer() __membar() #define membar_sync() __membar() #endif /* defined(_KERNEL) */ #endif /* _M88K_ATOMIC_H_ */