xref: /openbsd/sys/arch/m88k/include/atomic.h (revision e5dd7070)
1 /*	$OpenBSD: atomic.h,v 1.14 2018/08/22 11:25:58 aoyama Exp $	*/
2 
3 /* Public Domain */
4 
5 #ifndef _M88K_ATOMIC_H_
6 #define _M88K_ATOMIC_H_
7 
8 #if defined(_KERNEL)
9 
10 #ifdef MULTIPROCESSOR
11 
12 /* actual implementation is hairy, see atomic.S */
13 void		atomic_setbits_int(volatile unsigned int *, unsigned int);
14 void		atomic_clearbits_int(volatile unsigned int *, unsigned int);
15 unsigned int	atomic_add_int_nv_mp(volatile unsigned int *, unsigned int);
16 unsigned int	atomic_sub_int_nv_mp(volatile unsigned int *, unsigned int);
17 unsigned int	atomic_cas_uint_mp(unsigned int *, unsigned int, unsigned int);
18 unsigned int	atomic_swap_uint_mp(unsigned int *, unsigned int);
19 
20 #define	atomic_add_int_nv	atomic_add_int_nv_mp
21 #define	atomic_sub_int_nv	atomic_sub_int_nv_mp
22 #define	atomic_cas_uint		atomic_cas_uint_mp
23 #define	atomic_swap_uint	atomic_swap_uint_mp
24 
25 #else
26 
27 #include <machine/asm_macro.h>
28 #include <machine/psl.h>
29 
30 static __inline void
31 atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
32 {
33 	u_int psr;
34 
35 	psr = get_psr();
36 	set_psr(psr | PSR_IND);
37 	*uip |= v;
38 	set_psr(psr);
39 }
40 
41 static __inline void
42 atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
43 {
44 	u_int psr;
45 
46 	psr = get_psr();
47 	set_psr(psr | PSR_IND);
48 	*uip &= ~v;
49 	set_psr(psr);
50 }
51 
52 static __inline unsigned int
53 atomic_add_int_nv_sp(volatile unsigned int *uip, unsigned int v)
54 {
55 	u_int psr;
56 	unsigned int nv;
57 
58 	psr = get_psr();
59 	set_psr(psr | PSR_IND);
60 	*uip += v;
61 	nv = *uip;
62 	set_psr(psr);
63 
64 	return nv;
65 }
66 
67 static __inline unsigned int
68 atomic_sub_int_nv_sp(volatile unsigned int *uip, unsigned int v)
69 {
70 	u_int psr;
71 	unsigned int nv;
72 
73 	psr = get_psr();
74 	set_psr(psr | PSR_IND);
75 	*uip -= v;
76 	nv = *uip;
77 	set_psr(psr);
78 
79 	return nv;
80 }
81 
82 static inline unsigned int
83 atomic_cas_uint_sp(unsigned int *p, unsigned int o, unsigned int n)
84 {
85 	u_int psr;
86 	unsigned int ov;
87 
88 	psr = get_psr();
89 	set_psr(psr | PSR_IND);
90 	ov = *p;
91 	if (ov == o)
92 		*p = n;
93 	set_psr(psr);
94 
95 	return ov;
96 }
97 
98 static inline unsigned int
99 atomic_swap_uint_sp(unsigned int *p, unsigned int v)
100 {
101 	u_int psr;
102 	unsigned int ov;
103 
104 	psr = get_psr();
105 	set_psr(psr | PSR_IND);
106 	ov = *p;
107 	*p = v;
108 	set_psr(psr);
109 
110 	return ov;
111 }
112 
113 #define	atomic_add_int_nv	atomic_add_int_nv_sp
114 #define	atomic_sub_int_nv	atomic_sub_int_nv_sp
115 #define	atomic_cas_uint		atomic_cas_uint_sp
116 #define	atomic_swap_uint	atomic_swap_uint_sp
117 
118 #endif	/* MULTIPROCESSOR */
119 
120 static __inline__ unsigned int
121 atomic_clear_int(volatile unsigned int *uip)
122 {
123 	u_int oldval;
124 
125 	oldval = 0;
126 	__asm__ volatile
127 	    ("xmem %0, %2, %%r0" : "+r"(oldval), "+m"(*uip) : "r"(uip));
128 	return oldval;
129 }
130 
131 #define	atomic_add_long_nv(p,v) \
132 	((unsigned long)atomic_add_int_nv((unsigned int *)p, (unsigned int)v))
133 #define	atomic_sub_long_nv(p,v) \
134 	((unsigned long)atomic_sub_int_nv((unsigned int *)p, (unsigned int)v))
135 
136 #define	atomic_cas_ulong(p,o,n) \
137 	((unsigned long)atomic_cas_uint((unsigned int *)p, (unsigned int)o, \
138 	 (unsigned int)n))
139 #define	atomic_cas_ptr(p,o,n) \
140 	((void *)atomic_cas_uint((void *)p, (void *)o, (void *)n))
141 
142 #define	atomic_swap_ulong(p,o) \
143 	((unsigned long)atomic_swap_uint((unsigned int *)p, (unsigned int)o)
144 #define	atomic_swap_ptr(p,o) \
145 	((void *)atomic_swap_uint((void *)p, (unsigned int)o))
146 
147 static inline void
148 __sync_synchronize(void)
149 {
150 	/* flush_pipeline(); */
151 	__asm__ volatile ("tb1 0, %%r0, 0" ::: "memory");
152 }
153 
154 #else /* _KERNEL */
155 
156 #if !defined(__GNUC__) || (__GNUC__ < 4)
157 
158 /*
159  * Atomic routines are not available to userland, but we need to prevent
160  * <sys/atomic.h> from declaring them as inline wrappers of __sync_* functions,
161  * which are not available with gcc 3.
162  */
163 
164 #define	atomic_cas_uint		UNIMPLEMENTED
165 #define	atomic_cas_ulong	UNIMPLEMENTED
166 #define	atomic_cas_ptr		UNIMPLEMENTED
167 
168 #define	atomic_swap_uint	UNIMPLEMENTED
169 #define	atomic_swap_ulong	UNIMPLEMENTED
170 #define	atomic_swap_ptr		UNIMPLEMENTED
171 
172 #define	atomic_add_int_nv	UNIMPLEMENTED
173 #define	atomic_add_long_nv	UNIMPLEMENTED
174 #define	atomic_add_int		UNIMPLEMENTED
175 #define	atomic_add_long		UNIMPLEMENTED
176 
177 #define	atomic_inc_int		UNIMPLEMENTED
178 #define	atomic_inc_long		UNIMPLEMENTED
179 
180 #define	atomic_sub_int_nv	UNIMPLEMENTED
181 #define	atomic_sub_long_nv	UNIMPLEMENTED
182 #define	atomic_sub_int		UNIMPLEMENTED
183 #define	atomic_sub_long		UNIMPLEMENTED
184 
185 #define	atomic_dec_int		UNIMPLEMENTED
186 #define	atomic_dec_long		UNIMPLEMENTED
187 
188 /* trap numbers below 128 would cause a privileged instruction fault */
189 #define	__membar() do {						\
190 	__asm __volatile("tb1 0, %%r0, 128" ::: "memory");	\
191 } while (0)
192 
193 #endif	/* gcc < 4 */
194 
195 #define	membar_enter()		__membar()
196 #define	membar_exit()		__membar()
197 #define	membar_producer()	__membar()
198 #define	membar_consumer()	__membar()
199 #define	membar_sync()		__membar()
200 
201 #endif /* defined(_KERNEL) */
202 
203 #endif /* _M88K_ATOMIC_H_ */
204