1 /* $OpenBSD: atomic.h,v 1.8 2014/11/17 23:51:32 dlg Exp $ */ 2 3 /* Public Domain */ 4 5 #ifndef _SH_ATOMIC_H_ 6 #define _SH_ATOMIC_H_ 7 8 #if defined(_KERNEL) 9 10 #include <sh/psl.h> 11 12 static inline unsigned int 13 __atomic_enter(void) 14 { 15 unsigned int sr; 16 17 asm volatile ("stc sr, %0" : "=r"(sr)); 18 asm volatile ("ldc %0, sr" : : "r"(sr | PSL_IMASK)); 19 20 return (sr); 21 } 22 23 static inline void 24 __atomic_leave(unsigned int sr) 25 { 26 asm volatile ("ldc %0, sr" : : "r"(sr)); 27 } 28 29 static inline unsigned int 30 _atomic_cas_uint(volatile unsigned int *uip, unsigned int o, unsigned int n) 31 { 32 unsigned int sr; 33 unsigned int rv; 34 35 sr = __atomic_enter(); 36 rv = *uip; 37 if (rv == o) 38 *uip = n; 39 __atomic_leave(sr); 40 41 return (rv); 42 } 43 #define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n)) 44 45 static inline unsigned long 46 _atomic_cas_ulong(volatile unsigned long *uip, unsigned long o, unsigned long n) 47 { 48 unsigned int sr; 49 unsigned long rv; 50 51 sr = __atomic_enter(); 52 rv = *uip; 53 if (rv == o) 54 *uip = n; 55 __atomic_leave(sr); 56 57 return (rv); 58 } 59 #define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n)) 60 61 static inline void * 62 _atomic_cas_ptr(volatile void *uip, void *o, void *n) 63 { 64 unsigned int sr; 65 void * volatile *uipp = (void * volatile *)uip; 66 void *rv; 67 68 sr = __atomic_enter(); 69 rv = *uipp; 70 if (rv == o) 71 *uipp = n; 72 __atomic_leave(sr); 73 74 return (rv); 75 } 76 #define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n)) 77 78 static inline unsigned int 79 _atomic_swap_uint(volatile unsigned int *uip, unsigned int n) 80 { 81 unsigned int sr; 82 unsigned int rv; 83 84 sr = __atomic_enter(); 85 rv = *uip; 86 *uip = n; 87 __atomic_leave(sr); 88 89 return (rv); 90 } 91 #define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n)) 92 93 static inline unsigned long 94 _atomic_swap_ulong(volatile unsigned long *uip, unsigned long n) 95 { 96 unsigned int sr; 97 unsigned long rv; 98 99 sr = __atomic_enter(); 100 rv = *uip; 101 *uip = n; 102 __atomic_leave(sr); 103 104 return (rv); 105 } 106 #define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n)) 107 108 static inline void * 109 _atomic_swap_ptr(volatile void *uip, void *n) 110 { 111 unsigned int sr; 112 void * volatile *uipp = (void * volatile *)uip; 113 void *rv; 114 115 sr = __atomic_enter(); 116 rv = *uipp; 117 *uipp = n; 118 __atomic_leave(sr); 119 120 return (rv); 121 } 122 #define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n)) 123 124 static inline unsigned int 125 _atomic_add_int_nv(volatile unsigned int *uip, unsigned int v) 126 { 127 unsigned int sr; 128 unsigned int rv; 129 130 sr = __atomic_enter(); 131 rv = *uip + v; 132 *uip = rv; 133 __atomic_leave(sr); 134 135 return (rv); 136 } 137 #define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v)) 138 139 static inline unsigned long 140 _atomic_add_long_nv(volatile unsigned long *uip, unsigned long v) 141 { 142 unsigned int sr; 143 unsigned long rv; 144 145 sr = __atomic_enter(); 146 rv = *uip + v; 147 *uip = rv; 148 __atomic_leave(sr); 149 150 return (rv); 151 } 152 #define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v)) 153 154 static inline unsigned int 155 _atomic_sub_int_nv(volatile unsigned int *uip, unsigned int v) 156 { 157 unsigned int sr; 158 unsigned int rv; 159 160 sr = __atomic_enter(); 161 rv = *uip - v; 162 *uip = rv; 163 __atomic_leave(sr); 164 165 return (rv); 166 } 167 #define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v)) 168 169 static inline unsigned long 170 _atomic_sub_long_nv(volatile unsigned long *uip, unsigned long v) 171 { 172 unsigned int sr; 173 unsigned long rv; 174 175 sr = __atomic_enter(); 176 rv = *uip - v; 177 *uip = rv; 178 __atomic_leave(sr); 179 180 return (rv); 181 } 182 #define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v)) 183 184 static inline void 185 atomic_setbits_int(volatile unsigned int *uip, unsigned int v) 186 { 187 unsigned int sr; 188 189 sr = __atomic_enter(); 190 *uip |= v; 191 __atomic_leave(sr); 192 } 193 194 static inline void 195 atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) 196 { 197 unsigned int sr; 198 199 sr = __atomic_enter(); 200 *uip &= ~v; 201 __atomic_leave(sr); 202 } 203 204 #endif /* defined(_KERNEL) */ 205 #endif /* _SH_ATOMIC_H_ */ 206