While working on strftime I noticed some constants were being defined in
unexpected places. One thing led to another, and I ended up doing a
major cleanup of the time functions.
What's included:
All uses of <time.h> in /src and /test removed (except for LibcTest.cpp)
The various time constants have been moved to time_constants.h, and the
`time_constants` namespace.
struct tm gets its own type indirection header now.
Add a `clock_gettime` emulation layer and use it to implement the `time`
entrypoint.
For windows, the monotonic clock is emulated using `QPC`.
The realtime clock is emulated using `GetSystemTimePreciseAsFileTime`.
`timespec_get` is C standard counterpart to POSIX `clock_gettime`. On
Linux we simply use `clock_gettime`. On baremetal we introduce a new
external API `__llvm_libc_timespec_get_utc` that should be implemented
by the vendor.
This is an implementation of `ctime` and includes `ctime_r`.
According to documentation, `ctime` and `ctime_r` are defined as the
following:
```c
char *ctime(const time_t *timep);
char *ctime_r(const time_t *restrict timep, char buf[restrict 26]);
```
closes#86567
The `<time.h>` functions `asctime`, `gmtime`, `mktime` and their `_r`
variants are purely computational functions which convert between well
defined time representations and/or strings. There's no reason these
shouldn't be available in bare-metal builds of the library as well as
hosted ones: even if the library has no way to find out the time in
POSIX format, it might still see POSIX-style `time_t` values in input
data (e.g. network protocols) and need to interpret them.
The only obstacle to this was that the `out_of_range()` helper function
set `errno` to `EOVERFLOW`, which fails in a bare-metal build because
the extra POSIX error values aren't defined, including `EOVERFLOW`. So
I've made that assignment conditional on `EOVERFLOW` being defined.
Fixes#85556.
The 32-bit time_t rolls over to a value with its high bit set at
2038-01-19 03:14:07. The overflow check for this in mktime() was
checking each individual component of the time: reject if year>2038, or
if month>1, or if day>19, etc. As a result it would reject valid times
before the overflow point, because a low-order component was out of
range even though a higher-order one makes the time as a whole safe. The
earliest failing value is 2145916808 == 2038-01-01 00:00:08, in which
only the seconds field 'overflows'.
Fixed so that if any component is _less_ than its threshold value, we
don't check the lower-order components.
When crosscompiling, we need to search for the linux kernel headers in the sysroot but since #97486 the linux kernel headers were always searched in /usr/include.
This patch fixes this behaviour by prepending a '=' to where we search for the kernel headers. As per the gcc/clang's documentation a '=' before the path is replaced by the sysroot.
This patch also includes a fix for rv32, that fails to compile due to a missing definition of CLOCK_REALTIME after this change.
Summary:
This patch implements `clock_gettime` using the monotonic clock. This
allows users to get time elapsed at nanosecond resolution. This is
primarily to facilitate compiling the `chrono` library from `libc++`.
For this reason we provide both `CLOCK_MONOTONIC`, which we can
implement
with the GPU's global fixed-frequency clock, and `CLOCK_REALTIME` which
we cannot. The latter is provided just to make people who use this
header happy and it will always return failure.
Summary:
Recent patches have added solutions to the remaining sources of
divergence. This patch simply removes the last occures of things like
`has_builtin`, `ifdef` or builtins with feature requirements. The one
exception here is `nanosleep`, but I made changes in the
`__nvvm_reflect` pass to make usage like this actually work at O0.
Depends on https://github.com/llvm/llvm-project/pull/81331
Summary:
The GPU `nanosleep` tests would occasionally fail. This was due to the
fact that we used integer division to determine how many ticks we had to
sleep for. This would then truncate, leaving us with a value just
slightly below the requested value. This would then occasionally leave
us with a return value of `-1`. This patch just changes the code to
round up by 1 so we always sleep for at least the requested value.
Summary:
Recent patches have implemented builitin versions of these functions.
This patch simply removes uses of inline assembly to hopefully improve
optimizations in this area.
Summary:
The AMDGPU fixed frequency clock is fixed to a chip dependent frequency.
More modern chips have started to fix this at known values of 25 MHz or
100 MHz, so this function forwards those values. This was done using the
individual architectures. This patch simply uses the more concise
`__GFXn__` macro which indicates the major revision
Summary:
The AMDGPU architecture does not use a fixed frequency for all of its
architectures. However, the newer GPUs tend to have one that's
consistent between them (Except for Vega10). This was set up but not
actually used, so the implementation was just defaulting to whatever
value the global was being set to. Fix.
This patch changes the size of time_t to be an int64_t. This still
follows the POSIX standard which only requires time_t to be an integer.
Making time_t a 64-bit integer also fixes two cases in 32 bits platforms
that use SYS_clock_nanosleep_time64 and SYS_clock_gettime64, as the name
of these calls implies, they require a 64-bit time_t. For instance, in rv32,
the 32-bit version of these syscalls is not available.
We also follow glibc here, where time_t is still a 32-bit integer in
arm32.
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D159125
Similar to D159208, this patch unifies the calls to a syscall, in this
patch it is the syscall SYS_clock_gettime/SYS_clock_gettime64.
This patch also fixes calls to SYS_clock_gettime64 by creating a
timespec64 object, passing it to the syscall and rewriting the timespec
given by the caller with timespec64 object's contents. This fixes cases
where timespec has a 4 bytes long time_t member, but SYS_clock_gettime
is not available (e.g., rv32).
This patch fixes the overflow check in update_from_seconds, used by
gmtime, gmtime_r and mktime.
In update_from_seconds, total_seconds is a int64_t and the previous
overflow check for when sizeof(time_t) == 4 would check if it was <
0x80000000 and > 0x7FFFFFFF, however, this check would cause the
following issues:
1. Valid negative numbers would be discarded, e.g., -1 is
0xffffffffffffffff as a int64_t, outside the range of the overflow
check.
2. Some valid positive numbers would be discarded because the hex
constants were being implicitly converted to int64_t, e.g., 0x80000000
would be implicitly converted to 2147483648, instead of -2147483648.
The fix for both cases was to static_cast total_seconds and the
constants to time_t if sizeof(time_t) == 4. The behaviour is not changed
in systems with sizeof(time_t) == 8.
---------
Signed-off-by: Mikhail R. Gadelha <mikhail@igalia.com>
The GPU has the ability to sleep for very short periods of time. We can
map this to the existing `nanosleep` utility. This patch maps the
nanosleep utility to the existing hardware instructions as best as
possible.
Depends on D159118
Reviewed By: JonChesterfield, sivachandra
Differential Revision: https://reviews.llvm.org/D159225
This patch implements the `clock()` function on the GPU. This function
is supposed to return a timestamp that can be converted into seconds
using the `CLOCKS_PER_SEC` macro. The GPU has a fixed frequency timer
that can be used for this purpose. However, there are some
considerations.
First is that AMDGPU does not have a statically known fixed frequency. I
know internally that the gfx10xx and gfx11xx series use a 100 MHz clock
which will probably remain for the future. Gfx9xx typically uses a 25
MHz clock except for the Vega 10 GPU. The only way to know for sure is
to look it up from the runtime. For this purpose, I elected to default
it to some known values and assign these to an exteranlly visible symbol
that can be initialized if needed. If we do not have a good guess we
just return zero.
Second is that the `CLOCKS_PER_SEC` macro only gives about a microsecond
of resolution. POSIX demands that it's 1,000,000 so it's best that we
keep with this tradition as almost all targets seem to respect this. The
reason this is important is because on the GPU we will almost assuredly
be copying the host's macro value (see the wrapper header) so we should
go with the POSIX version that's most likely to be set. (We could
probably make a warning if the included header doesn't match the
expected value).
Reviewed By: jdoerfert
Differential Revision: https://reviews.llvm.org/D159118
This patch fixes the floating point conversion warnings found with
`-Wconversion` and `-Wno-sign-conversion`. These were the last warnings
I found, meaning that once this lands https://reviews.llvm.org/D156630
should be unblocked.
Reviewed By: mcgrathr, lntue
Differential Revision: https://reviews.llvm.org/D157449
This patch is large, but is almost entirely just adding casts to calls
to syscall_impl. Much of the work was done programatically, with human
checking when the syntax or types got confusing.
Reviewed By: mcgrathr
Differential Revision: https://reviews.llvm.org/D156950
This patch adds a bunch of ifdefs to handle the 32 bit versions of
some syscalls, which often only append a 64 to the name of the syscall
(with exception of SYS_lseek -> SYS_llseek and SYS_futex ->
SYS_futex_time64)
This patch also tries to handle cases where wait4 is not available
(as in riscv32): to implement wait, wait4 and waitpid when wait4 is
not available, we check for alternative wait calls and ultimately rely
on waitid to implement them all.
In riscv32, only waitid is available, so we need it to support this
platform.
Reviewed By: michaelrj
Differential Revision: https://reviews.llvm.org/D148371
The time functions have not yet been updated to match our new coding
patterns. This patch removes some unnecessary includes, adjusts the
names of the test targets, and adds several TODO comments. It is my
intention to follow this patch up with additional cleanup.
Reviewed By: sivachandra, rtenneti
Differential Revision: https://reviews.llvm.org/D149487
Introduce Month enum.
Use designated initializers instead of comments to ensure that tm_data
is initialized correctly. Use Month enum for initializing .tm_mon to
avoid off-by-one errors.
Co-authored-by: Raman Tenneti <rtenneti@google.com>
Reviewed By: rtenneti
Differential Revision: https://reviews.llvm.org/D144357
+ Avoid the `clockid` var and just passed `long(CLOCK_REALTIME)`
to the syscall.
Reviewed By: rtenneti
Differential Revision: https://reviews.llvm.org/D138070
+ Deleted duplicate definitions of StructTimeVal and StructTimeValPtr.
+ Caled syscall clock_gettime to get timespec data.
+ Added tests to test for sleeping 200 and 1000 microseconds.
+ Fixed comments from https://reviews.llvm.org/D137881
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D138064