#define word_t uint64_t #define word_logbytes 3 /* = log_2(sizeof(word_t)) */ #define atomic_cas_word atomic_cas_64 #define word_t uint32_t #define word_logbytes 2 /* = log_2(sizeof(word_t)) */ #define atomic_cas_word atomic_cas_32 #define subword_t uint16_t #define subword_logbytes 1 /* = log_2(sizeof(subword_t)) */ #define atomic_cas_subword atomic_cas_16 #define subword_t uint8_t #define subword_logbytes 0 /* = log_2(sizeof(subword_t)) */ #define atomic_cas_subword atomic_cas_8 subword_t atomic_cas_subword(volatile subword_t *ptr, subword_t old, subword_t new) { const uintptr_t addr = (uintptr_t)ptr; const uintptr_t addrmask = ~(uintptr_t)0 << word_logbytes; volatile word_t *const wptr = (volatile word_t *) (addr & addrmask); const unsigned shift = sizeof(subword_t)*CHAR_BIT * ((addr & ~addrmask) >> subword_logbytes); const word_t mask = ~(~(word_t)0 << sizeof(subword_t)*CHAR_BIT) << shift; const word_t wold_part = (word_t)old << shift; const word_t wnew_part = (word_t)new << shift; word_t wold, wnew; assert((addr & ~(~(uintptr_t)0 << subword_logbytes)) == 0); do { wold = *wptr; if ((wold & mask) != wold_part) return (subword_t)((wold & mask) >> shift); wnew = ((wold & ~mask) | wnew_part); } while (atomic_cas_word(wptr, wold, wnew) != wold); return old; }