#ifndef __DISPATCH_SHIMS_ATOMIC_SFB__
#define __DISPATCH_SHIMS_ATOMIC_SFB__
#if defined(__x86_64__) || defined(__i386__)
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;
}
#else
#if __clang__ && __clang_major__ < 5 // <rdar://problem/13833871>
#define __builtin_ffs(x) __builtin_ffs((unsigned int)(x))
#endif
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, b_masked;
os_atomic_rmw_loop(p, b, b_masked, relaxed, {
index = (unsigned int)__builtin_ffsl((long)~b);
if (unlikely(index == 0)) {
os_atomic_rmw_loop_give_up(return UINT_MAX);
}
index--;
if (unlikely(index > max_index)) {
os_atomic_rmw_loop_give_up(return UINT_MAX);
}
b_masked = b | (1UL << index);
});
return index;
}
#endif
#endif // __DISPATCH_SHIMS_ATOMIC_SFB__