From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46F94C02194 for ; Sun, 2 Feb 2025 13:06:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 0B2126B007B; Sun, 2 Feb 2025 08:06:44 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 062356B0085; Sun, 2 Feb 2025 08:06:44 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D82DF6B0089; Sun, 2 Feb 2025 08:06:43 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id A4D796B007B for ; Sun, 2 Feb 2025 08:06:43 -0500 (EST) Received: from smtpin05.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 1F14B1A20B2 for ; Sun, 2 Feb 2025 13:06:43 +0000 (UTC) X-FDA: 83075029086.05.6581D9B Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by imf18.hostedemail.com (Postfix) with ESMTP id D4FA51C000C for ; Sun, 2 Feb 2025 13:06:40 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=asahilina.net header.s=default header.b=a6FbgBjV; spf=pass (imf18.hostedemail.com: domain of lina@asahilina.net designates 212.63.210.85 as permitted sender) smtp.mailfrom=lina@asahilina.net; dmarc=pass (policy=quarantine) header.from=asahilina.net ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738501601; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=JCfjxk6jBLm4PuhXdtZUIC5jGtPufrSGA9FWY7XOt7o=; b=GTTPZoaYDhwg1nm8li0s9mveITek2Fx2GMbU08geYV7420yYJhMwXOwLOCg9X+6TBo+E9B JH0QVa2J43vuHMivfn8qD42/PeHSrrw8kR8Tkq4xDShHmFOj4KA2kJWN5U0PLILoewQSfM WvDyIYJV4FsVoOCaCbO3AN+IbigUp8c= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738501601; a=rsa-sha256; cv=none; b=MmtHPKkOMpynjOe21iTS1CUnsa45UuRp+dljcqUi6Wzi7IigCakSzqNlVblObHRymSLs6E QXBasWGcKgdvRyyOVgcVdhB9yUt1Y3YdfQ7qaQ85D4XK32yav0ADoLgg3ziCgzyP8dSyFw srPDwHtGyD7ii3NqRHSR8WYEKgGChY4= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=asahilina.net header.s=default header.b=a6FbgBjV; spf=pass (imf18.hostedemail.com: domain of lina@asahilina.net designates 212.63.210.85 as permitted sender) smtp.mailfrom=lina@asahilina.net; dmarc=pass (policy=quarantine) header.from=asahilina.net Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sendonly@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id C261F42601; Sun, 2 Feb 2025 13:06:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1738501598; bh=db+CTl7vXN85Dcw+hwBoMAovv2p9XLFk8QMb0+h2eUk=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=a6FbgBjVng3G981fDt43dF40MXlTw0rneaJMabBeyx+aIR56WSn59r40VougNzdn9 sAN00S22Hl9EimtHryyQ2WLebuOp1SFD1vHROBQQm6o5hLtff/bVxEfldzY26ZVKCs 90Iz6seFHpmJcG0RC9KmKpu9BAkJYuL4ZW+Ue+5w8gLxQ0berFYK9GcuremJ+f6LvT q8Kf9DMk8LmruH8sMGyzTRbNisX6FmMrS7gXSJFmY9l8H3XOCDyvP7fQDgR1XFX6jr Z+/7MUCQliMV8rJrfuUhi+igiiZ2uSyYJIZs8Cf6A0ZQqHkSnIj13WdS1w9EADuKLK I2PobK+BvOepA== From: Asahi Lina Date: Sun, 02 Feb 2025 22:05:43 +0900 Subject: [PATCH 1/6] rust: types: Add Ownable/Owned types MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20250202-rust-page-v1-1-e3170d7fe55e@asahilina.net> References: <20250202-rust-page-v1-0-e3170d7fe55e@asahilina.net> In-Reply-To: <20250202-rust-page-v1-0-e3170d7fe55e@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Jann Horn , Matthew Wilcox , Paolo Bonzini , Danilo Krummrich , Wedson Almeida Filho , Valentin Obst , Andrew Morton , linux-mm@kvack.org, airlied@redhat.com, Abdiel Janulgue , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1738501594; l=5188; i=lina@asahilina.net; s=20240902; h=from:subject:message-id; bh=db+CTl7vXN85Dcw+hwBoMAovv2p9XLFk8QMb0+h2eUk=; b=v4PEmnpGzrguSNB9PT6BnZr6+ea6iCaG0tCqNXz3t0LXfHn0sXubw18gYdI27epEwjEXxH8Ou PmgIcPGn+PiB7ALp4QLTfYWJgBI28JDbm3gcQoszN3vZbwEzEW2Tw8a X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=tpv7cWfUnHNw5jwf6h4t0gGgglt3/xcwlfs0+A/uUu8= X-Rspamd-Queue-Id: D4FA51C000C X-Stat-Signature: 9jf99f7opb79cnq3nshtitjkwqwr4nyb X-Rspam-User: X-Rspamd-Server: rspam12 X-HE-Tag: 1738501600-990688 X-HE-Meta: U2FsdGVkX19prK/zZweujjmGnJ86OeOxAtA6Id03eUzYa5f88+6aAFGvtGUnquLrFjckWdnU+dw7bHIHBwReAg1ehQX6epIum0ZGam2hvGHyHi5Q/AntF/Elai/B37lcgLAMfOBa+bAx2MVXWpljR5d6XBOG21UHqWZvVLkAlxUA2is+1lp6n0c6llIx1rN/5YNQJt5BEUk0RttZz1bxu/+alDoP+5APSiDTd3J/a1/C8FvayJ1y19WaEqVXPBG5slTUpeWNN9mpFRL7Lq7YRbpax0Yv32dORn97Cwklx1utFFkk5Y5vvx1xu81TCJeUUUI6Ostzt02B2AzTEe0WRlcEdP3ks12ElG4dtF9Me0g3Jn821oXmuudX2mnWULaIX14u5Wy/utJjAq1uCUOCK8FyNXebZJCg8Oz9bwayDDO0dPwIJtpHQZnmxqoGKcr1RKeMC+CBzZy80pCLYpkde+ElISFPBKTUjz6vAYQE9YTk6A4IVyU/keB9ve5rTSiD5mDbu9eqX3ZkhaWsjshYfssFEFMwLv4aYMsODuBzLfibp7Mo0eTg++hOlMtJco6wmAPmKyt+oZbvmJajFYOEKHGw/1Ww6uIqz5w4Q5GAnqkBvcqcWm9Y+PZCHaSSb3UUcA3KPgXeWsHE2hlswlkhLBhgp4KAAXLByT21x3CX06NHcSvyOIyppItXxvZJFdeZnI14dZSAvVL6axUFEnTYHbE0d0FKc5QrsnRz0ZCBuc+J9GMvsFHIgDRlgZiCd34hj4zwZnPOOMh8lWeXkb/ajunZA11kgNJ6hyyS2v2UmSrP0/JzEr674Gj3/6q2a6nA0kWfVacBLADfm20pR050rjwF85LnF8PSbajfjiIVfXQq3rJUWhdDCYIjBgXCp8Drh2zX/Y+8+Ix3+y5dNs2Dq6E1Bmdr0BGu6fsChqLGIRlA5n00drkHbau1u9mgtM+sQZRYi1o5lrG7IHfXvbx 1dSZM8nK Y43IlQWTggfIb+Mw/Z06UeXcAqUTywtm+q0lNM3XoQrWGIF/+KBGzDdPdNJfO3icpU9oggxA2peSoEPMdlQne6atZul+QiwPP/9BrDMYjjOrpxE5PM/0qgVyIQYxTvuUp3jqfBsndwVz3UNoqo4h4sl21Mkfjc2GhJKU6G8fiUIpqZsOApI6MAu5ePv3zn8f/xDbk/GbQ6RUpVA+PRXOZa50r9zq5paEtLe9Atq8K3UwfDwIWXPcxCNa5qfMyS7Xip6VLYXvfkDYtS3u85LlJRRwRlX0I9kaCNMJDKZvTWHtaOovqvHRBPfduKH3wBO2dlUeIF8SmFstpMeqhDvlYM6DgbZx5kmdBuEAJeBhpkPuAbHz1tnCcXwEQ7mKly01su9WISZTPZ9fwYMsy3aLY2sHim2QJo3+wN18mmufbbrttI8Q= X-Bogosity: Unsure, tests=bogofilter, spamicity=0.500000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: By analogy to AlwaysRefCounted and ARef, an Ownable type is a (typically C FFI) type that *may* be owned by Rust, but need not be. Unlike AlwaysRefCounted, this mechanism expects the reference to be unique within Rust, and does not allow cloning. Conceptually, this is similar to a KBox, except that it delegates resource management to the T instead of using a generic allocator. Signed-off-by: Asahi Lina --- rust/kernel/types.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index ec6457bb3084ae327c38ba4ba79b1601aef38244..0bee56153dcea47fb1321162df6b8765b5436e9f 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -479,6 +479,116 @@ fn drop(&mut self) { } } +/// Types that may be owned by Rust code or borrowed, but have a lifetime managed by C code. +/// +/// It allows such types to define their own custom destructor function to be called when +/// a Rust-owned reference is dropped. +/// +/// This is usually implemented by wrappers to existing structures on the C side of the code. +/// +/// # Safety +/// +/// Implementers must ensure that any objects borrowed directly as `&T` stay alive for the duration +/// of the lifetime, and that any objects owned by Rust as `Owned`) stay alive while that owned +/// reference exists, until the [`Ownable::release()`] trait method is called. +pub unsafe trait Ownable { + /// Releases the object (frees it or returns it to foreign ownership). + /// + /// # Safety + /// + /// Callers must ensure that the object is no longer referenced after this call. + unsafe fn release(this: NonNull); +} + +/// A subtrait of Ownable that asserts that an `Owned` Rust reference is not only unique +/// within Rust and keeps the `T` alive, but also guarantees that the C code follows the +/// usual mutable reference requirements. That is, the kernel will never mutate the +/// `T` (excluding internal mutability that follows the usual rules) while Rust owns it. +/// +/// When this type is implemented for an [`Ownable`] type, it allows `Owned` to be +/// dereferenced into a &mut T. +/// +/// # Safety +/// +/// Implementers must ensure that the kernel never mutates the underlying type while +/// Rust owns it. +pub unsafe trait OwnableMut: Ownable {} + +/// An owned reference to an ownable kernel object. +/// +/// The object is automatically freed or released when an instance of [`Owned`] is +/// dropped. +/// +/// # Invariants +/// +/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`Owned`] instance. +pub struct Owned { + ptr: NonNull, + _p: PhantomData, +} + +// SAFETY: It is safe to send `Owned` to another thread when the underlying `T` is `Send` because +// it effectively means sending a unique `&mut T` pointer (which is safe because `T` is `Send`). +unsafe impl Send for Owned {} + +// SAFETY: It is safe to send `&Owned` to another thread when the underlying `T` is `Sync` +// because it effectively means sharing `&T` (which is safe because `T` is `Sync`). +unsafe impl Sync for Owned {} + +impl Owned { + /// Creates a new instance of [`Owned`]. + /// + /// It takes over ownership of the underlying object. + /// + /// # Safety + /// + /// Callers must ensure that the underlying object is acquired and can be considered owned by + /// Rust. + pub(crate) unsafe fn from_raw(ptr: NonNull) -> Self { + // INVARIANT: The safety requirements guarantee that the new instance now owns the + // reference. + Self { + ptr, + _p: PhantomData, + } + } + + /// Consumes the `Owned`, returning a raw pointer. + /// + /// This function does not actually relinquish ownership of the object. + /// After calling this function, the caller is responsible for ownership previously managed + /// by the `Owned`. + #[allow(dead_code)] + pub(crate) fn into_raw(me: Self) -> NonNull { + ManuallyDrop::new(me).ptr + } +} + +impl Deref for Owned { + type Target = T; + + fn deref(&self) -> &Self::Target { + // SAFETY: The type invariants guarantee that the object is valid. + unsafe { self.ptr.as_ref() } + } +} + +impl DerefMut for Owned { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: The type invariants guarantee that the object is valid, + // and that we can safely return a mutable reference to it. + unsafe { self.ptr.as_mut() } + } +} + +impl Drop for Owned { + fn drop(&mut self) { + // SAFETY: The type invariants guarantee that the `Owned` owns the object we're about to + // release. + unsafe { T::release(self.ptr) }; + } +} + /// A sum type that always holds either a value of type `L` or `R`. /// /// # Examples -- 2.47.1