Auto merge of #3614 - devnexen:illumos_time_support, r=oli-obk

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.
This commit is contained in:
bors 2024-05-22 20:14:42 +00:00
commit 04a9a1a531
3 changed files with 44 additions and 29 deletions

View File

@ -148,8 +148,8 @@ case $HOST_TARGET in
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
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX pthread-sync
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync libc-time
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX pthread-sync libc-time
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX
TEST_TARGET=wasm32-wasip2 run_tests_minimal empty_main wasm heap_alloc libc-mem
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm

View File

@ -62,6 +62,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// We need to support it because std uses it.
relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW"));
}
"solaris" | "illumos" => {
// The REALTIME clock returns the actual time since the Unix epoch.
absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")];
// MONOTONIC, in the other hand, is the high resolution, non-adjustable
// clock from an arbitrary time in the past.
// Note that the man page mentions HIGHRES but it is just
// an alias of MONOTONIC and the libc crate does not expose it anyway.
// https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html
relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")];
}
target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
}
@ -153,30 +163,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// chrono crate yet.
// This may not be consistent with libc::localtime_r's result.
let tm_isdst = -1;
// tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
// This may not be consistent with libc::localtime_r's result.
let offset_in_seconds = dt.offset().fix().local_minus_utc();
let tm_gmtoff = offset_in_seconds;
let mut tm_zone = String::new();
if offset_in_seconds < 0 {
tm_zone.push('-');
} else {
tm_zone.push('+');
}
let offset_hour = offset_in_seconds.abs() / 3600;
write!(tm_zone, "{:02}", offset_hour).unwrap();
let offset_min = (offset_in_seconds.abs() % 3600) / 60;
if offset_min != 0 {
write!(tm_zone, "{:02}", offset_min).unwrap();
}
// FIXME: String de-duplication is needed so that we only allocate this string only once
// even when there are multiple calls to this function.
let tm_zone_ptr =
this.alloc_os_str_as_c_str(&OsString::from(tm_zone), MiriMemoryKind::Machine.into())?;
this.write_pointer(tm_zone_ptr, &this.project_field_named(&result, "tm_zone")?)?;
this.write_int_fields_named(
&[
("tm_sec", dt.second().into()),
@ -188,11 +174,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
("tm_wday", dt.weekday().num_days_from_sunday().into()),
("tm_yday", dt.ordinal0().into()),
("tm_isdst", tm_isdst),
("tm_gmtoff", tm_gmtoff.into()),
],
&result,
)?;
// solaris/illumos system tm struct does not have
// the additional tm_zone/tm_gmtoff fields.
// https://docs.oracle.com/cd/E36784_01/html/E36874/localtime-r-3c.html
if !matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") {
// tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
// This may not be consistent with libc::localtime_r's result.
let offset_in_seconds = dt.offset().fix().local_minus_utc();
let tm_gmtoff = offset_in_seconds;
let mut tm_zone = String::new();
if offset_in_seconds < 0 {
tm_zone.push('-');
} else {
tm_zone.push('+');
}
let offset_hour = offset_in_seconds.abs() / 3600;
write!(tm_zone, "{:02}", offset_hour).unwrap();
let offset_min = (offset_in_seconds.abs() % 3600) / 60;
if offset_min != 0 {
write!(tm_zone, "{:02}", offset_min).unwrap();
}
// FIXME: String de-duplication is needed so that we only allocate this string only once
// even when there are multiple calls to this function.
let tm_zone_ptr = this
.alloc_os_str_as_c_str(&OsString::from(tm_zone), MiriMemoryKind::Machine.into())?;
this.write_pointer(tm_zone_ptr, &this.project_field_named(&result, "tm_zone")?)?;
this.write_int_fields_named(&[("tm_gmtoff", tm_gmtoff.into())], &result)?;
}
Ok(result.ptr())
}
#[allow(non_snake_case, clippy::arithmetic_side_effects)]

View File

@ -1,6 +1,5 @@
//@ignore-target-windows: no libc time APIs on Windows
//@compile-flags: -Zmiri-disable-isolation
use std::ffi::CStr;
use std::{env, mem, ptr};
fn main() {
@ -64,7 +63,9 @@ fn test_localtime_r() {
tm_wday: 0,
tm_yday: 0,
tm_isdst: 0,
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
tm_gmtoff: 0,
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
tm_zone: std::ptr::null_mut::<libc::c_char>(),
};
let res = unsafe { libc::localtime_r(custom_time_ptr, &mut tm) };
@ -82,7 +83,7 @@ fn test_localtime_r() {
assert_eq!(tm.tm_gmtoff, 0);
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
unsafe {
assert_eq!(CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00")
assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00")
};
// The returned value is the pointer passed in.