Rust and UB
Rust and UB
Posted Aug 16, 2024 11:16 UTC (Fri) by pbonzini (subscriber, #60935)In reply to: Rust and UB by ralfj
Parent article: Standards for use of unsafe Rust in the kernel
Agreed. It would be nice to have a formal promise for that, as it's UB with the current models. But if not I think it's possible for Linux to live with *this* specific UB.
> to make sure we are talking about the same thing, you are using the operations from the C "atomics" library (https://en.cppreference.com/w/c/atomic), and no volatile accesses or inline assembly?
Yes—but not in Linux, only in QEMU. QEMU is in user space and uses the C memory model, but historically most people involved were more familiar with Linux atomics. We limit ourselves to a restricted API (consisting of relaxed load, relaxed store, acquire load, release store, SeqCst read-modify-write operations, and acquire/release/full fences) that mostly resembles the Linux API but is implemented on top of C atomics. Maybe something like that could be used as a starting point to bridge LKMM and Rust memory models. As you say there would be some handwaving on how compatible the happens-before relationships are; assuming that the Rust and C worlds are separate enough, maybe you can treat them similar to kernel–userspace or inter-process cases.
> Even if the processor can't do such reorderings, the compiler can. So I see no way to ever justify using compiler fences instead of thread fences in a principled way.
My understanding is that compiler fences can be used instead of thread fences if you know that two threads only ever run on the same physical CPUs. So, as far as the compiler is concerned, they should block the same optimizations as thread fences, generating the same code apart from the fence instructions themselves. The assumptions that are made on generated instructions might be dubious in terms of portability, but they're fine with respect to data races and hence UB.
> I would expect that on strongly ordered hardware like x86, most thread fences anyway compile to NOPs?
The main exception is SeqCst fences after SeqCst RMW operation. Those are unnecessary and pretty expensive (a few tens of cycles) even on x86, and we have a couple in really hot places. I think only Arm needs a processor fence instead, for some unobvious reason related to the semantics of LDAR instructions (which are stronger than just acquire) and to the code that's generated for SeqCst RMW operations.
