Refactor gettimeofday()

This commit is contained in:
Justine Tunney 2022-08-05 02:13:41 -07:00
parent 4238e4def9
commit af3df0893b
11 changed files with 195 additions and 36 deletions

29
examples/gettimeofday.c Normal file
View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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};
}

View file

@ -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};
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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);