mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-24 03:20:30 +00:00
Refactor gettimeofday()
This commit is contained in:
parent
4238e4def9
commit
af3df0893b
11 changed files with 195 additions and 36 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue