a653rs/apex/
process.rs

1/// bindings for ARINC653P1-5 3.3 process
2pub mod basic {
3    use crate::apex::time::basic::*;
4    use crate::apex::types::basic::*;
5
6    /// ARINC653P1-5 3.3.1
7    pub type ProcessName = ApexName;
8    /// ARINC653P1-5 3.3.1
9    pub type ProcessIndex = ApexInteger;
10    /// ARINC653P1-5 3.3.1
11    pub type StackSize = ApexUnsigned;
12
13    /// ARINC653P1-5 3.3.1
14    pub type Priority = ApexInteger;
15    pub const MIN_PRIORITY_VALUE: Priority = 1;
16    pub const MAX_PRIORITY_VALUE: Priority = 239;
17
18    /// ARINC653P1-5 3.3.1
19    pub type LockLevel = ApexInteger;
20    pub const MIN_LOCK_LEVEL: LockLevel = 0;
21    pub const MAX_LOCK_LEVEL: LockLevel = 16;
22
23    /// ARINC653P1-5 3.3.1 C compatible function type
24    pub type SystemAddress = extern "C" fn();
25
26    /// ARINC653P1-5 3.3.1
27    ///
28    /// According to ARINC 653P1-5 this may either be 32 or 64 bits.
29    /// Internally we will use 64-bit by default.
30    /// The implementing Hypervisor may cast this to 32-bit if needed
31    pub type ProcessId = ApexLongInteger;
32    pub const NULL_PROCESS_ID: ProcessId = 0;
33    pub const MAIN_PROCESS_ID: ProcessId = -1;
34
35    /// ARINC653P1-5 3.3.1
36    #[repr(u32)]
37    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
38    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39    #[cfg_attr(feature = "strum", derive(strum::FromRepr))]
40    pub enum ProcessState {
41        Dormant = 0,
42        Ready = 1,
43        Running = 2,
44        Waiting = 3,
45        Faulted = 4,
46    }
47
48    /// ARINC653P1-5 3.3.1
49    #[repr(u32)]
50    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
51    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52    #[cfg_attr(feature = "strum", derive(strum::FromRepr))]
53    pub enum Deadline {
54        Soft = 0,
55        Hard = 1,
56    }
57
58    /// ARINC653P1-5 3.3.1
59    #[repr(C)]
60    #[derive(Debug, Clone, PartialEq, Eq)]
61    pub struct ApexProcessAttribute {
62        pub period: ApexSystemTime,
63        pub time_capacity: ApexSystemTime,
64        pub entry_point: SystemAddress,
65        pub stack_size: StackSize,
66        pub base_priority: Priority,
67        pub deadline: Deadline,
68        pub name: ProcessName,
69    }
70
71    /// ARINC653P1-5 3.3.1
72    #[repr(C)]
73    #[derive(Debug, Clone, PartialEq, Eq)]
74    pub struct ApexProcessStatus {
75        pub deadline_time: ApexSystemTime,
76        pub current_priority: Priority,
77        pub process_state: ProcessState,
78        pub attributes: ApexProcessAttribute,
79    }
80
81    /// ARINC653P4 3.3.2 required functions for process functionality
82    pub trait ApexProcessP4 {
83        /// ARINC653P4 3.3.2.3
84        ///
85        /// # Errors
86        /// - [ErrorReturnCode::InvalidConfig]: not enough memory is available
87        /// - [ErrorReturnCode::InvalidConfig]: [ApexLimits::SYSTEM_LIMIT_NUMBER_OF_PROCESSES](crate::apex::limits::ApexLimits::SYSTEM_LIMIT_NUMBER_OF_PROCESSES) was reached
88        /// - [ErrorReturnCode::NoAction]: a process with given `attributes.name` already exists
89        /// - [ErrorReturnCode::InvalidParam]: `attributes.stack_size` is invalid
90        /// - [ErrorReturnCode::InvalidParam]: `attributes.base_priority` is invalid
91        /// - [ErrorReturnCode::InvalidParam]: `attributes.period` is invalid
92        /// - [ErrorReturnCode::InvalidConfig]: `attributes.period` is positive and `attributes.period` is not dividable by the partition period
93        /// - [ErrorReturnCode::InvalidParam]: `attributes.time_capacity` is invalid
94        /// - [ErrorReturnCode::InvalidParam]: `attributes.period` is positive and `attributes.period` is less than `attributes.time_capacity`
95        /// - [ErrorReturnCode::InvalidMode]: our current operating mode is [OperatingMode::Normal](crate::prelude::OperatingMode::Normal)
96        fn create_process(attributes: &ApexProcessAttribute) -> Result<ProcessId, ErrorReturnCode>;
97
98        fn start(process_id: ProcessId) -> Result<(), ErrorReturnCode>;
99    }
100
101    pub trait ApexProcessP1: ApexProcessP4 {
102        fn set_priority(process_id: ProcessId, priority: Priority) -> Result<(), ErrorReturnCode>;
103
104        fn suspend_self(time_out: ApexSystemTime) -> Result<(), ErrorReturnCode>;
105
106        fn suspend(process_id: ProcessId) -> Result<(), ErrorReturnCode>;
107
108        fn resume(process_id: ProcessId) -> Result<(), ErrorReturnCode>;
109
110        fn stop_self();
111
112        fn stop(process_id: ProcessId) -> Result<(), ErrorReturnCode>;
113
114        fn delayed_start(
115            process_id: ProcessId,
116            delay_time: ApexSystemTime,
117        ) -> Result<(), ErrorReturnCode>;
118
119        fn lock_preemption() -> Result<LockLevel, ErrorReturnCode>;
120
121        fn unlock_preemption() -> Result<LockLevel, ErrorReturnCode>;
122
123        fn get_my_id() -> Result<ProcessId, ErrorReturnCode>;
124
125        fn get_process_id(process_name: ProcessName) -> Result<ProcessId, ErrorReturnCode>;
126
127        fn get_process_status(process_id: ProcessId) -> Result<ApexProcessStatus, ErrorReturnCode>;
128
129        // Only during Warm/Cold-Start
130        fn initialize_process_core_affinity(
131            process_id: ProcessId,
132            processor_core_id: ProcessorCoreId,
133        ) -> Result<(), ErrorReturnCode>;
134
135        fn get_my_processor_core_id() -> ProcessorCoreId;
136
137        fn get_my_index() -> Result<ProcessIndex, ErrorReturnCode>;
138    }
139}
140
141/// abstractions for ARINC653P1-5 3.3 process
142pub mod abstraction {
143    use core::marker::PhantomData;
144    use core::sync::atomic::AtomicPtr;
145
146    use super::basic::{ApexProcessAttribute, ApexProcessP1, ApexProcessP4, ApexProcessStatus};
147    // Reexport important basic-types for downstream-user
148    pub use super::basic::{
149        Deadline, LockLevel, Priority, ProcessId, ProcessIndex, ProcessName, StackSize,
150        SystemAddress, MAIN_PROCESS_ID, MAX_LOCK_LEVEL, MAX_PRIORITY_VALUE, MIN_LOCK_LEVEL,
151        MIN_PRIORITY_VALUE, NULL_PROCESS_ID,
152    };
153    use crate::prelude::*;
154
155    #[derive(Debug, Clone, PartialEq, Eq)]
156    pub struct ProcessAttribute {
157        pub period: SystemTime,
158        pub time_capacity: SystemTime,
159        pub entry_point: SystemAddress,
160        pub stack_size: StackSize,
161        pub base_priority: Priority,
162        pub deadline: Deadline,
163        pub name: Name,
164    }
165
166    impl From<ProcessAttribute> for ApexProcessAttribute {
167        fn from(p: ProcessAttribute) -> Self {
168            ApexProcessAttribute {
169                period: p.period.into(),
170                time_capacity: p.time_capacity.into(),
171                entry_point: p.entry_point,
172                stack_size: p.stack_size,
173                base_priority: p.base_priority,
174                deadline: p.deadline,
175                name: p.name.into(),
176            }
177        }
178    }
179
180    impl From<ApexProcessAttribute> for ProcessAttribute {
181        fn from(p: ApexProcessAttribute) -> Self {
182            ProcessAttribute {
183                period: p.period.into(),
184                time_capacity: p.time_capacity.into(),
185                entry_point: p.entry_point,
186                stack_size: p.stack_size,
187                base_priority: p.base_priority,
188                deadline: p.deadline,
189                name: Name::new(p.name),
190            }
191        }
192    }
193
194    #[derive(Debug, Clone, PartialEq, Eq)]
195    pub struct ProcessStatus {
196        pub deadline_time: SystemTime,
197        pub current_priority: Priority,
198        pub process_state: super::basic::ProcessState,
199        pub attributes: ProcessAttribute,
200    }
201
202    impl From<ApexProcessStatus> for ProcessStatus {
203        fn from(p: ApexProcessStatus) -> Self {
204            ProcessStatus {
205                deadline_time: p.deadline_time.into(),
206                current_priority: p.current_priority,
207                process_state: p.process_state,
208                attributes: p.attributes.into(),
209            }
210        }
211    }
212
213    #[derive(Debug)]
214    pub struct Process<P: ApexProcessP4> {
215        _p: PhantomData<AtomicPtr<P>>,
216        id: ProcessId,
217    }
218
219    impl<P: ApexProcessP4> Clone for Process<P> {
220        fn clone(&self) -> Self {
221            Self {
222                _p: self._p,
223                id: self.id,
224            }
225        }
226    }
227
228    pub trait ApexProcessP1Ext: ApexProcessP1 + Sized {
229        fn get_process(name: Name) -> Result<Process<Self>, Error>;
230    }
231
232    impl<P: ApexProcessP1> ApexProcessP1Ext for P {
233        fn get_process(name: Name) -> Result<Process<P>, Error> {
234            let id = P::get_process_id(name.into())?;
235            Ok(Process {
236                _p: Default::default(),
237                id,
238            })
239        }
240    }
241
242    impl<P: ApexProcessP4> Process<P> {
243        pub fn start(&self) -> Result<(), Error> {
244            P::start(self.id)?;
245            Ok(())
246        }
247
248        pub fn id(&self) -> ProcessId {
249            self.id
250        }
251    }
252
253    impl<P: ApexProcessP1> Process<P> {
254        pub fn from_name(name: Name) -> Result<Process<P>, Error> {
255            P::get_process(name)
256        }
257
258        pub fn get_self() -> Result<Process<P>, Error> {
259            let id = P::get_my_id()?;
260            Ok(Process {
261                _p: Default::default(),
262                id,
263            })
264        }
265
266        pub fn set_priority(&self, priority: Priority) -> Result<(), Error> {
267            P::set_priority(self.id, priority)?;
268            Ok(())
269        }
270
271        pub fn suspend_self(time_out: SystemTime) -> Result<(), Error> {
272            P::suspend_self(time_out.into())?;
273            Ok(())
274        }
275
276        pub fn suspend(&self) -> Result<(), Error> {
277            P::suspend(self.id)?;
278            Ok(())
279        }
280
281        pub fn resume(&self) -> Result<(), Error> {
282            P::resume(self.id)?;
283            Ok(())
284        }
285
286        pub fn stop_self() {
287            P::stop_self()
288        }
289
290        pub fn stop(&self) -> Result<(), Error> {
291            P::stop(self.id)?;
292            Ok(())
293        }
294
295        pub fn delayed_start(&self, delay_time: SystemTime) -> Result<(), Error> {
296            P::delayed_start(self.id, delay_time.into())?;
297            Ok(())
298        }
299
300        pub fn lock_preemption() -> Result<LockLevel, Error> {
301            Ok(P::lock_preemption()?)
302        }
303
304        pub fn unlock_preemption() -> Result<LockLevel, Error> {
305            Ok(P::unlock_preemption()?)
306        }
307
308        pub fn status(&self) -> ProcessStatus {
309            // According to ARINC653P1-5 3.3.2.2 this can only fail if the processId
310            //  does not exist in the current partition.
311            // But since we retrieve the processId directly from the hypervisor
312            //  there is no possible way for it not existing
313            P::get_process_status(self.id).unwrap().into()
314        }
315
316        pub fn get_my_processor_core_id() -> ProcessorCoreId {
317            P::get_my_processor_core_id()
318        }
319
320        pub fn get_my_index() -> Result<ProcessIndex, Error> {
321            Ok(P::get_my_index()?)
322        }
323    }
324
325    impl<P: ApexProcessP4> StartContext<P> {
326        pub fn create_process(&mut self, attr: ProcessAttribute) -> Result<Process<P>, Error> {
327            let id = P::create_process(&attr.into())?;
328            Ok(Process {
329                _p: Default::default(),
330                id,
331            })
332        }
333    }
334
335    impl<P: ApexProcessP1> StartContext<P> {
336        pub fn initialize_process_core_affinity(
337            &self,
338            process: &Process<P>,
339            processor_core_id: ProcessorCoreId,
340        ) -> Result<(), Error> {
341            P::initialize_process_core_affinity(process.id, processor_core_id)?;
342            Ok(())
343        }
344    }
345}