1use zx::sys::{ZX_HANDLE_INVALID, zx_handle_t, zx_status_t};
10use zx::{BootTimeline, Clock, NullableHandle, Status, SyntheticTimeline, Timeline, Unowned};
11
12unsafe extern "C" {
14 fn _zx_utc_reference_get() -> zx_handle_t;
15
16 fn _zx_utc_reference_swap(
17 new_utc_reference: zx_handle_t,
18 prev_utc_reference_out: *mut zx_handle_t,
19 ) -> zx_status_t;
20}
21
22pub type UtcClock<T = SyntheticTimeline> = Clock<BootTimeline, T>;
25
26pub fn reference_get<T: Timeline>() -> Unowned<'static, UtcClock<T>> {
36 unsafe { Unowned::from_raw_handle(_zx_utc_reference_get()) }
38}
39
40pub fn reference_swap<T: Timeline>(new_clock: UtcClock<T>) -> Result<UtcClock<T>, Status> {
42 Ok(unsafe {
44 let mut old = ZX_HANDLE_INVALID;
45 Status::ok(_zx_utc_reference_swap(new_clock.into_raw(), &mut old))?;
46 NullableHandle::from_raw(old)
47 }
48 .into())
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use zx::ClockOpts;
55
56 fn fake_clock() -> UtcClock {
57 UtcClock::create(ClockOpts::MONOTONIC, None).expect("cannot create test clock")
58 }
59
60 #[test]
61 fn test_get() {
62 let test_clock = fake_clock();
63 let original_clock = reference_get();
64 assert_ne!(original_clock, test_clock.unowned())
65 }
66
67 #[test]
68 fn test_swap() {
69 let original_clock = reference_get();
70 let new_clock = fake_clock();
71
72 let test_clock = unsafe { Unowned::<UtcClock>::from_raw_handle(new_clock.raw_handle()) };
74
75 let real_clock = reference_swap(new_clock).expect("cannot swap");
76 assert_eq!(real_clock.unowned(), original_clock);
77
78 let got_clock = reference_get();
79
80 let swapped_clock = reference_swap(real_clock).expect("cannot swap back");
82
83 assert_ne!(original_clock, test_clock);
84 assert_eq!(got_clock, test_clock);
85 assert_eq!(swapped_clock.unowned(), test_clock);
86 }
87}