atomic.h raw

   1  #ifndef _ATOMIC_H
   2  #define _ATOMIC_H
   3  
   4  #include <stdint.h>
   5  
   6  #include "atomic_arch.h"
   7  
   8  #ifdef a_ll
   9  
  10  #ifndef a_pre_llsc
  11  #define a_pre_llsc()
  12  #endif
  13  
  14  #ifndef a_post_llsc
  15  #define a_post_llsc()
  16  #endif
  17  
  18  #ifndef a_cas
  19  #define a_cas a_cas
  20  static inline int a_cas(volatile int *p, int t, int s)
  21  {
  22  	int old;
  23  	a_pre_llsc();
  24  	do old = a_ll(p);
  25  	while (old==t && !a_sc(p, s));
  26  	a_post_llsc();
  27  	return old;
  28  }
  29  #endif
  30  
  31  #ifndef a_swap
  32  #define a_swap a_swap
  33  static inline int a_swap(volatile int *p, int v)
  34  {
  35  	int old;
  36  	a_pre_llsc();
  37  	do old = a_ll(p);
  38  	while (!a_sc(p, v));
  39  	a_post_llsc();
  40  	return old;
  41  }
  42  #endif
  43  
  44  #ifndef a_fetch_add
  45  #define a_fetch_add a_fetch_add
  46  static inline int a_fetch_add(volatile int *p, int v)
  47  {
  48  	int old;
  49  	a_pre_llsc();
  50  	do old = a_ll(p);
  51  	while (!a_sc(p, (unsigned)old + v));
  52  	a_post_llsc();
  53  	return old;
  54  }
  55  #endif
  56  
  57  #ifndef a_fetch_and
  58  #define a_fetch_and a_fetch_and
  59  static inline int a_fetch_and(volatile int *p, int v)
  60  {
  61  	int old;
  62  	a_pre_llsc();
  63  	do old = a_ll(p);
  64  	while (!a_sc(p, old & v));
  65  	a_post_llsc();
  66  	return old;
  67  }
  68  #endif
  69  
  70  #ifndef a_fetch_or
  71  #define a_fetch_or a_fetch_or
  72  static inline int a_fetch_or(volatile int *p, int v)
  73  {
  74  	int old;
  75  	a_pre_llsc();
  76  	do old = a_ll(p);
  77  	while (!a_sc(p, old | v));
  78  	a_post_llsc();
  79  	return old;
  80  }
  81  #endif
  82  
  83  #endif
  84  
  85  #ifdef a_ll_p
  86  
  87  #ifndef a_cas_p
  88  #define a_cas_p a_cas_p
  89  static inline void *a_cas_p(volatile void *p, void *t, void *s)
  90  {
  91  	void *old;
  92  	a_pre_llsc();
  93  	do old = a_ll_p(p);
  94  	while (old==t && !a_sc_p(p, s));
  95  	a_post_llsc();
  96  	return old;
  97  }
  98  #endif
  99  
 100  #endif
 101  
 102  #ifndef a_cas
 103  #error missing definition of a_cas
 104  #endif
 105  
 106  #ifndef a_swap
 107  #define a_swap a_swap
 108  static inline int a_swap(volatile int *p, int v)
 109  {
 110  	int old;
 111  	do old = *p;
 112  	while (a_cas(p, old, v) != old);
 113  	return old;
 114  }
 115  #endif
 116  
 117  #ifndef a_fetch_add
 118  #define a_fetch_add a_fetch_add
 119  static inline int a_fetch_add(volatile int *p, int v)
 120  {
 121  	int old;
 122  	do old = *p;
 123  	while (a_cas(p, old, (unsigned)old+v) != old);
 124  	return old;
 125  }
 126  #endif
 127  
 128  #ifndef a_fetch_and
 129  #define a_fetch_and a_fetch_and
 130  static inline int a_fetch_and(volatile int *p, int v)
 131  {
 132  	int old;
 133  	do old = *p;
 134  	while (a_cas(p, old, old&v) != old);
 135  	return old;
 136  }
 137  #endif
 138  #ifndef a_fetch_or
 139  #define a_fetch_or a_fetch_or
 140  static inline int a_fetch_or(volatile int *p, int v)
 141  {
 142  	int old;
 143  	do old = *p;
 144  	while (a_cas(p, old, old|v) != old);
 145  	return old;
 146  }
 147  #endif
 148  
 149  #ifndef a_and
 150  #define a_and a_and
 151  static inline void a_and(volatile int *p, int v)
 152  {
 153  	a_fetch_and(p, v);
 154  }
 155  #endif
 156  
 157  #ifndef a_or
 158  #define a_or a_or
 159  static inline void a_or(volatile int *p, int v)
 160  {
 161  	a_fetch_or(p, v);
 162  }
 163  #endif
 164  
 165  #ifndef a_inc
 166  #define a_inc a_inc
 167  static inline void a_inc(volatile int *p)
 168  {
 169  	a_fetch_add(p, 1);
 170  }
 171  #endif
 172  
 173  #ifndef a_dec
 174  #define a_dec a_dec
 175  static inline void a_dec(volatile int *p)
 176  {
 177  	a_fetch_add(p, -1);
 178  }
 179  #endif
 180  
 181  #ifndef a_store
 182  #define a_store a_store
 183  static inline void a_store(volatile int *p, int v)
 184  {
 185  #ifdef a_barrier
 186  	a_barrier();
 187  	*p = v;
 188  	a_barrier();
 189  #else
 190  	a_swap(p, v);
 191  #endif
 192  }
 193  #endif
 194  
 195  #ifndef a_barrier
 196  #define a_barrier a_barrier
 197  static void a_barrier()
 198  {
 199  	volatile int tmp = 0;
 200  	a_cas(&tmp, 0, 0);
 201  }
 202  #endif
 203  
 204  #ifndef a_spin
 205  #define a_spin a_barrier
 206  #endif
 207  
 208  #ifndef a_and_64
 209  #define a_and_64 a_and_64
 210  static inline void a_and_64(volatile uint64_t *p, uint64_t v)
 211  {
 212  	union { uint64_t v; uint32_t r[2]; } u = { v };
 213  	if (u.r[0]+1) a_and((int *)p, u.r[0]);
 214  	if (u.r[1]+1) a_and((int *)p+1, u.r[1]);
 215  }
 216  #endif
 217  
 218  #ifndef a_or_64
 219  #define a_or_64 a_or_64
 220  static inline void a_or_64(volatile uint64_t *p, uint64_t v)
 221  {
 222  	union { uint64_t v; uint32_t r[2]; } u = { v };
 223  	if (u.r[0]) a_or((int *)p, u.r[0]);
 224  	if (u.r[1]) a_or((int *)p+1, u.r[1]);
 225  }
 226  #endif
 227  
 228  #ifndef a_cas_p
 229  typedef char a_cas_p_undefined_but_pointer_not_32bit[-sizeof(char) == 0xffffffff ? 1 : -1];
 230  #define a_cas_p a_cas_p
 231  static inline void *a_cas_p(volatile void *p, void *t, void *s)
 232  {
 233  	return (void *)a_cas((volatile int *)p, (int)t, (int)s);
 234  }
 235  #endif
 236  
 237  #ifndef a_or_l
 238  #define a_or_l a_or_l
 239  static inline void a_or_l(volatile void *p, long v)
 240  {
 241  	if (sizeof(long) == sizeof(int)) a_or(p, v);
 242  	else a_or_64(p, v);
 243  }
 244  #endif
 245  
 246  #ifndef a_crash
 247  #define a_crash a_crash
 248  static inline void a_crash()
 249  {
 250  	*(volatile char *)0=0;
 251  }
 252  #endif
 253  
 254  #ifndef a_ctz_32
 255  #define a_ctz_32 a_ctz_32
 256  static inline int a_ctz_32(uint32_t x)
 257  {
 258  #ifdef a_clz_32
 259  	return 31-a_clz_32(x&-x);
 260  #else
 261  	static const char debruijn32[32] = {
 262  		0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
 263  		31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
 264  	};
 265  	return debruijn32[(x&-x)*0x076be629 >> 27];
 266  #endif
 267  }
 268  #endif
 269  
 270  #ifndef a_ctz_64
 271  #define a_ctz_64 a_ctz_64
 272  static inline int a_ctz_64(uint64_t x)
 273  {
 274  	static const char debruijn64[64] = {
 275  		0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
 276  		62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
 277  		63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
 278  		51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
 279  	};
 280  	if (sizeof(long) < 8) {
 281  		uint32_t y = x;
 282  		if (!y) {
 283  			y = x>>32;
 284  			return 32 + a_ctz_32(y);
 285  		}
 286  		return a_ctz_32(y);
 287  	}
 288  	return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
 289  }
 290  #endif
 291  
 292  static inline int a_ctz_l(unsigned long x)
 293  {
 294  	return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x);
 295  }
 296  
 297  #ifndef a_clz_64
 298  #define a_clz_64 a_clz_64
 299  static inline int a_clz_64(uint64_t x)
 300  {
 301  #ifdef a_clz_32
 302  	if (x>>32)
 303  		return a_clz_32(x>>32);
 304  	return a_clz_32(x) + 32;
 305  #else
 306  	uint32_t y;
 307  	int r;
 308  	if (x>>32) y=x>>32, r=0; else y=x, r=32;
 309  	if (y>>16) y>>=16; else r |= 16;
 310  	if (y>>8) y>>=8; else r |= 8;
 311  	if (y>>4) y>>=4; else r |= 4;
 312  	if (y>>2) y>>=2; else r |= 2;
 313  	return r | !(y>>1);
 314  #endif
 315  }
 316  #endif
 317  
 318  #ifndef a_clz_32
 319  #define a_clz_32 a_clz_32
 320  static inline int a_clz_32(uint32_t x)
 321  {
 322  	x >>= 1;
 323  	x |= x >> 1;
 324  	x |= x >> 2;
 325  	x |= x >> 4;
 326  	x |= x >> 8;
 327  	x |= x >> 16;
 328  	x++;
 329  	return 31-a_ctz_32(x);
 330  }
 331  #endif
 332  
 333  #endif
 334