From nobody Sun Feb 8 04:33:36 2026 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D5472253EF for ; Sat, 17 Jan 2026 15:25:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768663531; cv=none; b=Q2WQPR7KKH2J9bLSqR1PaX4sjCg/q+5AJHpA+YKhT7HzZiw12ysFoMhtO9Fu7gIOuwqV3CMbU6I0bFppolAWIydvRVfeXDsQVMN7Bhd+xhh3R2cl/Vl0/g+cAC6OkW1W5IzyilQCKcMiQge+Q/fl4j+Lty9cbTN/KvsuXYQ2z4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768663531; c=relaxed/simple; bh=AwcTgsthYx0aIP7jt5SIJ3bUXr4UAdp7zAjyr7QxFZ0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=IVkslOA5M7u+xmprcDQKxNYBWp/zlASPNpdG/AkWR3O8Y2VzORD0jWp+KC1gvowSjz/hts3NgB6x7unsSEv8rDjAPrKvZ5un074cpfHzcVJWPShyLYYF75HuIsObJ1eOVv+SQNzoyx0UP8GsElobiT7JY+oNVJwuPMhHHMnLohw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=F56Gdrlp; arc=none smtp.client-ip=209.85.218.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="F56Gdrlp" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-b871328f6caso296505566b.3 for ; Sat, 17 Jan 2026 07:25:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768663528; x=1769268328; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=1KycL/RP2UnaKXzhbUKxpWD/C+4095bTNRjfo4uJ3+8=; b=F56GdrlpxuUB/auXAfmP7EsDw7xrLZnPO91f2sIqfPjmRS26O8CoUCac/oslVgG3h4 udbO+tUKWexgT7dOfuKfctSE4TFaI+fSaq36u0QZ8GwJexwzE95/1zMRpaAzXVoLOiM+ aT1nWDWbEOn21Qb22wR62RQA5da0hP8/oeveo3B5FjJH2I75g3jtQ5YcON+TEM/ytZah 0qq+iMwa4bMIu3Ht1Ysr4norxspnBYHKo2x6J3dQzGytbFIXTlh+sE509n0ssdbR/ro4 SyKTlFT4+HSpiCX+uiMHmvrE9OtsMDcSGgwwmsycN8Ix4BOG59WAIceIVug8aIjSjaVY msaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768663528; x=1769268328; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1KycL/RP2UnaKXzhbUKxpWD/C+4095bTNRjfo4uJ3+8=; b=biiBvIhTSZNtuJvQscbARr3eqIEzSn/pclPGN9s3NqpFihTTcE+LRFcMnQbpFaEX0K a9+iRppizGjtw8eqtkaPBRhTgqOG4+z8xNBN/FHh/JBvRyXgzmnrj0BCpD0P9Ss7mKI7 TE7oJ5lhw/LZh6ajxYgb/1F/hfLOSf9PovBAamYGot0MRexpOaLqG3+inUReA0P2mDDY F+5F1LFaIdX9d7G+/L9kJ3Fiut0xCKXpVHVTQgDsR5Qt+//u68xLAm9ByEOrvJEhv/nF kp5SthOABDgh16W34YcPhcMpwZ9Mv/1JKi7KmiuDN/LB1FaD792sB/XhlzPrIHxz+xR5 xYrQ== X-Forwarded-Encrypted: i=1; AJvYcCU4IkZgy1DsIthwd5fSp41BtIIk3dsvQWr8xNjFSSbp8IRBT1rMtJFG8VpSD7yfixBD7/FG64OquI0j52A=@vger.kernel.org X-Gm-Message-State: AOJu0Yyq1dhUa1DS+fo9B/S75gGxcz09SvQKI2ooED6GtABNtcumarsG 76BrccOFyDgy5WglOoqYJjfDhAV3BlX4xIHHPk5jUStypHWwZf42gnHlPYVCILbow/IAKy/wRPh mpLPUhTzRh12+uc0CNg== X-Received: from edcx10.prod.google.com ([2002:a05:6402:a14a:b0:653:500:d80c]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:f509:b0:b87:298a:da9c with SMTP id a640c23a62f3a-b8792d489bbmr511146466b.6.1768663527693; Sat, 17 Jan 2026 07:25:27 -0800 (PST) Date: Sat, 17 Jan 2026 15:25:19 +0000 In-Reply-To: <20260117-upgrade-poll-v1-0-179437b7bd49@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260117-upgrade-poll-v1-0-179437b7bd49@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7824; i=aliceryhl@google.com; h=from:subject:message-id; bh=AwcTgsthYx0aIP7jt5SIJ3bUXr4UAdp7zAjyr7QxFZ0=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBpa6nlCM1RLO25hi+Og3yrpuOfBAdPBOgDOkh3H HgeQMgPA5yJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCaWup5QAKCRAEWL7uWMY5 RlSaD/4zqoJE1iw3f4OcubEFoTGU2vMN/zsSzBI+dNBvE1ntVBKRwEwMq7stU0/ughVEWlLH5mW qlv7W73hhqJWw9BIs6FxYiblu2NvI9rAO/v5S8d18fZM7YJdV4VHwq6vDNB9cMHF+UEHkZ8Ie97 hKi5M5SS41ORKk7mcdLErsjpiY9wOfwVyLnSN7ERMvSXnMfWsHA8yBwdJwLMqqkJvqi5UWHQhAX 8FZ7w6UaJ1XCAc9SMrnjzwYfArxWuMHQQ32/E2y05+dWk8KdWWICyUAC0JnOUcvcnrG9Qxwdpcl 8pLH4hlU86XEKdzVCAptr13OlMyxcdJ+t10quV8r7MzUXdRMVpK6mPHOjpyFrB4jUi0l7NQ2haZ 9zM5RdnuvdbUSJMnEKuO53nsUnQZKWq0aH1qKznRzL7nhM+fMW/RgIgVspSMeNxvZf5bfP+QjVv NILjfBp68cKuRtgSeLqG71VpE8GTcpccMjiENcnwHi0VO24FjzWicDQdEM80BOKa5Mjwz1dKGOA IRs6qEHGHnN+zXFYWOdJ19er9Y5cPnF8LXBAwSu7u+yypUD74tgqMCrMfpKSo5J06upLxg/laVU YFK2gkeYlJodG3JiQ0R0ShGNcPK6nW7Xa1Yi9NMHk7QOFhFvQhWaDQBxTTCmkLYNp5Im+gtdMlb OyFamKZWCrF84Qg== X-Mailer: b4 0.14.2 Message-ID: <20260117-upgrade-poll-v1-1-179437b7bd49@google.com> Subject: [PATCH RFC 1/2] rust: poll: make PollCondVar upgradable From: Alice Ryhl To: Christian Brauner , Boqun Feng , "Paul E. McKenney" Cc: Gary Guo , Greg Kroah-Hartman , Carlos Llamas , linux-fsdevel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Signed-off-by: Alice Ryhl --- rust/kernel/sync/poll.rs | 163 +++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 161 insertions(+), 2 deletions(-) diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs index 0ec985d560c8d3405c08dbd86e48b14c7c34484d..9fb004c71c78375bb16ded7f518= aa282cdcc50f5 100644 --- a/rust/kernel/sync/poll.rs +++ b/rust/kernel/sync/poll.rs @@ -5,12 +5,16 @@ //! Utilities for working with `struct poll_table`. =20 use crate::{ - bindings, + alloc::AllocError, + bindings, container_of, fs::File, prelude::*, + sync::atomic::{Acquire, Atomic, Relaxed, Release}, + sync::lock::{Backend, Lock}, sync::{CondVar, LockClassKey}, + types::Opaque, }; -use core::{marker::PhantomData, ops::Deref}; +use core::{marker::PhantomData, ops::Deref, ptr}; =20 /// Creates a [`PollCondVar`] initialiser with the given name and a newly-= created lock class. #[macro_export] @@ -22,6 +26,17 @@ macro_rules! new_poll_condvar { }; } =20 +/// Creates a [`UpgradePollCondVar`] initialiser with the given name and a= newly-created lock +/// class. +#[macro_export] +macro_rules! new_upgrade_poll_condvar { + ($($name:literal)?) =3D> { + $crate::sync::poll::UpgradePollCondVar::new( + $crate::optional_name!($($name)?), $crate::static_lock_class!() + ) + }; +} + /// Wraps the kernel's `poll_table`. /// /// # Invariants @@ -66,6 +81,7 @@ pub fn register_wait(&self, file: &File, cv: &PollCondVar= ) { /// /// [`CondVar`]: crate::sync::CondVar #[pin_data(PinnedDrop)] +#[repr(transparent)] pub struct PollCondVar { #[pin] inner: CondVar, @@ -78,6 +94,17 @@ pub fn new(name: &'static CStr, key: Pin<&'static LockCl= assKey>) -> impl PinInit inner <- CondVar::new(name, key), }) } + + /// Use this `CondVar` as a `PollCondVar`. + /// + /// # Safety + /// + /// After the last use of the returned `&PollCondVar`, `__wake_up_poll= free` must be called on + /// the `wait_queue_head` at least one grace period before the `CondVa= r` is destroyed. + unsafe fn from_non_poll(c: &CondVar) -> &PollCondVar { + // SAFETY: Layout is the same. Caller ensures that PollTables are = cleared in time. + unsafe { &*ptr::from_ref(c).cast() } + } } =20 // Make the `CondVar` methods callable on `PollCondVar`. @@ -104,3 +131,135 @@ fn drop(self: Pin<&mut Self>) { unsafe { bindings::synchronize_rcu() }; } } + +/// Wrapper around [`CondVar`] that can be upgraded to [`PollCondVar`]. +/// +/// By using this wrapper, you can avoid rcu for cases that don't use [`Po= llTable`], and in all +/// cases you can avoid `synchronize_rcu()`. +/// +/// # Invariants +/// +/// `active` either references `simple`, or a `kmalloc` allocation holding= an +/// `UpgradePollCondVarInner`. In the latter case, the allocation remains = valid until +/// `Self::drop()` plus one grace period. +#[pin_data(PinnedDrop)] +pub struct UpgradePollCondVar { + #[pin] + simple: CondVar, + active: Atomic<*mut CondVar>, +} + +#[pin_data] +#[repr(C)] +struct UpgradePollCondVarInner { + #[pin] + upgraded: CondVar, + #[pin] + rcu: Opaque, +} + +impl UpgradePollCondVar { + /// Constructs a new upgradable condvar initialiser. + pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> im= pl PinInit { + pin_init!(&this in Self { + simple <- CondVar::new(name, key), + // SAFETY: `this->inner` is in-bounds. + active: Atomic::new((unsafe { &raw const (*this.as_ptr()).simp= le }).cast_mut()), + }) + } + + /// Obtain a [`PollCondVar`], upgrading if necessary. + /// + /// You should use the same lock as what is passed to the `wait_*` met= hods. Otherwise wakeups + /// may be missed. + pub fn poll( + &self, + lock: &Lock, + name: &'static CStr, + key: Pin<&'static LockClassKey>, + ) -> Result<&PollCondVar, AllocError> { + let mut ptr =3D self.active.load(Acquire).cast_const(); + if ptr::eq(ptr, &self.simple) { + self.upgrade(lock, name, key)?; + ptr =3D self.active.load(Acquire).cast_const(); + debug_assert_ne!(ptr, ptr::from_ref(&self.simple)); + } + // SAFETY: Signature ensures that last use of returned `&PollCondV= ar` is before drop(), and + // drop() calls `__wake_up_pollfree` followed by waiting a grace p= eriod before the + // `CondVar` is destroyed. + Ok(unsafe { PollCondVar::from_non_poll(&*ptr) }) + } + + fn upgrade( + &self, + lock: &Lock, + name: &'static CStr, + key: Pin<&'static LockClassKey>, + ) -> Result<(), AllocError> { + let upgraded =3D KBox::pin_init( + pin_init!(UpgradePollCondVarInner { + upgraded <- CondVar::new(name, key), + rcu: Opaque::uninit(), + }), + GFP_KERNEL, + ) + .map_err(|_| AllocError)?; + + // SAFETY: The value is treated as pinned. + let upgraded =3D KBox::into_raw(unsafe { Pin::into_inner_unchecked= (upgraded) }); + + let res =3D self.active.cmpxchg( + ptr::from_ref(&self.simple).cast_mut(), + // SAFETY: This operation stays in-bounds of the above allocat= ion. + unsafe { &raw mut (*upgraded).upgraded }, + Release, + ); + + if res.is_err() { + // SAFETY: The cmpxchg failed, so take back ownership of the b= ox. + drop(unsafe { KBox::from_raw(upgraded) }); + return Ok(()); + } + + // If a normal waiter registers in parallel with us, then either: + // * We took the lock first. In that case, the waiter sees the abo= ve cmpxchg. + // * They took the lock first. In that case, we wake them up below. + drop(lock.lock()); + self.simple.notify_all(); + + Ok(()) + } +} + +// Make the `CondVar` methods callable on `UpgradePollCondVar`. +impl Deref for UpgradePollCondVar { + type Target =3D CondVar; + + fn deref(&self) -> &CondVar { + // SAFETY: By the type invariants, this is either `&self.simple` o= r references an + // allocation that lives until `UpgradePollCondVar::drop`. + unsafe { &*self.active.load(Acquire) } + } +} + +#[pinned_drop] +impl PinnedDrop for UpgradePollCondVar { + #[inline] + fn drop(self: Pin<&mut Self>) { + // ORDERING: All calls to upgrade happens-before Drop, so no synch= ronization is required. + let ptr =3D self.active.load(Relaxed); + if ptr::eq(ptr, &self.simple) { + return; + } + // SAFETY: When the pointer is not &self.active, it is an `Upgrade= PollCondVarInner`. + let ptr =3D unsafe { container_of!(ptr, UpgradePollCondVarInner, u= pgraded) }; + // SAFETY: The pointer points at a valid `wait_queue_head`. + unsafe { bindings::__wake_up_pollfree((*ptr).upgraded.wait_queue_h= ead.get()) }; + // This skips drop of `CondVar`, but that's ok because we reimplem= ented its drop here. + // + // SAFETY: `__wake_up_pollfree` ensures that all registered PollTa= ble instances are gone in + // one grace period, and this is the destructor so no new PollTabl= e instances can be + // registered. Thus, it's safety to rcu free the `UpgradePollCondV= arInner`. + unsafe { bindings::kvfree_call_rcu((*ptr).rcu.get(), ptr.cast::()) }; + } +} --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 04:33:36 2026 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E93E2367D3 for ; Sat, 17 Jan 2026 15:25:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768663534; cv=none; b=EcX5bbj0iDKEk2iPRW0sOPcidC38jBwhoADfq7XKUXf8M/J17XplXK73C0YmGV6zbRCqJzP9qJa4/sidufw7K+ua9bOAQum1FeTF5kOU4a0UzVkbHQMDhniyva3PUF2doAukmwQSygcJMX6uiE6uzjBIMhcX4QONtwdLnrwrND4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768663534; c=relaxed/simple; bh=9ipAyLskKwi1ksx9hkkM2iyTNIPdZ0fYz79QhCj4ffA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ahaULdCtHx0gi3PYOdFV9K6IK1HLQWD0Y1X6KJetrCkUL88baUn1ZpMG0MVyVbEABtRdP7bjY0GPk+BsfKWJsCcYakZzIdaBezKJyMWeM7VmGbvbDXueri+AdaznlJPxsAoVp0FeG1iVywqQUYxWQP8fBRCkUUSokG3s/Hp3WSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=w0zaPWxa; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="w0zaPWxa" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-4801da6f5c9so25084085e9.1 for ; Sat, 17 Jan 2026 07:25:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768663530; x=1769268330; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KqqLu+rK83FYvuu43UqacZgGarS1nyPWiHaErFCcx+s=; b=w0zaPWxac3n44oJeA2yYz1htROIZE7YRtAhUA3iMpqpD3spou6UQkDfZ9D1Z60Xunb t701e3bTfAsypHwmmhCIiZ50wTlGC2ATfm5ZP2f1snD0NsexfT0Zt2/9EDYnEuHm+D8Q 0VPSoEcBalbdCSCgFojMfBWvYIhWewyjiXvzT/nDQDQx2mz1PkNgSqPdN8A0Vzd/oir6 ROBx/Npis/R4NvmqSwD88+qMe67DOcXz9He8mlsYQy3g45scwZ1DP2MeUNeefpc0LLID 34J3UsjwJ3fO0oPwhxAiwpMae3t++3rE5PnFYGxLYTmo/7n6BRq8DFcu5pp6wDu34JZn 90sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768663530; x=1769268330; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KqqLu+rK83FYvuu43UqacZgGarS1nyPWiHaErFCcx+s=; b=NnZaQnTkL4HafVrMjAVLC0HmLGt8W4LaEQwR4c4odwEjPFMhqDMiXYnrXOU2FApRJg KQsYjY0CHISMN/xBFOwS9o0MZY218q5Cw7nwMiucRV3O+BChobXQGesdv5gu3Yb2v9+t Sim+fz7hJGEWjLNkdmOx5KJqRDlYa//n2wrrqwRYa3AOMNFE2ZlruIuxpyU63eKS0lr6 LOcAoChcTcb5xfMisOXlCNg/lOOSJ4VuuBCQJQfp7Ui92sTLKbKkXfBSspFmzeuQByYW eOk3EwkYY/1evI7Zq8Kg0xs1pCAS8gRxmPHavV2HYb6vhTHammV2zP/qDQkERlnoxavt 5rcw== X-Forwarded-Encrypted: i=1; AJvYcCWAwmAfLicADJ0O4fHTI6gxtKQA19jXbPYXljAQqxWl5qwqyRDjj2gEm9fWZ3kWchUme0pLrsXA8utL9ZU=@vger.kernel.org X-Gm-Message-State: AOJu0YwZrghWu41KmXHfdcSp175AgMi2aoXnUlF/7oLLp/zqj06I985e IKaGoVfQ6ZAmaEzp4sjwufBgdUVPPmwHhe/Ov/oI2fX7P431DFKer5aiiFdvBot9Bk7XDFBK08e /2xwCxqF78GeYQZfFKw== X-Received: from wmhm8.prod.google.com ([2002:a05:600c:40c8:b0:477:7893:c737]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4e0f:b0:47e:e779:36e with SMTP id 5b1f17b1804b1-4801eb0375amr70230175e9.19.1768663529817; Sat, 17 Jan 2026 07:25:29 -0800 (PST) Date: Sat, 17 Jan 2026 15:25:20 +0000 In-Reply-To: <20260117-upgrade-poll-v1-0-179437b7bd49@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260117-upgrade-poll-v1-0-179437b7bd49@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3796; i=aliceryhl@google.com; h=from:subject:message-id; bh=9ipAyLskKwi1ksx9hkkM2iyTNIPdZ0fYz79QhCj4ffA=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBpa6nlFxHRFC9Er4fNiBw9GYpYeu3Uu4ieGDJeI wo6v3Mb5H6JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCaWup5QAKCRAEWL7uWMY5 RtG8EACdXCwXlePrBnRXKgNEHXkdYMvJULH49b5iki2wcp8iujIwa+FEoFXm1Y69eN5UCCZtcQH zylpEINsHKVe4/to8zHNwCmm5tLMwDeEWjNTv2t2g9W5UXD4Zw/F9RrerMh4va+TshAnCJGLJXu 04229CYQkUTlNmMwREG+u9/+6hcT1fMQgYSijDpVy1gdhpBb1PPyCgcx7AmiYkX+V/4JihValTI hU8iO7IyLpKIlH6kuT2gRS9bCG4At0CSusPaMiH45agzSNWx+3HWRp9PtxcbjsQXOxXQ7Z7DsWf CUGEAxYfVXI6OTKm3Nz9IzdyZtkrxqjT+KyHKNCbH1VAKXqrp9kaJAYbmgMSkkEkOZGAYBiVCTu +K8UtmVC9olOfl/EDZNYg9PLy13SnSorCw6hO5i610hJVHp6kllzrwdbjfV25/P+hjP3K8oNRAw rGMIGCeT1h1wmNC5ddkhoe6q+jH+CVhkaBQDuI6R6XSg6VgtTkx+Psi8L78z5mR7h8iM5j3EY4Z jrhvuVEHQJKj1FaVH5+oMhINwBUn092wKAxAk4S6RPiL1yH+saaVfT05jl72QSYKxV5AfMNVvwD exsQTHgSAT1OQyHjhwsRtP+bE/AJHnT4On9+oN0IeJdPXLy4I4TuuYgCegpoj/IEYnvGYMHEQyb 0ULwk+2ADGWOyqw== X-Mailer: b4 0.14.2 Message-ID: <20260117-upgrade-poll-v1-2-179437b7bd49@google.com> Subject: [PATCH RFC 2/2] rust_binder: use UpgradePollCondVar From: Alice Ryhl To: Christian Brauner , Boqun Feng , "Paul E. McKenney" Cc: Gary Guo , Greg Kroah-Hartman , Carlos Llamas , linux-fsdevel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alice Ryhl Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Most processes do not use Rust Binder with epoll, so avoid paying the synchronize_rcu() cost in drop for those that don't need it. For those that do, we also manage to replace synchronize_rcu() with kfree_rcu(), though we introduce an extra allocation. Signed-off-by: Alice Ryhl --- drivers/android/binder/process.rs | 2 +- drivers/android/binder/thread.rs | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/pro= cess.rs index 132055b4790f0ec69a87635b498909df2bf475e2..9374f1a86766c09321b57e565b6= 317cc290ea32b 100644 --- a/drivers/android/binder/process.rs +++ b/drivers/android/binder/process.rs @@ -1684,7 +1684,7 @@ pub(crate) fn poll( table: PollTable<'_>, ) -> Result { let thread =3D this.get_current_thread()?; - let (from_proc, mut mask) =3D thread.poll(file, table); + let (from_proc, mut mask) =3D thread.poll(file, table)?; if mask =3D=3D 0 && from_proc && !this.inner.lock().work.is_empty(= ) { mask |=3D bindings::POLLIN; } diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thre= ad.rs index 82264db06507d4641b60cbed96af482a9d36e7b2..8f09cf1599ae7edcf2ee60b2cb1= b08cc2d0afd3f 100644 --- a/drivers/android/binder/thread.rs +++ b/drivers/android/binder/thread.rs @@ -16,7 +16,7 @@ seq_file::SeqFile, seq_print, sync::atomic::{ordering::Relaxed, Atomic}, - sync::poll::{PollCondVar, PollTable}, + sync::poll::{PollTable, UpgradePollCondVar}, sync::{Arc, SpinLock}, task::Task, types::ARef, @@ -412,7 +412,7 @@ pub(crate) struct Thread { #[pin] inner: SpinLock, #[pin] - work_condvar: PollCondVar, + work_condvar: UpgradePollCondVar, /// Used to insert this thread into the process' `ready_threads` list. /// /// INVARIANT: May never be used for any other list than the `self.pro= cess.ready_threads`. @@ -443,7 +443,7 @@ pub(crate) fn new(id: i32, process: Arc) -> Re= sult> { process, task: ARef::from(&**kernel::current!()), inner <- kernel::new_spinlock!(inner, "Thread::inner"), - work_condvar <- kernel::new_poll_condvar!("Thread::work_co= ndvar"), + work_condvar <- kernel::new_upgrade_poll_condvar!("Thread:= :work_condvar"), links <- ListLinks::new(), links_track <- AtomicTracker::new(), }), @@ -1484,10 +1484,15 @@ pub(crate) fn write_read(self: &Arc, data: Us= erSlice, wait: bool) -> Resul ret } =20 - pub(crate) fn poll(&self, file: &File, table: PollTable<'_>) -> (bool,= u32) { - table.register_wait(file, &self.work_condvar); + pub(crate) fn poll(&self, file: &File, table: PollTable<'_>) -> Result= <(bool, u32)> { + let condvar =3D self.work_condvar.poll( + &self.inner, + c"Thread::work_condvar (upgraded)", + kernel::static_lock_class!(), + )?; + table.register_wait(file, condvar); let mut inner =3D self.inner.lock(); - (inner.should_use_process_work_queue(), inner.poll()) + Ok((inner.should_use_process_work_queue(), inner.poll())) } =20 /// Make the call to `get_work` or `get_work_local` return immediately= , if any. @@ -1523,7 +1528,6 @@ pub(crate) fn notify_if_poll_ready(&self, sync: bool)= { pub(crate) fn release(self: &Arc) { self.inner.lock().is_dead =3D true; =20 - //self.work_condvar.clear(); self.unwind_transaction_stack(); =20 // Cancel all pending work items. --=20 2.52.0.457.g6b5491de43-goog