@@ -14,41 +14,46 @@ use core::marker::PhantomPinned;
14
14
use core:: pin:: Pin ;
15
15
16
16
/// A registration of a miscellaneous device.
17
- pub struct Registration {
17
+ pub struct Registration < T : Sync = ( ) > {
18
18
registered : bool ,
19
19
mdev : bindings:: miscdevice ,
20
20
_pin : PhantomPinned ,
21
+
22
+ /// Context initialised on construction.
23
+ pub context : T ,
21
24
}
22
25
23
- impl Registration {
26
+ impl < T : Sync > Registration < T > {
24
27
/// Creates a new [`Registration`] but does not register it yet.
25
28
///
26
29
/// It is allowed to move.
27
- pub fn new ( ) -> Self {
30
+ pub fn new ( context : T ) -> Self {
28
31
Self {
29
32
registered : false ,
30
33
mdev : bindings:: miscdevice:: default ( ) ,
31
34
_pin : PhantomPinned ,
35
+ context,
32
36
}
33
37
}
34
38
35
39
/// Registers a miscellaneous device.
36
40
///
37
41
/// Returns a pinned heap-allocated representation of the registration.
38
- pub fn new_pinned < T : FileOperations > (
42
+ pub fn new_pinned < F : FileOperations > (
39
43
name : CStr < ' static > ,
40
44
minor : Option < i32 > ,
45
+ context : T ,
41
46
) -> KernelResult < Pin < Box < Self > > > {
42
- let mut r = Pin :: from ( Box :: try_new ( Self :: new ( ) ) ?) ;
43
- r. as_mut ( ) . register :: < T > ( name, minor) ?;
47
+ let mut r = Pin :: from ( Box :: try_new ( Self :: new ( context ) ) ?) ;
48
+ r. as_mut ( ) . register :: < F > ( name, minor) ?;
44
49
Ok ( r)
45
50
}
46
51
47
52
/// Registers a miscellaneous device with the rest of the kernel.
48
53
///
49
54
/// It must be pinned because the memory block that represents the registration is
50
55
/// self-referential. If a minor is not given, the kernel allocates a new one if possible.
51
- pub fn register < T : FileOperations > (
56
+ pub fn register < F : FileOperations > (
52
57
self : Pin < & mut Self > ,
53
58
name : CStr < ' static > ,
54
59
minor : Option < i32 > ,
@@ -60,7 +65,7 @@ impl Registration {
60
65
return Err ( Error :: EINVAL ) ;
61
66
}
62
67
63
- this. mdev . fops = FileOperationsVtable :: < T > :: build ( ) ;
68
+ this. mdev . fops = FileOperationsVtable :: < F > :: build ( ) ;
64
69
this. mdev . name = name. as_ptr ( ) as * const c_types:: c_char ;
65
70
this. mdev . minor = minor. unwrap_or ( bindings:: MISC_DYNAMIC_MINOR as i32 ) ;
66
71
@@ -73,17 +78,17 @@ impl Registration {
73
78
}
74
79
}
75
80
76
- impl Default for Registration {
77
- fn default ( ) -> Self {
78
- Self :: new ( )
79
- }
80
- }
81
-
82
81
// SAFETY: The only method is `register()`, which requires a (pinned) mutable `Registration`, so it
83
- // is safe to pass `&Registration` to multiple threads because it offers no interior mutability.
84
- unsafe impl Sync for Registration { }
82
+ // is safe to pass `&Registration` to multiple threads because it offers no interior mutability,
83
+ // except maybe through `Registration::context`, but it is itself `Sync`.
84
+ unsafe impl < T : Sync > Sync for Registration < T > { }
85
+
86
+ // SAFETY: All functions work from any thread. So as long as the `Registration::context` is
87
+ // `Send`, so is `Registration<T>`. `T` needs to be `Sync` because it's a requirement of
88
+ // `Registration<T>`.
89
+ unsafe impl < T : Send + Sync > Send for Registration < T > { }
85
90
86
- impl Drop for Registration {
91
+ impl < T : Sync > Drop for Registration < T > {
87
92
/// Removes the registration from the kernel if it has completed successfully before.
88
93
fn drop ( & mut self ) {
89
94
if self . registered {
0 commit comments