Skip to content

x86_64 cmpxchgl constraints are odd and easy to miscompile #54

@braindigitalis

Description

@braindigitalis
uint32_t expected = 0;
uint32_t desired = 1;
uint32_t old;
asm volatile("lock cmpxchgl %2, %1"
             : "=a"(old), "+m"(lock->lock)
             : "r"(desired), "0"(expected)
             : "memory", "cc");
if (old == 0) { return; }

cmpxchg uses EAX/RAX as the expected value input and returns the previous value in EAX. The constraints here are non-standard-looking: old is output in =a, and expected is tied to operand 0 via "0"(expected).

This might work, but it’s brittle. If the compiler decides to treat old purely as output and doesn’t initialise EAX from expected correctly under some optimisation, you get incorrect behaviour. In kernel code, “brittle inline asm constraints” is a common source of heisenbugs and lockups.

Even if it’s correct today, it’s a miscompile risk.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions