1570af302Sopenharmony_ci#ifndef _ATOMIC_H 2570af302Sopenharmony_ci#define _ATOMIC_H 3570af302Sopenharmony_ci 4570af302Sopenharmony_ci#include <stdint.h> 5570af302Sopenharmony_ci 6570af302Sopenharmony_ci#include "atomic_arch.h" 7570af302Sopenharmony_ci 8570af302Sopenharmony_ci#ifdef a_ll 9570af302Sopenharmony_ci 10570af302Sopenharmony_ci#ifndef a_pre_llsc 11570af302Sopenharmony_ci#define a_pre_llsc() 12570af302Sopenharmony_ci#endif 13570af302Sopenharmony_ci 14570af302Sopenharmony_ci#ifndef a_post_llsc 15570af302Sopenharmony_ci#define a_post_llsc() 16570af302Sopenharmony_ci#endif 17570af302Sopenharmony_ci 18570af302Sopenharmony_ci#ifndef a_cas 19570af302Sopenharmony_ci#define a_cas a_cas 20570af302Sopenharmony_cistatic inline int a_cas(volatile int *p, int t, int s) 21570af302Sopenharmony_ci{ 22570af302Sopenharmony_ci int old; 23570af302Sopenharmony_ci a_pre_llsc(); 24570af302Sopenharmony_ci do old = a_ll(p); 25570af302Sopenharmony_ci while (old==t && !a_sc(p, s)); 26570af302Sopenharmony_ci a_post_llsc(); 27570af302Sopenharmony_ci return old; 28570af302Sopenharmony_ci} 29570af302Sopenharmony_ci#endif 30570af302Sopenharmony_ci 31570af302Sopenharmony_ci#ifndef a_swap 32570af302Sopenharmony_ci#define a_swap a_swap 33570af302Sopenharmony_cistatic inline int a_swap(volatile int *p, int v) 34570af302Sopenharmony_ci{ 35570af302Sopenharmony_ci int old; 36570af302Sopenharmony_ci a_pre_llsc(); 37570af302Sopenharmony_ci do old = a_ll(p); 38570af302Sopenharmony_ci while (!a_sc(p, v)); 39570af302Sopenharmony_ci a_post_llsc(); 40570af302Sopenharmony_ci return old; 41570af302Sopenharmony_ci} 42570af302Sopenharmony_ci#endif 43570af302Sopenharmony_ci 44570af302Sopenharmony_ci#ifndef a_fetch_add 45570af302Sopenharmony_ci#define a_fetch_add a_fetch_add 46570af302Sopenharmony_cistatic inline int a_fetch_add(volatile int *p, int v) 47570af302Sopenharmony_ci{ 48570af302Sopenharmony_ci int old; 49570af302Sopenharmony_ci a_pre_llsc(); 50570af302Sopenharmony_ci do old = a_ll(p); 51570af302Sopenharmony_ci while (!a_sc(p, (unsigned)old + v)); 52570af302Sopenharmony_ci a_post_llsc(); 53570af302Sopenharmony_ci return old; 54570af302Sopenharmony_ci} 55570af302Sopenharmony_ci#endif 56570af302Sopenharmony_ci 57570af302Sopenharmony_ci#ifndef a_fetch_and 58570af302Sopenharmony_ci#define a_fetch_and a_fetch_and 59570af302Sopenharmony_cistatic inline int a_fetch_and(volatile int *p, int v) 60570af302Sopenharmony_ci{ 61570af302Sopenharmony_ci int old; 62570af302Sopenharmony_ci a_pre_llsc(); 63570af302Sopenharmony_ci do old = a_ll(p); 64570af302Sopenharmony_ci while (!a_sc(p, old & v)); 65570af302Sopenharmony_ci a_post_llsc(); 66570af302Sopenharmony_ci return old; 67570af302Sopenharmony_ci} 68570af302Sopenharmony_ci#endif 69570af302Sopenharmony_ci 70570af302Sopenharmony_ci#ifndef a_fetch_or 71570af302Sopenharmony_ci#define a_fetch_or a_fetch_or 72570af302Sopenharmony_cistatic inline int a_fetch_or(volatile int *p, int v) 73570af302Sopenharmony_ci{ 74570af302Sopenharmony_ci int old; 75570af302Sopenharmony_ci a_pre_llsc(); 76570af302Sopenharmony_ci do old = a_ll(p); 77570af302Sopenharmony_ci while (!a_sc(p, old | v)); 78570af302Sopenharmony_ci a_post_llsc(); 79570af302Sopenharmony_ci return old; 80570af302Sopenharmony_ci} 81570af302Sopenharmony_ci#endif 82570af302Sopenharmony_ci 83570af302Sopenharmony_ci#endif 84570af302Sopenharmony_ci 85570af302Sopenharmony_ci#ifdef a_ll_p 86570af302Sopenharmony_ci 87570af302Sopenharmony_ci#ifndef a_cas_p 88570af302Sopenharmony_ci#define a_cas_p a_cas_p 89570af302Sopenharmony_cistatic inline void *a_cas_p(volatile void *p, void *t, void *s) 90570af302Sopenharmony_ci{ 91570af302Sopenharmony_ci void *old; 92570af302Sopenharmony_ci a_pre_llsc(); 93570af302Sopenharmony_ci do old = a_ll_p(p); 94570af302Sopenharmony_ci while (old==t && !a_sc_p(p, s)); 95570af302Sopenharmony_ci a_post_llsc(); 96570af302Sopenharmony_ci return old; 97570af302Sopenharmony_ci} 98570af302Sopenharmony_ci#endif 99570af302Sopenharmony_ci 100570af302Sopenharmony_ci#endif 101570af302Sopenharmony_ci 102570af302Sopenharmony_ci#ifndef a_cas 103570af302Sopenharmony_ci#error missing definition of a_cas 104570af302Sopenharmony_ci#endif 105570af302Sopenharmony_ci 106570af302Sopenharmony_ci#ifndef a_swap 107570af302Sopenharmony_ci#define a_swap a_swap 108570af302Sopenharmony_cistatic inline int a_swap(volatile int *p, int v) 109570af302Sopenharmony_ci{ 110570af302Sopenharmony_ci int old; 111570af302Sopenharmony_ci do old = *p; 112570af302Sopenharmony_ci while (a_cas(p, old, v) != old); 113570af302Sopenharmony_ci return old; 114570af302Sopenharmony_ci} 115570af302Sopenharmony_ci#endif 116570af302Sopenharmony_ci 117570af302Sopenharmony_ci#ifndef a_fetch_add 118570af302Sopenharmony_ci#define a_fetch_add a_fetch_add 119570af302Sopenharmony_cistatic inline int a_fetch_add(volatile int *p, int v) 120570af302Sopenharmony_ci{ 121570af302Sopenharmony_ci int old; 122570af302Sopenharmony_ci do old = *p; 123570af302Sopenharmony_ci while (a_cas(p, old, (unsigned)old+v) != old); 124570af302Sopenharmony_ci return old; 125570af302Sopenharmony_ci} 126570af302Sopenharmony_ci#endif 127570af302Sopenharmony_ci 128570af302Sopenharmony_ci#ifndef a_fetch_and 129570af302Sopenharmony_ci#define a_fetch_and a_fetch_and 130570af302Sopenharmony_cistatic inline int a_fetch_and(volatile int *p, int v) 131570af302Sopenharmony_ci{ 132570af302Sopenharmony_ci int old; 133570af302Sopenharmony_ci do old = *p; 134570af302Sopenharmony_ci while (a_cas(p, old, old&v) != old); 135570af302Sopenharmony_ci return old; 136570af302Sopenharmony_ci} 137570af302Sopenharmony_ci#endif 138570af302Sopenharmony_ci#ifndef a_fetch_or 139570af302Sopenharmony_ci#define a_fetch_or a_fetch_or 140570af302Sopenharmony_cistatic inline int a_fetch_or(volatile int *p, int v) 141570af302Sopenharmony_ci{ 142570af302Sopenharmony_ci int old; 143570af302Sopenharmony_ci do old = *p; 144570af302Sopenharmony_ci while (a_cas(p, old, old|v) != old); 145570af302Sopenharmony_ci return old; 146570af302Sopenharmony_ci} 147570af302Sopenharmony_ci#endif 148570af302Sopenharmony_ci 149570af302Sopenharmony_ci#ifndef a_and 150570af302Sopenharmony_ci#define a_and a_and 151570af302Sopenharmony_cistatic inline void a_and(volatile int *p, int v) 152570af302Sopenharmony_ci{ 153570af302Sopenharmony_ci a_fetch_and(p, v); 154570af302Sopenharmony_ci} 155570af302Sopenharmony_ci#endif 156570af302Sopenharmony_ci 157570af302Sopenharmony_ci#ifndef a_or 158570af302Sopenharmony_ci#define a_or a_or 159570af302Sopenharmony_cistatic inline void a_or(volatile int *p, int v) 160570af302Sopenharmony_ci{ 161570af302Sopenharmony_ci a_fetch_or(p, v); 162570af302Sopenharmony_ci} 163570af302Sopenharmony_ci#endif 164570af302Sopenharmony_ci 165570af302Sopenharmony_ci#ifndef a_inc 166570af302Sopenharmony_ci#define a_inc a_inc 167570af302Sopenharmony_cistatic inline void a_inc(volatile int *p) 168570af302Sopenharmony_ci{ 169570af302Sopenharmony_ci a_fetch_add(p, 1); 170570af302Sopenharmony_ci} 171570af302Sopenharmony_ci#endif 172570af302Sopenharmony_ci 173570af302Sopenharmony_ci#ifndef a_dec 174570af302Sopenharmony_ci#define a_dec a_dec 175570af302Sopenharmony_cistatic inline void a_dec(volatile int *p) 176570af302Sopenharmony_ci{ 177570af302Sopenharmony_ci a_fetch_add(p, -1); 178570af302Sopenharmony_ci} 179570af302Sopenharmony_ci#endif 180570af302Sopenharmony_ci 181570af302Sopenharmony_ci#ifndef a_store 182570af302Sopenharmony_ci#define a_store a_store 183570af302Sopenharmony_cistatic inline void a_store(volatile int *p, int v) 184570af302Sopenharmony_ci{ 185570af302Sopenharmony_ci#ifdef a_barrier 186570af302Sopenharmony_ci a_barrier(); 187570af302Sopenharmony_ci *p = v; 188570af302Sopenharmony_ci a_barrier(); 189570af302Sopenharmony_ci#else 190570af302Sopenharmony_ci a_swap(p, v); 191570af302Sopenharmony_ci#endif 192570af302Sopenharmony_ci} 193570af302Sopenharmony_ci#endif 194570af302Sopenharmony_ci 195570af302Sopenharmony_ci#ifndef a_barrier 196570af302Sopenharmony_ci#define a_barrier a_barrier 197570af302Sopenharmony_cistatic void a_barrier() 198570af302Sopenharmony_ci{ 199570af302Sopenharmony_ci volatile int tmp = 0; 200570af302Sopenharmony_ci a_cas(&tmp, 0, 0); 201570af302Sopenharmony_ci} 202570af302Sopenharmony_ci#endif 203570af302Sopenharmony_ci 204570af302Sopenharmony_ci#ifndef a_spin 205570af302Sopenharmony_ci#define a_spin a_barrier 206570af302Sopenharmony_ci#endif 207570af302Sopenharmony_ci 208570af302Sopenharmony_ci#ifndef a_and_64 209570af302Sopenharmony_ci#define a_and_64 a_and_64 210570af302Sopenharmony_cistatic inline void a_and_64(volatile uint64_t *p, uint64_t v) 211570af302Sopenharmony_ci{ 212570af302Sopenharmony_ci union { uint64_t v; uint32_t r[2]; } u = { v }; 213570af302Sopenharmony_ci if (u.r[0]+1) a_and((int *)p, u.r[0]); 214570af302Sopenharmony_ci if (u.r[1]+1) a_and((int *)p+1, u.r[1]); 215570af302Sopenharmony_ci} 216570af302Sopenharmony_ci#endif 217570af302Sopenharmony_ci 218570af302Sopenharmony_ci#ifndef a_or_64 219570af302Sopenharmony_ci#define a_or_64 a_or_64 220570af302Sopenharmony_cistatic inline void a_or_64(volatile uint64_t *p, uint64_t v) 221570af302Sopenharmony_ci{ 222570af302Sopenharmony_ci union { uint64_t v; uint32_t r[2]; } u = { v }; 223570af302Sopenharmony_ci if (u.r[0]) a_or((int *)p, u.r[0]); 224570af302Sopenharmony_ci if (u.r[1]) a_or((int *)p+1, u.r[1]); 225570af302Sopenharmony_ci} 226570af302Sopenharmony_ci#endif 227570af302Sopenharmony_ci 228570af302Sopenharmony_ci#ifndef a_cas_p 229570af302Sopenharmony_citypedef char a_cas_p_undefined_but_pointer_not_32bit[-sizeof(char) == 0xffffffff ? 1 : -1]; 230570af302Sopenharmony_ci#define a_cas_p a_cas_p 231570af302Sopenharmony_cistatic inline void *a_cas_p(volatile void *p, void *t, void *s) 232570af302Sopenharmony_ci{ 233570af302Sopenharmony_ci return (void *)a_cas((volatile int *)p, (int)t, (int)s); 234570af302Sopenharmony_ci} 235570af302Sopenharmony_ci#endif 236570af302Sopenharmony_ci 237570af302Sopenharmony_ci#ifndef a_or_l 238570af302Sopenharmony_ci#define a_or_l a_or_l 239570af302Sopenharmony_cistatic inline void a_or_l(volatile void *p, long v) 240570af302Sopenharmony_ci{ 241570af302Sopenharmony_ci if (sizeof(long) == sizeof(int)) a_or(p, v); 242570af302Sopenharmony_ci else a_or_64(p, v); 243570af302Sopenharmony_ci} 244570af302Sopenharmony_ci#endif 245570af302Sopenharmony_ci 246570af302Sopenharmony_ci#ifndef a_crash 247570af302Sopenharmony_ci#define a_crash a_crash 248570af302Sopenharmony_cistatic inline void a_crash() 249570af302Sopenharmony_ci{ 250570af302Sopenharmony_ci *(volatile char *)0=0; 251570af302Sopenharmony_ci} 252570af302Sopenharmony_ci#endif 253570af302Sopenharmony_ci 254570af302Sopenharmony_ci#ifndef a_ctz_32 255570af302Sopenharmony_ci#define a_ctz_32 a_ctz_32 256570af302Sopenharmony_cistatic inline int a_ctz_32(uint32_t x) 257570af302Sopenharmony_ci{ 258570af302Sopenharmony_ci#ifdef a_clz_32 259570af302Sopenharmony_ci return 31-a_clz_32(x&-x); 260570af302Sopenharmony_ci#else 261570af302Sopenharmony_ci static const char debruijn32[32] = { 262570af302Sopenharmony_ci 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 263570af302Sopenharmony_ci 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 264570af302Sopenharmony_ci }; 265570af302Sopenharmony_ci return debruijn32[(x&-x)*0x076be629 >> 27]; 266570af302Sopenharmony_ci#endif 267570af302Sopenharmony_ci} 268570af302Sopenharmony_ci#endif 269570af302Sopenharmony_ci 270570af302Sopenharmony_ci#ifndef a_ctz_64 271570af302Sopenharmony_ci#define a_ctz_64 a_ctz_64 272570af302Sopenharmony_cistatic inline int a_ctz_64(uint64_t x) 273570af302Sopenharmony_ci{ 274570af302Sopenharmony_ci static const char debruijn64[64] = { 275570af302Sopenharmony_ci 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 276570af302Sopenharmony_ci 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, 277570af302Sopenharmony_ci 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, 278570af302Sopenharmony_ci 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 279570af302Sopenharmony_ci }; 280570af302Sopenharmony_ci if (sizeof(long) < 8) { 281570af302Sopenharmony_ci uint32_t y = x; 282570af302Sopenharmony_ci if (!y) { 283570af302Sopenharmony_ci y = x>>32; 284570af302Sopenharmony_ci return 32 + a_ctz_32(y); 285570af302Sopenharmony_ci } 286570af302Sopenharmony_ci return a_ctz_32(y); 287570af302Sopenharmony_ci } 288570af302Sopenharmony_ci return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58]; 289570af302Sopenharmony_ci} 290570af302Sopenharmony_ci#endif 291570af302Sopenharmony_ci 292570af302Sopenharmony_cistatic inline int a_ctz_l(unsigned long x) 293570af302Sopenharmony_ci{ 294570af302Sopenharmony_ci return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x); 295570af302Sopenharmony_ci} 296570af302Sopenharmony_ci 297570af302Sopenharmony_ci#ifndef a_clz_64 298570af302Sopenharmony_ci#define a_clz_64 a_clz_64 299570af302Sopenharmony_cistatic inline int a_clz_64(uint64_t x) 300570af302Sopenharmony_ci{ 301570af302Sopenharmony_ci#ifdef a_clz_32 302570af302Sopenharmony_ci if (x>>32) 303570af302Sopenharmony_ci return a_clz_32(x>>32); 304570af302Sopenharmony_ci return a_clz_32(x) + 32; 305570af302Sopenharmony_ci#else 306570af302Sopenharmony_ci uint32_t y; 307570af302Sopenharmony_ci int r; 308570af302Sopenharmony_ci if (x>>32) y=x>>32, r=0; else y=x, r=32; 309570af302Sopenharmony_ci if (y>>16) y>>=16; else r |= 16; 310570af302Sopenharmony_ci if (y>>8) y>>=8; else r |= 8; 311570af302Sopenharmony_ci if (y>>4) y>>=4; else r |= 4; 312570af302Sopenharmony_ci if (y>>2) y>>=2; else r |= 2; 313570af302Sopenharmony_ci return r | !(y>>1); 314570af302Sopenharmony_ci#endif 315570af302Sopenharmony_ci} 316570af302Sopenharmony_ci#endif 317570af302Sopenharmony_ci 318570af302Sopenharmony_ci#ifndef a_clz_32 319570af302Sopenharmony_ci#define a_clz_32 a_clz_32 320570af302Sopenharmony_cistatic inline int a_clz_32(uint32_t x) 321570af302Sopenharmony_ci{ 322570af302Sopenharmony_ci x >>= 1; 323570af302Sopenharmony_ci x |= x >> 1; 324570af302Sopenharmony_ci x |= x >> 2; 325570af302Sopenharmony_ci x |= x >> 4; 326570af302Sopenharmony_ci x |= x >> 8; 327570af302Sopenharmony_ci x |= x >> 16; 328570af302Sopenharmony_ci x++; 329570af302Sopenharmony_ci return 31-a_ctz_32(x); 330570af302Sopenharmony_ci} 331570af302Sopenharmony_ci#endif 332570af302Sopenharmony_ci 333570af302Sopenharmony_ci#endif 334