@@ -9,9 +9,8 @@ use crate::{
99 fs:: File ,
1010 prelude:: * ,
1111 sync:: { CondVar , LockClassKey } ,
12- types:: Opaque ,
1312} ;
14- use core:: ops:: Deref ;
13+ use core:: { marker :: PhantomData , ops:: Deref } ;
1514
1615/// Creates a [`PollCondVar`] initialiser with the given name and a newly-created lock class.
1716#[ macro_export]
@@ -23,58 +22,43 @@ macro_rules! new_poll_condvar {
2322 } ;
2423}
2524
26- /// Wraps the kernel's `struct poll_table`.
25+ /// Wraps the kernel's `poll_table`.
2726///
2827/// # Invariants
2928///
30- /// This struct contains a valid `struct poll_table`.
31- ///
32- /// For a `struct poll_table` to be valid, its `_qproc` function must follow the safety
33- /// requirements of `_qproc` functions:
34- ///
35- /// * The `_qproc` function is given permission to enqueue a waiter to the provided `poll_table`
36- /// during the call. Once the waiter is removed and an rcu grace period has passed, it must no
37- /// longer access the `wait_queue_head`.
29+ /// The pointer must be null or reference a valid `poll_table`.
3830#[ repr( transparent) ]
39- pub struct PollTable ( Opaque < bindings:: poll_table > ) ;
31+ pub struct PollTable < ' a > {
32+ table : * mut bindings:: poll_table ,
33+ _lifetime : PhantomData < & ' a bindings:: poll_table > ,
34+ }
4035
41- impl PollTable {
42- /// Creates a reference to a [`PollTable`] from a valid pointer.
36+ impl < ' a > PollTable < ' a > {
37+ /// Creates a [`PollTable`] from a valid pointer.
4338 ///
4439 /// # Safety
4540 ///
46- /// The caller must ensure that for the duration of `'a`, the pointer will point at a valid poll
47- /// table (as defined in the type invariants).
48- ///
49- /// The caller must also ensure that the `poll_table` is only accessed via the returned
50- /// reference for the duration of `'a`.
51- pub unsafe fn from_ptr < ' a > ( ptr : * mut bindings:: poll_table ) -> & ' a mut PollTable {
52- // SAFETY: The safety requirements guarantee the validity of the dereference, while the
53- // `PollTable` type being transparent makes the cast ok.
54- unsafe { & mut * ptr. cast ( ) }
55- }
56-
57- fn get_qproc ( & self ) -> bindings:: poll_queue_proc {
58- let ptr = self . 0 . get ( ) ;
59- // SAFETY: The `ptr` is valid because it originates from a reference, and the `_qproc`
60- // field is not modified concurrently with this call since we have an immutable reference.
61- unsafe { ( * ptr) . _qproc }
41+ /// The pointer must be null or reference a valid `poll_table` for the duration of `'a`.
42+ pub unsafe fn from_raw ( table : * mut bindings:: poll_table ) -> Self {
43+ // INVARIANTS: The safety requirements are the same as the struct invariants.
44+ PollTable {
45+ table,
46+ _lifetime : PhantomData ,
47+ }
6248 }
6349
6450 /// Register this [`PollTable`] with the provided [`PollCondVar`], so that it can be notified
6551 /// using the condition variable.
66- pub fn register_wait ( & mut self , file : & File , cv : & PollCondVar ) {
67- if let Some ( qproc) = self . get_qproc ( ) {
68- // SAFETY: The pointers to `file` and `self` need to be valid for the duration of this
69- // call to `qproc`, which they are because they are references.
70- //
71- // The `cv.wait_queue_head` pointer must be valid until an rcu grace period after the
72- // waiter is removed. The `PollCondVar` is pinned, so before `cv.wait_queue_head` can
73- // be destroyed, the destructor must run. That destructor first removes all waiters,
74- // and then waits for an rcu grace period. Therefore, `cv.wait_queue_head` is valid for
75- // long enough.
76- unsafe { qproc ( file. as_ptr ( ) as _ , cv. wait_queue_head . get ( ) , self . 0 . get ( ) ) } ;
77- }
52+ pub fn register_wait ( & self , file : & File , cv : & PollCondVar ) {
53+ // SAFETY:
54+ // * `file.as_ptr()` references a valid file for the duration of this call.
55+ // * `self.table` is null or references a valid poll_table for the duration of this call.
56+ // * Since `PollCondVar` is pinned, its destructor is guaranteed to run before the memory
57+ // containing `cv.wait_queue_head` is invalidated. Since the destructor clears all
58+ // waiters and then waits for an rcu grace period, it's guaranteed that
59+ // `cv.wait_queue_head` remains valid for at least an rcu grace period after the removal
60+ // of the last waiter.
61+ unsafe { bindings:: poll_wait ( file. as_ptr ( ) , cv. wait_queue_head . get ( ) , self . table ) }
7862 }
7963}
8064
0 commit comments