#ifndef __DISPATCH_SHIMS_ATOMIC_SFB__
#define __DISPATCH_SHIMS_ATOMIC_SFB__
#if __clang__ && __clang_major__ < 5 // <rdar://problem/13833871>
#define __builtin_ffs(x) __builtin_ffs((unsigned int)(x))
#endif
#define os_atomic_set_first_bit(p,m) _os_atomic_set_first_bit(p,m)
DISPATCH_ALWAYS_INLINE
static inline unsigned int
_os_atomic_set_first_bit(volatile unsigned long *p,
unsigned int max_index)
{
unsigned int index;
unsigned long b, mask, b_masked;
for (;;) {
b = *p;
index = (unsigned int)__builtin_ffsl((long)~b);
if (slowpath(index == 0)) {
return UINT_MAX;
}
index--;
if (slowpath(index > max_index)) {
return UINT_MAX;
}
mask = ((typeof(b))1) << index;
b_masked = b | mask;
if (__sync_bool_compare_and_swap(p, b, b_masked)) {
return index;
}
}
}
#if defined(__x86_64__) || defined(__i386__)
#undef os_atomic_set_first_bit
DISPATCH_ALWAYS_INLINE
static inline unsigned int
os_atomic_set_first_bit(volatile unsigned long *p, unsigned int max)
{
unsigned long val, bit;
if (max > (sizeof(val) * 8)) {
__asm__ (
"1: \n\t"
"mov %[_p], %[_val] \n\t"
"not %[_val] \n\t"
"bsf %[_val], %[_bit] \n\t"
"jz 2f \n\t"
"lock \n\t"
"bts %[_bit], %[_p] \n\t"
"jc 1b \n\t"
"jmp 3f \n\t"
"2: \n\t"
"mov %[_all_ones], %[_bit]" "\n\t"
"3: \n\t"
: [_p] "=m" (*p), [_val] "=&r" (val), [_bit] "=&r" (bit)
: [_all_ones] "i" ((typeof(bit))UINT_MAX) : "memory", "cc");
} else {
__asm__ (
"1: \n\t"
"mov %[_p], %[_val] \n\t"
"not %[_val] \n\t"
"bsf %[_val], %[_bit] \n\t"
"jz 2f \n\t"
"cmp %[_max], %[_bit] \n\t"
"jg 2f \n\t"
"lock \n\t"
"bts %[_bit], %[_p] \n\t"
"jc 1b \n\t"
"jmp 3f \n\t"
"2: \n\t"
"mov %[_all_ones], %[_bit]" "\n\t"
"3: \n\t"
: [_p] "=m" (*p), [_val] "=&r" (val), [_bit] "=&r" (bit)
: [_all_ones] "i" ((typeof(bit))UINT_MAX),
[_max] "g" ((typeof(bit))max) : "memory", "cc");
}
return (unsigned int)bit;
}
#endif
#endif // __DISPATCH_SHIMS_ATOMIC_SFB__