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