From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-40134.protonmail.ch (mail-40134.protonmail.ch [185.70.40.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 58124248872 for ; Mon, 24 Feb 2025 12:47:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.40.134 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740401269; cv=none; b=c+6HL0zLKxph6CzjKpQsPg7vw5im8nT2mOSldxHeFGzlXtngtjRFTakPVzXdcFi1hi7FoeNrPSeQZtZ8MbWMcpWQc0h4br0tgFgrQb4Hw7MFwDY4w+eKxiymQQCwrUtuctz3C4IjOBMqzuLdWsUgZJpoB7F8HUa+kJKtKTHNB9k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740401269; c=relaxed/simple; bh=oZ2dWmyU4A//0DoserIi+hU6J9FipYEUap9axJniyx4=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=a98WAPL/F4m83xNIOdUcRWjeD/2AION7mIevYXsRDGzqtklcYY9ACdLM9oGcqq9htWKsuCRHeicRpBTAMwUESmtem/E7bY3cRaKWbzPmNtRF9PAiCmvVd7hE/ooybKfoaJdwxooOK3EudM7KbVEAFvg9woiUxEPyxM4s8DArJCE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me; spf=pass smtp.mailfrom=proton.me; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b=exZNX6Mr; arc=none smtp.client-ip=185.70.40.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=proton.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b="exZNX6Mr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=vldkxvxq5bgy3elbypmorpcpye.protonmail; t=1740401258; x=1740660458; bh=izzT/+0Q8SQxJzAfO8adqcn2Lgu3MSr0pO4y4sFm3ys=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=exZNX6MrZub/mnUGj6o/6Nq69vx7GgeC3TMGUDibQyxTc6nuKWYxmtWTgWtIqdz4P p9TNIP8ChSbMuwMPCJQRcSmqPfSA0gks98iBMQp1h+xxVwQ2WnBb7C37lU+yKtlCW2 3cwVRumVstGDepJO95gozF3Z8OmF6OiIPtC+KmuuY75kX/iEACUxq8YJOQYC+quvgA /Dk8YKV7zUfCWxscoTHsGsaS/D13XHqSDz/xCKh09ey2nIp3a2ztkAtZJm4VRFm5Yn GrRLe5Di82lZOkNmPc4IBHjCbY7PYQa43jQ3b+p1v5XblsmgtJvDtcG647c+cqJifi udNoy5YMQhmfA== Date: Mon, 24 Feb 2025 12:47:32 +0000 To: Ventura Jack From: Benno Lossin Cc: Gary Guo , Linus Torvalds , Kent Overstreet , airlied@gmail.com, boqun.feng@gmail.com, david.laight.linux@gmail.com, ej@inai.de, gregkh@linuxfoundation.org, hch@infradead.org, hpa@zytor.com, ksummit@lists.linux.dev, linux-kernel@vger.kernel.org, miguel.ojeda.sandonis@gmail.com, rust-for-linux@vger.kernel.org Subject: Re: C aggregate passing (Rust kernel policy) Message-ID: In-Reply-To: References: <20250222141521.1fe24871@eugeo> <6pwjvkejyw2wjxobu6ffeyolkk2fppuuvyrzqpigchqzhclnhm@v5zhfpmirk2c> <20250224002745.7d7460a7.gary@garyguo.net> <4cb1d98b-f94b-410a-be90-4394c48bdbf2@proton.me> Feedback-ID: 71780778:user:proton X-Pm-Message-ID: 5e36dc550687cf705f54d72a0b677ac4439eb912 Precedence: bulk X-Mailing-List: ksummit@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 24.02.25 13:21, Ventura Jack wrote: > On Mon, Feb 24, 2025 at 3:31=E2=80=AFAM Benno Lossin wrote: >> >> On 24.02.25 10:57, Ventura Jack wrote: >>> >>> In regards to `UnsafeCell`, I believe that you are correct in regards >>> to mutability. However, if I understand you correctly, and if I >>> am not mistaken, I believe that you are wrong about `UnsafeCell` >>> making it possible to opt-out of the aliasing rules. And thus that >>> `UnsafeCell` does not behave like `T*` in C. >> >> `UnsafeCell` does not behave like `T*` in C, because it isn't a >> pointer. Like Gary said, `&UnsafeCell` behaves like `T*` in C, while >> `&mut UnsafeCell` does not. That is what you quote from the docs >> below. (Those ampersands mark references in Rust, pointers that have >> additional guarantees [1]) >=20 > From what I can see in the documentation, `&UnsafeCell` also does not > behave like `T*` in C. In C, especially if "strict aliasing" is turned > off in the > compiler, `T*` does not have aliasing requirements. You can have multiple > C `T*` pointers pointing to the same object, and mutate the same object. This is true for `&UnsafeCell`. You can have multiple of those and mutate the same value via only shared references. Note that `UnsafeCell` is `!Sync`, so it cannot be shared across threads, so all of those shared references have to be on the same thread. (there is the `SyncUnsafeCell` type that is `Sync`, so it does allow for across-thread mutations, but that is much more of a footgun, since you still have to synchronize the writes/reads) > The documentation for `UnsafeCell` conversely spends a lot of space > discussing invariants and aliasing requirements. Yes, since normally in Rust, you can either have exactly one mutable reference, or several shared references (which cannot be used to mutate a value). `UnsafeCell` is essentially a low-level primitive that can only be used with `unsafe` to build for example a mutex. > I do not understand why you claim: >=20 > "`&UnsafeCell` behaves like `T*` in C," >=20 > That statement is false as far as I can figure out, though I have taken i= t > out of context here. Not sure how you arrived at that conclusion, the following code is legal and sound Rust: let val =3D UnsafeCell::new(42); let x =3D &val; let y =3D &val; unsafe { *x.get() =3D 0; *y.get() =3D 42; *x.get() =3D 24; } You can't do this with `&mut i32`. > Is the argument in regards to mutability? But `T*` in C > allows mutability. If you looked at C++ instead of C, maybe a `const` > pointer would be closer in semantics and behavior. >=20 >> below. (Those ampersands mark references in Rust, pointers that have >> additional guarantees [1]) >> >> [omitted] >> >> [1]: https://doc.rust-lang.org/std/primitive.reference.html >=20 > There is also https://doc.rust-lang.org/reference/types/pointer.html . Yes that is the description of all primitive pointer types. Both references and raw pointers. > But, references must follow certain aliasing rules, and in unsafe Rust, > it is the programmer that has the burden of upholding those aliasing rule= s, > right? Indeed. >> For disabling the uniqueness guarantee for `&mut`, we use an official >> "hack" that the Rust language developers are working on replacing with >> a better mechanism (this was also mentioned by Gary above). >=20 > Are you referring to `Opaque`? I am referring to the hack used by `Opaque`, it is `!Unpin` which results in `&mut Opaque` not having the `noalias` attribute. >>> Documentation and related links for `Opaque`: >>> https://rust.docs.kernel.org/kernel/types/struct.Opaque.html >>> https://rust.docs.kernel.org/src/kernel/types.rs.html#307-310 >>> https://github.com/Rust-for-Linux/pinned-init >>> >>> It uses `UnsafeCell`, Rust "pinning", and the Rust for Linux library >>> "pinned-init". >> >> pinned-init is not specific to `Opaque` and not really relevant with >> respect to discussing aliasing guarantees. >=20 > Is `Opaque` really able to avoid aliasing requirements for users, > without internally using "pinned-init"/derivative or the pinning > feature used in its implementation? Yes, you can write `Opaque` without using pinned-init. The hack described above uses `PhantomPinned` to make `Opaque: !Unpin`. >>> "pinned-init" uses a number of experimental, unstable and nightly >>> features of Rust. >> >> This is wrong. It uses no unstable features when you look at the version >> in-tree (at `rust/kernel/init.rs`). The user-space version uses a single >> unstable feature: `allocator_api` for accessing the `AllocError` type >> from the standard library. You can disable the `alloc` feature and use >> it on a stable compiler as written in the readme. >=20 > Interesting, I did not realize that the Rust for Linux project uses > a fork or derivative of "pinned-init" in-tree, not "pinned-init" itself. Yes, that is something that I am working on at the moment. > What I can read in the README.md: > https://github.com/Rust-for-Linux/pinned-init/tree/main >=20 > "Nightly Needed for alloc feature >=20 > This library requires the allocator_api unstable feature > when the alloc feature is enabled and thus this feature > can only be used with a nightly compiler. When enabling > the alloc feature, the user will be required to activate > allocator_api as well. >=20 > The feature is enabled by default, thus by default > pinned-init will require a nightly compiler. However, using > the crate on stable compilers is possible by disabling alloc. > In practice this will require the std feature, because stable > compilers have neither Box nor Arc in no-std mode." >=20 > Rust in Linux uses no_std, right? So Rust in Linux would not be > able to use the original "pinned_init" library as it currently is without > using currently nightly/unstable features, until the relevant feature(s) > is stabilized. Yes, Rust for Linux uses `#![no_std]` (and also has its own alloc), so it an use the stable version of pinned-init. However, there are several differences between the current in-tree version and the user-space version. I am working on some patches that fix that. >>> Working with the library implementation requires having a good >>> understanding of unsafe Rust and many advanced features of Rust. >> >> pinned-init was explicitly designed such that you *don't* have to write >> unsafe code for initializing structures that require pinning from the >> get-go (such as the kernel's mutex). >=20 > Sorry, I sought to convey that I was referring to the internal library > implementation, not the usage of the library. Ah I see. > For the library implementation, do you agree that a good > understanding of unsafe Rust and many advanced features > are required to work with the library implementation? Such as > pinning? Yes I agree. --- Cheers, Benno >>> `Opaque` looks interesting. Do you know if it will become a more >>> widely used abstraction outside the Linux kernel? >> >> Only in projects that do FFI with C/C++ (or other such languages). >> Outside of that the `Opaque` type is rather useless, since it disables >> normal guarantees and makes working with the inner type annoying. >=20 > Interesting. >=20 > Best, VJ.