Can I implement seqlocks safely in rust?

Hans-J. Boehm described in Can Seqlocks Get Along With Programming Language Memory Models? some ways to implement the "seqlock" in Linux kernel within the C++ memory model safely. Because the core idea of the algorithm is to let it race, and check whether a race really happened, so naively copying the object is obviously UB, and the author proposes to replace naive objects with a few atomic variables. In C++ this is not a problem at all, because the standard explicitly allows reinterpreting any trivially_copyable objects as bytes, and copy the bytes around and cast back to the original type, so with a few templates I can copy any POD in atomic steps. But I found no such "backdoors" mentioned in rust; can I assume the same operation is also safe in rust, or I must explicitly code the protected object in many atomic objects?

1 Like

Here's a simple way of doing it:

struct SeqLock<T: Copy> {
    counter: AtomicU64,
    value: UnsafeCell<MaybeUninit<T>>,

MaybeUninit allows us to directly manipulate the bytes of value without causing undefined behavior. It's on the writer to make sure that they prove that T is valid when they extract it.

E: see @quinedot's reply regarding races - sadly, I think calling ptr::read and ptr::write at the same time is undefined behavior. I don't think read_volatile gets you out of this either.

Races in Rust's model are UB.

Yeah, and it's also UB in C++, so the original object is replaced with one or more atomic objects --- but C++ offers a way to manually copying the underlying bytes, whereas rust does not (if I'm not mistaken).

Rust has bytemuck crate to mark types as "POD" with no padding. With this you could safely copy bytes in and out of a bunch of AtomicUsize instances.


You might be interested in this RFC.


Ah, repr(rust) support is definitely better than bytemuck, if it is to be accepted...

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.