-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Instant + Duration
produce wrong result on aarch64-apple-darwin
#91417
Comments
@rustbot label +T-libs +O-macos +O-arm |
Seems related to the time resolution difference on Apple M1, cc https://eclecticlight.co/2020/09/08/changing-the-clock-in-apple-silicon-macs/ |
The reason for this behavior is that
|
So is it considered a bug? Should we round 41 ns up to 1? |
Thought about this some more. We allow those operations:
That can't be changed, so simple arithmetic identities such as i0 + (i1 - i0) == i1 should hold if there is no overflow. In particular because the current behavior leads to real bugs. The only way to achieve this is IMHO to change the internal representation for cc @thomcc What do you think? |
We should do this, but I'm not sure we can do it everywhere — We can certainly do it on macOS+aarch64 targets though, since those should always have it. |
This seems pretty severe. I'm a novice contributor, but I do have an M1 device if there's anything I can do to aid the development of a fix here. Also, should this get some sort of I-prioritize doohickey? |
But the documentation says:
So the consequence would seem that we can any range and precision limitations from the underlying type and thus rounding errors are part of the API? I don't see the benefit of it, but it's documented. |
It is documented for Instant, yes. But we do allow arithmetic operations (+/-) between Duration and Instant leading to those problems, that - at minimum - violate the principle of the least surprise. It is exacerbated by the fact that Linux, Windows and macOS x86-64 (de facto because numer and denom are both 1) Instants all use nanosecond resolution. We should just use Footnotes |
It tried to use https://github.com/lyinch/rust/blob/issue-91417-fix/library/std/src/sys/unix/time.rs#L154 I also added a test which still fails:
I'm not sure how to correctly get typedef enum {
_CLOCK_REALTIME __CLOCK_AVAILABILITY = 0,
#define CLOCK_REALTIME _CLOCK_REALTIME
_CLOCK_MONOTONIC __CLOCK_AVAILABILITY = 6,
#define CLOCK_MONOTONIC _CLOCK_MONOTONIC
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
_CLOCK_MONOTONIC_RAW __CLOCK_AVAILABILITY = 4,
#define CLOCK_MONOTONIC_RAW _CLOCK_MONOTONIC_RAW
_CLOCK_MONOTONIC_RAW_APPROX __CLOCK_AVAILABILITY = 5,
#define CLOCK_MONOTONIC_RAW_APPROX _CLOCK_MONOTONIC_RAW_APPROX
_CLOCK_UPTIME_RAW __CLOCK_AVAILABILITY = 8,
#define CLOCK_UPTIME_RAW _CLOCK_UPTIME_RAW
_CLOCK_UPTIME_RAW_APPROX __CLOCK_AVAILABILITY = 9,
#define CLOCK_UPTIME_RAW_APPROX _CLOCK_UPTIME_RAW_APPROX
#endif
_CLOCK_PROCESS_CPUTIME_ID __CLOCK_AVAILABILITY = 12,
#define CLOCK_PROCESS_CPUTIME_ID _CLOCK_PROCESS_CPUTIME_ID
_CLOCK_THREAD_CPUTIME_ID __CLOCK_AVAILABILITY = 16
#define CLOCK_THREAD_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID
} clockid_t; Note that this enum uses #if !defined(_DARWIN_FEATURE_CLOCK_GETTIME) || _DARWIN_FEATURE_CLOCK_GETTIME != 0
#if __DARWIN_C_LEVEL >= 199309L
#if __has_feature(enumerator_attributes)
#define __CLOCK_AVAILABILITY __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
#else
#define __CLOCK_AVAILABILITY
#endif and possibly: https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html |
@lyinch That can't work, because you are still adjusting the value returned by Also this can only be done for macOS aarch64 where it is always available. It just occurred to me that we don't even need to use |
The test passes now with your proposed changes: lyinch@f9f0c97 |
Macos aarch64 clock uptime const This will add the constant `CLOCK_UPTIME_RAW` from `time.h` on macos apple silicon. I don't know if the same constant also exists for other systems, so I put it into the most specific file. Background is this issue: rust-lang/rust#91417 which might need the constant. On my machine, it is defined as: ```C typedef enum { _CLOCK_REALTIME __CLOCK_AVAILABILITY = 0, #define CLOCK_REALTIME _CLOCK_REALTIME _CLOCK_MONOTONIC __CLOCK_AVAILABILITY = 6, #define CLOCK_MONOTONIC _CLOCK_MONOTONIC #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) _CLOCK_MONOTONIC_RAW __CLOCK_AVAILABILITY = 4, #define CLOCK_MONOTONIC_RAW _CLOCK_MONOTONIC_RAW _CLOCK_MONOTONIC_RAW_APPROX __CLOCK_AVAILABILITY = 5, #define CLOCK_MONOTONIC_RAW_APPROX _CLOCK_MONOTONIC_RAW_APPROX _CLOCK_UPTIME_RAW __CLOCK_AVAILABILITY = 8, #define CLOCK_UPTIME_RAW _CLOCK_UPTIME_RAW _CLOCK_UPTIME_RAW_APPROX __CLOCK_AVAILABILITY = 9, #define CLOCK_UPTIME_RAW_APPROX _CLOCK_UPTIME_RAW_APPROX #endif _CLOCK_PROCESS_CPUTIME_ID __CLOCK_AVAILABILITY = 12, #define CLOCK_PROCESS_CPUTIME_ID _CLOCK_PROCESS_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID __CLOCK_AVAILABILITY = 16 #define CLOCK_THREAD_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID } clockid_t; ``` I ran the tests in `libc-test` : ``` % cargo test Compiling libc v0.2.118 (/Users/backes/dev/libc) Compiling libc-test v0.2.118 (/Users/backes/dev/libc/libc-test) Finished test [unoptimized + debuginfo] target(s) in 10.40s Running test/cmsg.rs (/Users/backes/dev/libc/target/debug/deps/cmsg-1a9cf9acb3bfd606) running 5 tests test t::test_cmsg_firsthdr ... ok test t::test_cmsg_data ... ok test t::test_cmsg_space ... ok test t::test_cmsg_len ... ok test t::test_cmsg_nxthdr ... ok test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.32s Running test/errqueue.rs (/Users/backes/dev/libc/target/debug/deps/errqueue-34a57aa145f73969) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running test/linux_elf.rs (/Users/backes/dev/libc/target/debug/deps/linux_elf-0d81190c35086f0f) PASSED 0 tests Running test/linux_fcntl.rs (/Users/backes/dev/libc/target/debug/deps/linux_fcntl-35043d47b0ba1ab8) PASSED 0 tests Running test/linux_if_arp.rs (/Users/backes/dev/libc/target/debug/deps/linux_if_arp-7d13a47b02694998) PASSED 0 tests Running test/linux_ipv6.rs (/Users/backes/dev/libc/target/debug/deps/linux_ipv6-019e5b7c295e467b) PASSED 0 tests Running test/linux_strerror_r.rs (/Users/backes/dev/libc/target/debug/deps/linux_strerror_r-177f4ad6f4f31457) PASSED 0 tests Running test/linux_termios.rs (/Users/backes/dev/libc/target/debug/deps/linux_termios-0ef27e1d55afb4db) PASSED 0 tests Running test/main.rs (/Users/backes/dev/libc/target/debug/deps/main-112b28ce12de7d4b) RUNNING ALL TESTS PASSED 13288 tests Running test/semver.rs (/Users/backes/dev/libc/target/debug/deps/semver-e9e1e170582c8b37) PASSED 1 tests Running test/sigrt.rs (/Users/backes/dev/libc/target/debug/deps/sigrt-13dc29f6aa83ea4c) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ```
Macos aarch64 clock uptime const This will add the constant `CLOCK_UPTIME_RAW` from `time.h` on macos apple silicon. I don't know if the same constant also exists for other systems, so I put it into the most specific file. Background is this issue: rust-lang/rust#91417 which might need the constant. On my machine, it is defined as: ```C typedef enum { _CLOCK_REALTIME __CLOCK_AVAILABILITY = 0, #define CLOCK_REALTIME _CLOCK_REALTIME _CLOCK_MONOTONIC __CLOCK_AVAILABILITY = 6, #define CLOCK_MONOTONIC _CLOCK_MONOTONIC #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) _CLOCK_MONOTONIC_RAW __CLOCK_AVAILABILITY = 4, #define CLOCK_MONOTONIC_RAW _CLOCK_MONOTONIC_RAW _CLOCK_MONOTONIC_RAW_APPROX __CLOCK_AVAILABILITY = 5, #define CLOCK_MONOTONIC_RAW_APPROX _CLOCK_MONOTONIC_RAW_APPROX _CLOCK_UPTIME_RAW __CLOCK_AVAILABILITY = 8, #define CLOCK_UPTIME_RAW _CLOCK_UPTIME_RAW _CLOCK_UPTIME_RAW_APPROX __CLOCK_AVAILABILITY = 9, #define CLOCK_UPTIME_RAW_APPROX _CLOCK_UPTIME_RAW_APPROX #endif _CLOCK_PROCESS_CPUTIME_ID __CLOCK_AVAILABILITY = 12, #define CLOCK_PROCESS_CPUTIME_ID _CLOCK_PROCESS_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID __CLOCK_AVAILABILITY = 16 #define CLOCK_THREAD_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID } clockid_t; ``` I ran the tests in `libc-test` : ``` % cargo test Compiling libc v0.2.118 (/Users/backes/dev/libc) Compiling libc-test v0.2.118 (/Users/backes/dev/libc/libc-test) Finished test [unoptimized + debuginfo] target(s) in 10.40s Running test/cmsg.rs (/Users/backes/dev/libc/target/debug/deps/cmsg-1a9cf9acb3bfd606) running 5 tests test t::test_cmsg_firsthdr ... ok test t::test_cmsg_data ... ok test t::test_cmsg_space ... ok test t::test_cmsg_len ... ok test t::test_cmsg_nxthdr ... ok test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.32s Running test/errqueue.rs (/Users/backes/dev/libc/target/debug/deps/errqueue-34a57aa145f73969) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running test/linux_elf.rs (/Users/backes/dev/libc/target/debug/deps/linux_elf-0d81190c35086f0f) PASSED 0 tests Running test/linux_fcntl.rs (/Users/backes/dev/libc/target/debug/deps/linux_fcntl-35043d47b0ba1ab8) PASSED 0 tests Running test/linux_if_arp.rs (/Users/backes/dev/libc/target/debug/deps/linux_if_arp-7d13a47b02694998) PASSED 0 tests Running test/linux_ipv6.rs (/Users/backes/dev/libc/target/debug/deps/linux_ipv6-019e5b7c295e467b) PASSED 0 tests Running test/linux_strerror_r.rs (/Users/backes/dev/libc/target/debug/deps/linux_strerror_r-177f4ad6f4f31457) PASSED 0 tests Running test/linux_termios.rs (/Users/backes/dev/libc/target/debug/deps/linux_termios-0ef27e1d55afb4db) PASSED 0 tests Running test/main.rs (/Users/backes/dev/libc/target/debug/deps/main-112b28ce12de7d4b) RUNNING ALL TESTS PASSED 13288 tests Running test/semver.rs (/Users/backes/dev/libc/target/debug/deps/semver-e9e1e170582c8b37) PASSED 1 tests Running test/sigrt.rs (/Users/backes/dev/libc/target/debug/deps/sigrt-13dc29f6aa83ea4c) running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ```
Issue rust-lang#91417 fix This is a regression test and a fixes rust-lang#91417 It also bumps the libc version to 0.2.119 because it requires the constant introduced here: rust-lang/libc#2689
Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Note that this change was made for aarch64 in 5008a31 which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang#91417 and in particular rust-lang#91417 (comment) and rust-lang#91417 (comment) are relevant. It's not clear from reading that thread why CLOCK_UPTIME_RAW was used rather than CLOCK_MONOTONIC. The latter is now used.
Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Note that this change was made for aarch64 in 5008a31 which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang#91417 and in particular rust-lang#91417 (comment) and rust-lang#91417 (comment) are relevant. It's not clear from reading that thread why `CLOCK_UPTIME_RAW` was used rather than `CLOCK_MONOTONIC`. The latter is now used.
Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Note that this change was made for aarch64 in 5008a31 which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang#91417 and in particular rust-lang#91417 (comment) and rust-lang#91417 (comment) are relevant. It's not clear from reading that thread why `CLOCK_UPTIME_RAW` was used rather than `CLOCK_MONOTONIC`. The latter is now used.
Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Note that this change was made for aarch64 in 5008a31 which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang#91417 and in particular rust-lang#91417 (comment) and rust-lang#91417 (comment) are relevant.
time: use clock_gettime on macos Replace `gettimeofday` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `gettimeofday` was first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Note that this change was made for aarch64 in 5008a31 which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang#91417 and in particular rust-lang#91417 (comment) and rust-lang#91417 (comment) are relevant.
time: use clock_gettime on macos Replace `gettimeofday` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `gettimeofday` was first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Note that this change was made for aarch64 in 5008a317ce8e508c390ed12bff281f307313376e which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang/rust#91417 and in particular rust-lang/rust#91417 (comment) and rust-lang/rust#91417 (comment) are relevant.
time: use clock_gettime on macos Replace `gettimeofday` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `gettimeofday` was first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Note that this change was made for aarch64 in 5008a317ce8e508c390ed12bff281f307313376e which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang/rust#91417 and in particular rust-lang/rust#91417 (comment) and rust-lang/rust#91417 (comment) are relevant.
time: use clock_gettime on macos Replace `gettimeofday` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `gettimeofday` was first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Note that this change was made for aarch64 in 5008a317ce8e508c390ed12bff281f307313376e which predated 10.12 becoming the minimum supported version. The discussion took place in rust-lang/rust#91417 and in particular rust-lang/rust#91417 (comment) and rust-lang/rust#91417 (comment) are relevant.
I tried this code on M1 macOS:
It's expected to succeed.
Instead, this happened:
It seems that there is something wrong with the
Duration -> Instant
casting in Rust std:rust/library/std/src/sys/unix/time.rs
Lines 227 to 232 in 1d6f242
This problem does not exist on x86_64-apple-darwin, because
info.denom = info.numer = 1
.Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: