]> git.lizzy.rs Git - rust.git/blob - src/shims/time.rs
97b74542d8091bacb93bfbaf50c96b2f8171fa0b
[rust.git] / src / shims / time.rs
1 use crate::stacked_borrows::Tag;
2 use crate::*;
3
4 use std::time::{Duration, SystemTime};
5
6 fn get_time() -> (Duration, i128) {
7     let mut sign = 1;
8     let duration = SystemTime::now()
9         .duration_since(SystemTime::UNIX_EPOCH)
10         .unwrap_or_else(|e| {
11             sign = -1;
12             e.duration()
13         });
14     (duration, sign)
15 }
16
17 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
18 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
19     fn clock_gettime(
20         &mut self,
21         clk_id_op: OpTy<'tcx, Tag>,
22         tp_op: OpTy<'tcx, Tag>,
23     ) -> InterpResult<'tcx, i32> {
24         let this = self.eval_context_mut();
25
26         if !this.machine.communicate {
27             throw_unsup_format!("`clock_gettime` not available when isolation is enabled")
28         }
29
30         let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
31         if clk_id != this.eval_libc_i32("CLOCK_REALTIME")? {
32             let einval = this.eval_libc("EINVAL")?;
33             this.set_last_error(einval)?;
34             return Ok(-1);
35         }
36
37         let tp = this.force_ptr(this.read_scalar(tp_op)?.not_undef()?)?;
38
39         let (duration, sign) = get_time();
40         let tv_sec = sign * (duration.as_secs() as i128);
41         let tv_nsec = duration.subsec_nanos() as i128;
42         this.write_c_ints(&tp, &[tv_sec, tv_nsec], &["time_t", "c_long"])?;
43
44         Ok(0)
45     }
46
47     fn gettimeofday(
48         &mut self,
49         tv_op: OpTy<'tcx, Tag>,
50         tz_op: OpTy<'tcx, Tag>,
51     ) -> InterpResult<'tcx, i32> {
52         let this = self.eval_context_mut();
53
54         if !this.machine.communicate {
55             throw_unsup_format!("`gettimeofday` not available when isolation is enabled")
56         }
57         // Using tz is obsolete and should always be null
58         let tz = this.read_scalar(tz_op)?.not_undef()?;
59         if !this.is_null(tz)? {
60             let einval = this.eval_libc("EINVAL")?;
61             this.set_last_error(einval)?;
62             return Ok(-1);
63         }
64
65         let tv = this.force_ptr(this.read_scalar(tv_op)?.not_undef()?)?;
66
67         let (duration, sign) = get_time();
68         let tv_sec = sign * (duration.as_secs() as i128);
69         let tv_usec = duration.subsec_micros() as i128;
70
71         this.write_c_ints(&tv, &[tv_sec, tv_usec], &["time_t", "suseconds_t"])?;
72
73         Ok(0)
74     }
75 }