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);
}