6
6
7
7
use crate :: { bindings, device:: Device , error:: Result , prelude:: ENODEV } ;
8
8
9
+ /// Returns the maximum number of possible CPUs in the current system configuration.
10
+ #[ inline]
11
+ pub fn nr_cpu_ids ( ) -> u32 {
12
+ #[ cfg( any( NR_CPUS_1 , CONFIG_FORCE_NR_CPUS ) ) ]
13
+ {
14
+ bindings:: NR_CPUS
15
+ }
16
+
17
+ #[ cfg( not( any( NR_CPUS_1 , CONFIG_FORCE_NR_CPUS ) ) ) ]
18
+ // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel.
19
+ unsafe {
20
+ bindings:: nr_cpu_ids
21
+ }
22
+ }
23
+
24
+ /// The CPU ID.
25
+ ///
26
+ /// Represents a CPU identifier as a wrapper around an [`u32`].
27
+ ///
28
+ /// # Invariants
29
+ ///
30
+ /// The CPU ID lies within the range `[0, nr_cpu_ids())`.
31
+ ///
32
+ /// # Examples
33
+ ///
34
+ /// ```
35
+ /// use kernel::cpu::CpuId;
36
+ ///
37
+ /// let cpu = 0;
38
+ ///
39
+ /// // SAFETY: 0 is always a valid CPU number.
40
+ /// let id = unsafe { CpuId::from_u32_unchecked(cpu) };
41
+ ///
42
+ /// assert_eq!(id.as_u32(), cpu);
43
+ /// assert!(CpuId::from_i32(0).is_some());
44
+ /// assert!(CpuId::from_i32(-1).is_none());
45
+ /// ```
46
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
47
+ pub struct CpuId ( u32 ) ;
48
+
49
+ impl CpuId {
50
+ /// Creates a new [`CpuId`] from the given `id` without checking bounds.
51
+ ///
52
+ /// # Safety
53
+ ///
54
+ /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
55
+ #[ inline]
56
+ pub unsafe fn from_i32_unchecked ( id : i32 ) -> Self {
57
+ debug_assert ! ( id >= 0 ) ;
58
+ debug_assert ! ( ( id as u32 ) < nr_cpu_ids( ) ) ;
59
+
60
+ // INVARIANT: The function safety guarantees `id` is a valid CPU id.
61
+ Self ( id as u32 )
62
+ }
63
+
64
+ /// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
65
+ pub fn from_i32 ( id : i32 ) -> Option < Self > {
66
+ if id < 0 || id as u32 >= nr_cpu_ids ( ) {
67
+ None
68
+ } else {
69
+ // INVARIANT: `id` has just been checked as a valid CPU ID.
70
+ Some ( Self ( id as u32 ) )
71
+ }
72
+ }
73
+
74
+ /// Creates a new [`CpuId`] from the given `id` without checking bounds.
75
+ ///
76
+ /// # Safety
77
+ ///
78
+ /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
79
+ #[ inline]
80
+ pub unsafe fn from_u32_unchecked ( id : u32 ) -> Self {
81
+ debug_assert ! ( id < nr_cpu_ids( ) ) ;
82
+
83
+ // Ensure the `id` fits in an [`i32`] as it's also representable that way.
84
+ debug_assert ! ( id <= i32 :: MAX as u32 ) ;
85
+
86
+ // INVARIANT: The function safety guarantees `id` is a valid CPU id.
87
+ Self ( id)
88
+ }
89
+
90
+ /// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
91
+ pub fn from_u32 ( id : u32 ) -> Option < Self > {
92
+ if id >= nr_cpu_ids ( ) {
93
+ None
94
+ } else {
95
+ // INVARIANT: `id` has just been checked as a valid CPU ID.
96
+ Some ( Self ( id) )
97
+ }
98
+ }
99
+
100
+ /// Returns CPU number.
101
+ #[ inline]
102
+ pub fn as_u32 ( & self ) -> u32 {
103
+ self . 0
104
+ }
105
+
106
+ /// Returns the ID of the CPU the code is currently running on.
107
+ ///
108
+ /// The returned value is considered unstable because it may change
109
+ /// unexpectedly due to preemption or CPU migration. It should only be
110
+ /// used when the context ensures that the task remains on the same CPU
111
+ /// or the users could use a stale (yet valid) CPU ID.
112
+ pub fn current ( ) -> Self {
113
+ // SAFETY: raw_smp_processor_id() always returns a valid CPU ID.
114
+ unsafe { Self :: from_u32_unchecked ( bindings:: raw_smp_processor_id ( ) ) }
115
+ }
116
+ }
117
+
118
+ impl From < CpuId > for u32 {
119
+ fn from ( id : CpuId ) -> Self {
120
+ id. as_u32 ( )
121
+ }
122
+ }
123
+
124
+ impl From < CpuId > for i32 {
125
+ fn from ( id : CpuId ) -> Self {
126
+ id. as_u32 ( ) as i32
127
+ }
128
+ }
129
+
9
130
/// Creates a new instance of CPU's device.
10
131
///
11
132
/// # Safety
@@ -17,9 +138,9 @@ use crate::{bindings, device::Device, error::Result, prelude::ENODEV};
17
138
/// Callers must ensure that the CPU device is not used after it has been unregistered.
18
139
/// This can be achieved, for example, by registering a CPU hotplug notifier and removing
19
140
/// any references to the CPU device within the notifier's callback.
20
- pub unsafe fn from_cpu ( cpu : u32 ) -> Result < & ' static Device > {
141
+ pub unsafe fn from_cpu ( cpu : CpuId ) -> Result < & ' static Device > {
21
142
// SAFETY: It is safe to call `get_cpu_device()` for any CPU.
22
- let ptr = unsafe { bindings:: get_cpu_device ( cpu) } ;
143
+ let ptr = unsafe { bindings:: get_cpu_device ( u32 :: from ( cpu) ) } ;
23
144
if ptr. is_null ( ) {
24
145
return Err ( ENODEV ) ;
25
146
}
0 commit comments