Disclaimer: I'm not an expert at all; essentially just answering in the hope that someone will correct / expand on this.
It seems the main issue is that this concerns the entire combination of machine semantics, OS semantics, and language semantics, and I would actually be surprised if that combination is sufficiently well-specified.
Focusing on the Rust side at first, I think everything would have well-defined semantics if fence
followed by sendmsg
was a single "external" operation, and so was recvmsg
followed by fence
. E.g. if both were C functions, and the shared memory is accessed via a raw pointer that may be aliased, things basically come down to how the C functions access the shared memory (or cause accesses later).
In particular, the compiler would definitely not be allowed to reorder these function calls with accesses to the shared memory, unless it could prove that the functions cannot possibly access the same memory without causing undefined behavior. This is an important caveat, e.g. if you hold a reference across such a call, that's essentially a promise that the corresponding location within the shared memory will not be written to or not even be read, depending on the reference.
Moreover, the two processes are required to cooperate in order to avoid data races (unless atomic accesses are used everywhere). Not sure if it's a good idea to have undefined behavior in case another process misbehaves.
I think these conditions can be formulated as safety requirements on the external functions that combine the memory fence and system call, and then on the Rust side it's just a matter of upholding these requirements.
The next questions would then be: Is it OK to implement those two functions in (unsafe) Rust instead, and if yes, is fence
the correct mechanism for their implementation?
I believe the answer to the first question is yes, simply because naively translating a C function to unsafe Rust should yield a Rust function with the same semantics. But then I'd say that fence
is actually at the wrong abstraction level. As you observed, the docs don't really specify its semantics at the machine/OS level (unless you read it into the word "CPU" there). IMHO, what's really needed is something lower level that is guaranteed to interact with sendmsg
and recvmsg
in the correct way.
I guess it would have to be "whatever you would use in C there". Unfortunately it raises the question whether that is sufficiently well-defined.