fix public clone function to be safe and usable by applications
[musl] / src / internal / atomic.h
index 2097247..96c1552 100644 (file)
@@ -82,6 +82,23 @@ static inline int a_fetch_or(volatile int *p, int v)
 
 #endif
 
+#ifdef a_ll_p
+
+#ifndef a_cas_p
+#define a_cas_p a_cas_p
+static inline void *a_cas_p(volatile void *p, void *t, void *s)
+{
+       void *old;
+       a_pre_llsc();
+       do old = a_ll_p(p);
+       while (old==t && !a_sc_p(p, s));
+       a_post_llsc();
+       return old;
+}
+#endif
+
+#endif
+
 #ifndef a_cas
 #error missing definition of a_cas
 #endif
@@ -209,6 +226,7 @@ static inline void a_or_64(volatile uint64_t *p, uint64_t v)
 #endif
 
 #ifndef a_cas_p
+typedef char a_cas_p_undefined_but_pointer_not_32bit[-sizeof(char) == 0xffffffff ? 1 : -1];
 #define a_cas_p a_cas_p
 static inline void *a_cas_p(volatile void *p, void *t, void *s)
 {
@@ -233,6 +251,22 @@ static inline void a_crash()
 }
 #endif
 
+#ifndef a_ctz_32
+#define a_ctz_32 a_ctz_32
+static inline int a_ctz_32(uint32_t x)
+{
+#ifdef a_clz_32
+       return 31-a_clz_32(x&-x);
+#else
+       static const char debruijn32[32] = {
+               0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
+               31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
+       };
+       return debruijn32[(x&-x)*0x076be629 >> 27];
+#endif
+}
+#endif
+
 #ifndef a_ctz_64
 #define a_ctz_64 a_ctz_64
 static inline int a_ctz_64(uint64_t x)
@@ -243,32 +277,56 @@ static inline int a_ctz_64(uint64_t x)
                63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
                51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
        };
-       static const char debruijn32[32] = {
-               0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
-               31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
-       };
        if (sizeof(long) < 8) {
                uint32_t y = x;
                if (!y) {
                        y = x>>32;
-                       return 32 + debruijn32[(y&-y)*0x076be629 >> 27];
+                       return 32 + a_ctz_32(y);
                }
-               return debruijn32[(y&-y)*0x076be629 >> 27];
+               return a_ctz_32(y);
        }
        return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
 }
 #endif
 
-#ifndef a_ctz_l
-#define a_ctz_l a_ctz_l
 static inline int a_ctz_l(unsigned long x)
 {
-       static const char debruijn32[32] = {
-               0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
-               31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
-       };
-       if (sizeof(long) == 8) return a_ctz_64(x);
-       return debruijn32[(x&-x)*0x076be629 >> 27];
+       return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x);
+}
+
+#ifndef a_clz_64
+#define a_clz_64 a_clz_64
+static inline int a_clz_64(uint64_t x)
+{
+#ifdef a_clz_32
+       if (x>>32)
+               return a_clz_32(x>>32);
+       return a_clz_32(x) + 32;
+#else
+       uint32_t y;
+       int r;
+       if (x>>32) y=x>>32, r=0; else y=x, r=32;
+       if (y>>16) y>>=16; else r |= 16;
+       if (y>>8) y>>=8; else r |= 8;
+       if (y>>4) y>>=4; else r |= 4;
+       if (y>>2) y>>=2; else r |= 2;
+       return r | !(y>>1);
+#endif
+}
+#endif
+
+#ifndef a_clz_32
+#define a_clz_32 a_clz_32
+static inline int a_clz_32(uint32_t x)
+{
+       x >>= 1;
+       x |= x >> 1;
+       x |= x >> 2;
+       x |= x >> 4;
+       x |= x >> 8;
+       x |= x >> 16;
+       x++;
+       return 31-a_ctz_32(x);
 }
 #endif