Skip to content

x86_64 cmpxchgl constraints are odd and easy to miscompile #54

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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