From af3df0893bd39c6f9d8d6bfa519fed51330c9123 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 5 Aug 2022 02:13:41 -0700 Subject: [PATCH] Refactor gettimeofday() --- examples/gettimeofday.c | 29 ++++++++++++ libc/calls/__clock_gettime.S | 6 +-- libc/calls/__gettimeofday.S | 30 +++++++++++++ libc/calls/gettimeofday-metal.c | 24 ++++++++++ libc/calls/gettimeofday-nt.c | 9 ++-- libc/calls/gettimeofday-xnu.c | 31 +++++++++++++ libc/calls/gettimeofday.c | 78 +++++++++++++++++++++++---------- libc/calls/internal.h | 4 +- libc/calls/time.c | 16 +++++-- third_party/tidy/sprtf.c | 2 +- tool/build/lib/loader.c | 2 +- 11 files changed, 195 insertions(+), 36 deletions(-) create mode 100644 examples/gettimeofday.c create mode 100644 libc/calls/__gettimeofday.S create mode 100644 libc/calls/gettimeofday-metal.c create mode 100644 libc/calls/gettimeofday-xnu.c diff --git a/examples/gettimeofday.c b/examples/gettimeofday.c new file mode 100644 index 000000000..2e5623e0b --- /dev/null +++ b/examples/gettimeofday.c @@ -0,0 +1,29 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/assert.h" +#include "libc/calls/struct/timeval.h" +#include "libc/stdio/stdio.h" +#include "libc/time/struct/tm.h" +#include "libc/time/time.h" +#include "net/http/http.h" + +int main(int argc, char *argv[]) { + int rc; + int64_t t; + char p[30]; + struct tm tm; + struct timeval tv; + rc = gettimeofday(&tv, 0); + assert(!rc); + t = tv.tv_sec; + gmtime_r(&t, &tm); + FormatHttpDateTime(p, &tm); + printf("%s\n", p); +} diff --git a/libc/calls/__clock_gettime.S b/libc/calls/__clock_gettime.S index 3e5d052c9..85f4a79cb 100644 --- a/libc/calls/__clock_gettime.S +++ b/libc/calls/__clock_gettime.S @@ -18,13 +18,13 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" - .initbss 201,_init___clock_gettime + .initbss 301,_init___clock_gettime __clock_gettime: .quad 0 .endobj __clock_gettime,globl,hidden .previous - .init.start 201,_init___clock_gettime + .init.start 301,_init___clock_gettime ezlea __clock_gettime_init,ax stosq - .init.end 201,_init___clock_gettime + .init.end 301,_init___clock_gettime diff --git a/libc/calls/__gettimeofday.S b/libc/calls/__gettimeofday.S new file mode 100644 index 000000000..982f9a2c6 --- /dev/null +++ b/libc/calls/__gettimeofday.S @@ -0,0 +1,30 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" + + .initbss 301,_init___gettimeofday +__gettimeofday: + .quad 0 + .endobj __gettimeofday,globl,hidden + .previous + + .init.start 301,_init___gettimeofday + ezlea __gettimeofday_init,ax + stosq + .init.end 301,_init___gettimeofday diff --git a/libc/calls/gettimeofday-metal.c b/libc/calls/gettimeofday-metal.c new file mode 100644 index 000000000..0d4ba83a3 --- /dev/null +++ b/libc/calls/gettimeofday-metal.c @@ -0,0 +1,24 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/internal.h" + +axdx_t sys_gettimeofday_metal(struct timeval *tv, struct timezone *tz, + void *wut) { + return (axdx_t){-1, 0}; +} diff --git a/libc/calls/gettimeofday-nt.c b/libc/calls/gettimeofday-nt.c index 8b808db05..88a28c48f 100644 --- a/libc/calls/gettimeofday-nt.c +++ b/libc/calls/gettimeofday-nt.c @@ -16,18 +16,17 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/struct/timeval.h" +#include "libc/calls/internal.h" #include "libc/fmt/conv.h" #include "libc/nt/struct/filetime.h" -#include "libc/nt/struct/systemtime.h" #include "libc/nt/synchronization.h" #include "libc/str/str.h" -#include "libc/time/struct/timezone.h" -textwindows int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) { +textwindows axdx_t sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz, + void *wut) { struct NtFileTime ft; GetSystemTimeAsFileTime(&ft); if (tv) *tv = FileTimeToTimeVal(ft); if (tz) bzero(tz, sizeof(*tz)); - return 0; + return (axdx_t){0, 0}; } diff --git a/libc/calls/gettimeofday-xnu.c b/libc/calls/gettimeofday-xnu.c new file mode 100644 index 000000000..b9d07a267 --- /dev/null +++ b/libc/calls/gettimeofday-xnu.c @@ -0,0 +1,31 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/internal.h" + +axdx_t sys_gettimeofday_xnu(struct timeval *tv, struct timezone *tz, + void *wut) { + axdx_t ad; + ad = sys_gettimeofday(tv, tz, wut); + if (ad.ax > 0 && tv) { + tv->tv_sec = ad.ax; + tv->tv_usec = ad.dx; + ad.ax = 0; + } + return ad; +} diff --git a/libc/calls/gettimeofday.c b/libc/calls/gettimeofday.c index 5b129ec60..1dee86c96 100644 --- a/libc/calls/gettimeofday.c +++ b/libc/calls/gettimeofday.c @@ -18,52 +18,86 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/calls/internal.h" +#include "libc/calls/state.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/timeval.h" #include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" +#include "libc/intrin/describeflags.internal.h" #include "libc/sysv/errfuns.h" #include "libc/time/struct/timezone.h" #include "libc/time/time.h" -static typeof(sys_gettimeofday) *__gettimeofday = sys_gettimeofday; +typedef axdx_t gettimeofday_f(struct timeval *, struct timezone *, void *); + +extern gettimeofday_f *__gettimeofday; /** - * Returns system wall time in microseconds. + * Returns system wall time in microseconds, e.g. + * + * int64_t t; + * char p[30]; + * struct tm tm; + * struct timeval tv; + * gettimeofday(&tv, 0); + * t = tv.tv_sec; + * gmtime_r(&t, &tm); + * FormatHttpDateTime(p, &tm); + * printf("%s\n", p); * * @param tv points to timeval that receives result if non-NULL * @param tz receives UTC timezone if non-NULL + * @error EFAULT if `tv` or `tz` isn't valid memory * @see clock_gettime() for nanosecond precision * @see strftime() for string formatting */ int gettimeofday(struct timeval *tv, struct timezone *tz) { + int rc; axdx_t ad; if (IsAsan() && ((tv && !__asan_is_valid(tv, sizeof(*tv))) || (tz && !__asan_is_valid(tz, sizeof(*tz))))) { - return efault(); - } - if (!IsWindows() && !IsMetal()) { - ad = __gettimeofday(tv, tz, NULL); - assert(ad.ax != -1); - if (SupportsXnu() && ad.ax && tv) { - tv->tv_sec = ad.ax; - tv->tv_usec = ad.dx; - } - return 0; - } else if (IsMetal()) { - return enosys(); + rc = efault(); } else { - return sys_gettimeofday_nt(tv, tz); + rc = __gettimeofday(tv, tz, 0).ax; } +#if SYSDEBUG + if (!__time_critical) { + STRACE("gettimeofday([%s], %p) → %d% m", DescribeTimeval(rc, tv), tz, rc); + } +#endif + return rc; } -static textstartup void __gettimeofday_init(void) { - void *vdso; - if ((vdso = __vdsosym("LINUX_2.6", "__vdso_gettimeofday"))) { - __gettimeofday = vdso; +/** + * Returns pointer to fastest gettimeofday(). + */ +gettimeofday_f *__gettimeofday_get(bool *opt_out_isfast) { + bool isfast; + gettimeofday_f *res; + if (IsLinux() && (res = __vdsosym("LINUX_2.6", "__vdso_gettimeofday"))) { + isfast = true; + } else if (IsWindows()) { + isfast = true; + res = sys_gettimeofday_nt; + } else if (IsXnu()) { + isfast = false; + res = sys_gettimeofday_xnu; + } else if (IsMetal()) { + isfast = false; + res = sys_gettimeofday_metal; + } else { + isfast = false; + res = sys_gettimeofday; } + if (opt_out_isfast) { + *opt_out_isfast = isfast; + } + return res; } -const void *const __gettimeofday_ctor[] initarray = { - __gettimeofday_init, -}; +hidden int __gettimeofday_init(struct timeval *tv, struct timezone *tz) { + gettimeofday_f *gettime; + __gettimeofday = gettime = __gettimeofday_get(0); + return gettime(tv, tz, 0).ax; +} diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 0514ad805..e531146f7 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -157,17 +157,18 @@ void __rusage2linux(struct rusage *) hidden; void __sigenter_xnu(void *, i32, i32, struct siginfo_xnu *, struct __darwin_ucontext *) hidden; void __stat2cosmo(struct stat *restrict, const union metastat *) hidden; +axdx_t sys_gettimeofday_xnu(struct timeval *, struct timezone *, void *) hidden; /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » windows nt » veneers ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ +axdx_t sys_gettimeofday_nt(struct timeval *, struct timezone *, void *) hidden; int ioctl_tiocgwinsz_nt(struct Fd *, struct winsize *) hidden; int sys_close_nt(struct Fd *) hidden; int sys_fstat_nt(i64, struct stat *) hidden; int sys_fstatat_nt(int, const char *, struct stat *, int) hidden; int sys_getrusage_nt(int, struct rusage *) hidden; -int sys_gettimeofday_nt(struct timeval *, struct timezone *) hidden; int sys_lstat_nt(const char *, struct stat *) hidden; int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden; int sys_setitimer_nt(int, const struct itimerval *, struct itimerval *) hidden; @@ -196,6 +197,7 @@ struct NtOverlapped *_offset2overlap(int64_t, int64_t, │ cosmopolitan § syscalls » metal ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ +axdx_t sys_gettimeofday_metal(struct timeval *, struct timezone *, void *); int sys_fstat_metal(int, struct stat *); int sys_openat_metal(int, const char *, int, unsigned); ssize_t sys_readv_metal(struct Fd *, const struct iovec *, int) hidden; diff --git a/libc/calls/time.c b/libc/calls/time.c index 6fbf62d32..3d10c0aba 100644 --- a/libc/calls/time.c +++ b/libc/calls/time.c @@ -17,6 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/struct/timeval.h" +#include "libc/dce.h" +#include "libc/intrin/asan.internal.h" +#include "libc/sysv/errfuns.h" #include "libc/time/time.h" /** @@ -29,9 +32,16 @@ int64_t time(int64_t *opt_out_ret) { int64_t secs; struct timeval tv; - secs = nowl(); - if (opt_out_ret) { - *opt_out_ret = secs; + if (IsAsan() && opt_out_ret && + !__asan_is_valid(opt_out_ret, sizeof(*opt_out_ret))) { + secs = efault(); + } else if (gettimeofday(&tv, 0) != -1) { + secs = tv.tv_sec; + if (opt_out_ret) { + *opt_out_ret = secs; + } + } else { + secs = -1; } return secs; } diff --git a/third_party/tidy/sprtf.c b/third_party/tidy/sprtf.c index 1f65f7539..0dd45c5a3 100644 --- a/third_party/tidy/sprtf.c +++ b/third_party/tidy/sprtf.c @@ -172,7 +172,7 @@ void set_log_file( char * nf, int open ) } #ifdef _MSC_VER -int gettimeofday(struct timeval *tp, void *tzp) +int _gettimeofday(struct timeval *tp, void *tzp) { #ifdef WIN32 struct _timeb timebuffer; diff --git a/tool/build/lib/loader.c b/tool/build/lib/loader.c index 55021743d..5c164e44b 100644 --- a/tool/build/lib/loader.c +++ b/tool/build/lib/loader.c @@ -83,7 +83,7 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize, static void LoadElf(struct Machine *m, struct Elf *elf) { unsigned i; Elf64_Phdr *phdr; - m->ip = elf->base = elf->ehdr->e_entry; + m->ip = elf->base = 0x400000 /* elf->ehdr->e_entry */; VERBOSEF("LOADELF ENTRY %012lx", m->ip); for (i = 0; i < elf->ehdr->e_phnum; ++i) { phdr = GetElfSegmentHeaderAddress(elf->ehdr, elf->size, i);