#define natural_t uint64_t #define natural_logbytes 3 /* = log_2(sizeof(natural_t)) */ #define atomic_cas_natural atomic_cas_64 #define natural_t uint32_t #define natural_logbytes 2 /* = log_2(sizeof(natural_t)) */ #define atomic_cas_natural atomic_cas_32 #define small_t uint16_t #define small_bits 16 /* = sizeof(small_t)*CHAR_BIT */ #define small_logbytes 1 /* = log_2(sizeof(small_t)) */ #define atomic_cas_small atomic_cas_16 #define small_t uint8_t #define small_bits 8 /* = sizeof(small_t)*CHAR_BIT */ #define small_logbytes 0 /* = log_2(sizeof(small_t)) */ #define atomic_cas_small atomic_cas_8 small_t atomic_cas_small(volatile small_t *ptr, small_t old, small_t new) { const uintptr_t addr = (uintptr_t)ptr; const uintptr_t highmask = ~(uintptr_t)0 << natural_logbytes; volatile natural_t *const nptr = (volatile natural_t *) (addr & highmask); const unsigned shift = small_bits * ((addr & ~highmask) >> small_logbytes); const natural_t mask = ~(~(natural_t)0 << small_bits) << shift; const natural_t nold_part = (natural_t)old << shift; const natural_t nnew_part = (natural_t)new << shift; natural_t nold, nnew; assert((addr & ~(~(uintptr_t)0 << small_logbytes)) == 0); do { nold = *nptr; if ((nold & mask) != nold_part) return (nold & mask) >> shift; nnew = ((nold & ~mask) | nnew_part); } while (atomic_cas_natural(nptr, nold, nnew) != nold); return nnew; }