Re: locking/atomic: Introduce atomic_try_cmpxchg()
From: Linus Torvalds
Date: Fri Mar 24 2017 - 16:59:08 EST
On Fri, Mar 24, 2017 at 1:46 PM, Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> I certainly like it better, but so far I'm having trouble reproducing
> your results. What compiler version are you on?
I have:
gcc version 6.3.1 20161221 (Red Hat 6.3.1-1) (GCC)
from
gcc-6.3.1-1.fc24.x86_64
and I'm attaching the edited form of your test-case, just so that
we're on the exact same page.
Linus
/* gcc -Os -std=gnu99 -fno-strict-overflow -falign-jumps=1 -falign-loops=1 -c tiny.c; objdump -dr tiny.o */
typedef _Bool bool;
#define try_cmpxchg(ptr, value, new, success_label) ({ \
bool __txchg_success; \
__typeof__(*(ptr)) __old; \
asm volatile("lock cmpxchgl %3, %1" \
: "=@ccz" (__txchg_success), \
"+m" (*ptr), \
"=a" (__old) \
: "r" (new), \
"2" (value) \
: "memory"); \
if (likely(__txchg_success)) goto success_label;\
__old; })
#define EXCEPTION_VALUE(val, handler) asm volatile ("ud2 # %0" : : "r" (val))
#define UINT_MAX (~0U)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
static inline void refcount_inc(unsigned int *r)
{
unsigned int new, val = *(unsigned int volatile *)r;
for (;;) {
if (unlikely(val == UINT_MAX)) /* saturated */
return;
if (unlikely(!val)) /* use-after-free */
goto exception;
/* cannot overflow because we already checked UINT_MAX */
new = val + 1;
val = try_cmpxchg(r, val, new, success);
}
success:
return;
exception:
EXCEPTION_VALUE(val, __refcount_warn);
}
void T_refcount_inc(unsigned int *r)
{
refcount_inc(r);
}