Intel memory model discussion cont

Continuing the discussion from Uninitialized memory varying from read to read:

Then yes, you were not understanding me. I was asking if the reason that mov didn't need lock, while read-modify-write operations like xadd, cmpxchg was that mov was always atomic even without lock, while RMW ops were not. Which is why I was confused about you asserting that MESI would apply to unlocked ops.

If so -- then Rust is already doing what you were asking for (see the godbolt link above). Atomic load and store are already not using lock on intel unless you are using SeqCst. The RMW atomic operations are, because otherwise it's not atomic. As it turns out, just writing what you mean does the right thing.

Literally creating a target is actually quite easy, it's all described in the link I put in that post:

# If you don't have it already...
$ rustup toolchain install nightly
# copy your default target to a new target file. use --target whatever to copy a different one
# Unfortunately, you need to name the target file after the LLVM target, due to crappy heuristics
# in std (it is pre-release!):
$ rustc +nightly -Z unstable-options --print target-spec-json --target x86_64-unknown-linux-glibc > x86_64-unknown-linux-glibc.json
# remove "is-builtin": true from the target json, any other changes you want
# build your crate and standard library, using your new target. build-std is required because
# there is no existing build for your custom target, of course!
$ cargo +nightly -Z build-std build --target x86_64-unknown-linux-glibc.json

You need to use nightly to use the unstable -Z options, and there's that annoying issue, but otherwise it's pretty straightforward.

Having actually tried dropping the preferred alignment of everything to 8 bits, though, I hit the error:

LLVM ERROR: Preferred alignment cannot be less than the ABI alignment

And then dropping the ABI alignment as well (which surely would break everything!) hits:

error[E0527]: pattern requires 0 elements but array has 7
    --> C:\Users\simon\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\sync\
1591 |                   let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
     |                       ^^ expected 7 elements
2533 | / atomic_int_ptr_sized! {
2534 | |     "16" 2
2535 | |     "32" 4
2536 | |     "64" 8
2537 | | }
     | |_- in this macro invocation
     = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info)

This is a bit annoying, I'm not sure why the atomics source hard-codes the alignment to the int size. LLVM doesn't require this.

It's avoiding creating an unaligned reference, which would be UB.

There is apparently a cfg(target_has_atomic_equal_alignment) you could perhaps adjust:

1 Like

For context, the intent here is to create a modified target where the alignment of everything is 1 to test the idea that Haswell+ don't have preferred alignment. So far as I'm aware, AtomicFoo should always have the same alignment as plain foo, so I don't know why it needs an explicit align at all, it should inherit it automatically.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.