[NOT FOR MERGE] [RFC PATCH v2 4/4] rust: poll: use kfree_rcu() for PollCondVar

Boqun Feng <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media,org.kernel.vger.rcu,org.kvack.linux-mm
Message-ID <[email protected]>
From: Alice Ryhl <[email protected]>

Rust Binder currently uses PollCondVar, but it calls synchronize_rcu()
in the destructor, which we would like to avoid. Add a variation of
PollCondVar that kfree_rcu() instead.

One could avoid the `rcu` field and allocate the rcu_head on drop using
a fallback to synchronize_rcu() on ENOMEM. However, I'd prefer to avoid
the potential for synchronize_rcu(), and Binder will only use this for a
small fraction of processes, so even if it changes which kmalloc bucket
it falls into, the extra memory is not a problem.

Signed-off-by: Alice Ryhl <[email protected]>
[boqun: Use RcuFreeSafe]
Signed-off-by: Boqun Feng <[email protected]>
---
 rust/kernel/sync/poll.rs | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs
index 5aa0ce9ba01b..830a4763a5c1 100644
--- a/rust/kernel/sync/poll.rs
+++ b/rust/kernel/sync/poll.rs
@@ -9,12 +9,19 @@
     fs::File,
     prelude::*,
     sync::{
-        rcu::synchronize_rcu,
+        rcu::{
+            synchronize_rcu, //
+            RcuFreeSafe,
+        },
         CondVar,
         LockClassKey, //
     }, //
 };
-use core::{marker::PhantomData, ops::Deref};
+
+use core::{
+    marker::PhantomData,
+    ops::Deref, //
+};
 
 /// Creates a [`PollCondVar`] initialiser with the given name and a newly-created lock class.
 #[macro_export]
@@ -70,6 +77,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,
@@ -97,12 +105,20 @@ fn deref(&self) -> &CondVar {
 impl PinnedDrop for PollCondVar {
     #[inline]
     fn drop(self: Pin<&mut Self>) {
+        self.drop_before_gp();
+
+        // Wait for epoll items to be properly removed.
+        synchronize_rcu();
+    }
+}
+
+// SAFETY: __wake_up_pollfree() guarantees all the epoll items on the wait list will be gone after
+// one grace period.
+unsafe impl RcuFreeSafe for PollCondVar {
+    fn drop_before_gp(self: Pin<&mut Self>) {
         // Clear anything registered using `register_wait`.
         //
         // SAFETY: The pointer points at a valid `wait_queue_head`.
         unsafe { bindings::__wake_up_pollfree(self.inner.wait_queue_head.get()) };
-
-        // Wait for epoll items to be properly removed.
-        synchronize_rcu();
     }
 }
-- 
2.50.1 (Apple Git-155)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.