Skip to content

Commit 3f638a9

Browse files
committed
solaris/illumos localtime_r / clock_getime support enabled.
clock_gettime support CLOCK_REALTIME/CLOCK_MONOTONIC clockid_t. localtime_r is supported only tm struct is more limited than other supported platforms.
1 parent 7fd1429 commit 3f638a9

File tree

3 files changed

+44
-29
lines changed

3 files changed

+44
-29
lines changed

src/tools/miri/ci/ci.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ case $HOST_TARGET in
148148
UNIX="panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
149149
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
150150
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
151-
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync
152-
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX pthread-sync
151+
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync libc-time
152+
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX pthread-sync libc-time
153153
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX
154154
TEST_TARGET=wasm32-wasip2 run_tests_minimal empty_main wasm heap_alloc libc-mem
155155
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm

src/tools/miri/src/shims/time.rs

+39-25
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
6262
// We need to support it because std uses it.
6363
relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW"));
6464
}
65+
"solaris" | "illumos" => {
66+
// The REALTIME clock returns the actual time since the Unix epoch.
67+
absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")];
68+
// MONOTONIC, in the other hand, is the high resolution, non-adjustable
69+
// clock from an arbitrary time in the past.
70+
// Note that the man page mentions HIGHRES but it is just
71+
// an alias of MONOTONIC and the libc crate does not expose it anyway.
72+
// https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html
73+
relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")];
74+
}
6575
target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
6676
}
6777

@@ -153,30 +163,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
153163
// chrono crate yet.
154164
// This may not be consistent with libc::localtime_r's result.
155165
let tm_isdst = -1;
156-
157-
// tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
158-
// This may not be consistent with libc::localtime_r's result.
159-
let offset_in_seconds = dt.offset().fix().local_minus_utc();
160-
let tm_gmtoff = offset_in_seconds;
161-
let mut tm_zone = String::new();
162-
if offset_in_seconds < 0 {
163-
tm_zone.push('-');
164-
} else {
165-
tm_zone.push('+');
166-
}
167-
let offset_hour = offset_in_seconds.abs() / 3600;
168-
write!(tm_zone, "{:02}", offset_hour).unwrap();
169-
let offset_min = (offset_in_seconds.abs() % 3600) / 60;
170-
if offset_min != 0 {
171-
write!(tm_zone, "{:02}", offset_min).unwrap();
172-
}
173-
174-
// FIXME: String de-duplication is needed so that we only allocate this string only once
175-
// even when there are multiple calls to this function.
176-
let tm_zone_ptr =
177-
this.alloc_os_str_as_c_str(&OsString::from(tm_zone), MiriMemoryKind::Machine.into())?;
178-
179-
this.write_pointer(tm_zone_ptr, &this.project_field_named(&result, "tm_zone")?)?;
180166
this.write_int_fields_named(
181167
&[
182168
("tm_sec", dt.second().into()),
@@ -188,11 +174,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
188174
("tm_wday", dt.weekday().num_days_from_sunday().into()),
189175
("tm_yday", dt.ordinal0().into()),
190176
("tm_isdst", tm_isdst),
191-
("tm_gmtoff", tm_gmtoff.into()),
192177
],
193178
&result,
194179
)?;
195180

181+
// solaris/illumos system tm struct does not have
182+
// the additional tm_zone/tm_gmtoff fields.
183+
// https://docs.oracle.com/cd/E36784_01/html/E36874/localtime-r-3c.html
184+
if !matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") {
185+
// tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
186+
// This may not be consistent with libc::localtime_r's result.
187+
let offset_in_seconds = dt.offset().fix().local_minus_utc();
188+
let tm_gmtoff = offset_in_seconds;
189+
let mut tm_zone = String::new();
190+
if offset_in_seconds < 0 {
191+
tm_zone.push('-');
192+
} else {
193+
tm_zone.push('+');
194+
}
195+
let offset_hour = offset_in_seconds.abs() / 3600;
196+
write!(tm_zone, "{:02}", offset_hour).unwrap();
197+
let offset_min = (offset_in_seconds.abs() % 3600) / 60;
198+
if offset_min != 0 {
199+
write!(tm_zone, "{:02}", offset_min).unwrap();
200+
}
201+
202+
// FIXME: String de-duplication is needed so that we only allocate this string only once
203+
// even when there are multiple calls to this function.
204+
let tm_zone_ptr = this
205+
.alloc_os_str_as_c_str(&OsString::from(tm_zone), MiriMemoryKind::Machine.into())?;
206+
207+
this.write_pointer(tm_zone_ptr, &this.project_field_named(&result, "tm_zone")?)?;
208+
this.write_int_fields_named(&[("tm_gmtoff", tm_gmtoff.into())], &result)?;
209+
}
196210
Ok(result.ptr())
197211
}
198212
#[allow(non_snake_case, clippy::arithmetic_side_effects)]

src/tools/miri/tests/pass-dep/libc/libc-time.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//@ignore-target-windows: no libc time APIs on Windows
22
//@compile-flags: -Zmiri-disable-isolation
3-
use std::ffi::CStr;
43
use std::{env, mem, ptr};
54

65
fn main() {
@@ -64,7 +63,9 @@ fn test_localtime_r() {
6463
tm_wday: 0,
6564
tm_yday: 0,
6665
tm_isdst: 0,
66+
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
6767
tm_gmtoff: 0,
68+
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
6869
tm_zone: std::ptr::null_mut::<libc::c_char>(),
6970
};
7071
let res = unsafe { libc::localtime_r(custom_time_ptr, &mut tm) };
@@ -82,7 +83,7 @@ fn test_localtime_r() {
8283
assert_eq!(tm.tm_gmtoff, 0);
8384
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
8485
unsafe {
85-
assert_eq!(CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00")
86+
assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00")
8687
};
8788

8889
// The returned value is the pointer passed in.

0 commit comments

Comments
 (0)