github.com/afumu/libc@v0.0.6/musl/src/internal/atomic.h (about)

     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