rt_xenomai/
lib.rs

1mod ffi;
2
3use core::time::Duration;
4use libc::{c_longlong, c_ulong};
5use nix::unistd::Uid;
6use realtime_core::*;
7
8pub struct Xenomai {
9    start_time: c_longlong,
10}
11
12impl Xenomai {
13    pub fn new(prio: i32) -> Result<Self> {
14        // 要求 root 权限,否则无法启动
15        if !Uid::effective().is_root() {
16            return Err(ErrorKind::NotRoot);
17        }
18        unsafe { ffi::init() };
19        match unsafe { ffi::shadow(prio, 1) } {
20            0 => {}
21            x => return Err(ErrorKind::Unknown(x as isize)),
22        }
23
24        Ok(Self { start_time: 0 })
25    }
26
27    pub fn get_time_ns() -> u64 {
28        unsafe { ffi::read() as u64 }
29    }
30}
31impl RealTime for Xenomai {
32    fn start(&mut self, period: Duration) -> Result<()> {
33        let period = period.as_nanos() as c_longlong;
34        let start_time = unsafe { ffi::read() } + period;
35        match unsafe { ffi::set_periodic(start_time, period) } {
36            0 => {
37                self.start_time = start_time;
38                log::info!(
39                    "Xenomai start: period={}, start_time={}",
40                    period,
41                    start_time
42                );
43                Ok(())
44            }
45            x => Err(ErrorKind::Unknown(x as isize)),
46        }
47    }
48    fn stop(&mut self) -> Result<()> {
49        if self.start_time == 0 {
50            return Ok(());
51        }
52        match unsafe { ffi::set_periodic(0, 0) } {
53            0 => {
54                self.start_time = 0;
55                Ok(())
56            }
57            x => Err(ErrorKind::Unknown(x as isize)),
58        }
59    }
60    fn wait_period(&mut self) -> Result<()> {
61        if self.start_time == 0 {
62            return Err(ErrorKind::NotStart);
63        }
64        let mut overrun: c_ulong = 0;
65        match unsafe { ffi::wait_period(&mut overrun as *mut _) } {
66            0 => Ok(()),
67            x => Err(ErrorKind::Unknown(x as isize)),
68        }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn tolerance() {
78        let mut xenomai = Xenomai::new(90).unwrap();
79        xenomai.start(Duration::from_millis(1)).unwrap();
80        xenomai.wait_period().unwrap();
81        let mut last_time = clock_source::now();
82        for _ in 0..1_000 {
83            xenomai.wait_period().unwrap();
84            let now = clock_source::now();
85            if now - last_time > 1_200_000 {
86                println!("{}", now - last_time - 1_000_000);
87            }
88            assert!(now - last_time < 1_200_000);
89            last_time = now;
90        }
91    }
92}