mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Avoid long double timestamps in redbean
This commit is contained in:
parent
8d9ac3da50
commit
acdf591833
17 changed files with 431 additions and 77 deletions
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ASSERT_H_
|
||||
#define COSMOPOLITAN_LIBC_ASSERT_H_
|
||||
#include "libc/bits/likely.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -10,7 +11,7 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
|
|||
#define assert(EXPR) ((void)0)
|
||||
#else
|
||||
#define assert(EXPR) \
|
||||
((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
|
||||
((void)(LIKELY(EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
|
26
libc/calls/_timespec_eq.c
Normal file
26
libc/calls/_timespec_eq.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Checks if 𝑥 = 𝑦.
|
||||
*/
|
||||
bool _timespec_eq(struct timespec x, struct timespec y) {
|
||||
return x.tv_sec == y.tv_sec && x.tv_nsec == y.tv_nsec;
|
||||
}
|
29
libc/calls/_timespec_frommicros.c
Normal file
29
libc/calls/_timespec_frommicros.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Converts timespec interval from microseconds.
|
||||
*/
|
||||
struct timespec _timespec_frommicros(int64_t x) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = x / 1000000;
|
||||
ts.tv_nsec = x % 1000000 * 1000;
|
||||
return ts;
|
||||
}
|
29
libc/calls/_timespec_frommillis.c
Normal file
29
libc/calls/_timespec_frommillis.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Converts timespec interval from milliseconds.
|
||||
*/
|
||||
struct timespec _timespec_frommillis(int64_t x) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = x / 1000;
|
||||
ts.tv_nsec = x % 1000 * 1000000;
|
||||
return ts;
|
||||
}
|
28
libc/calls/_timespec_gte.c
Normal file
28
libc/calls/_timespec_gte.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Checks if 𝑥 ≥ 𝑦.
|
||||
*/
|
||||
bool _timespec_gte(struct timespec x, struct timespec y) {
|
||||
if (x.tv_sec > y.tv_sec) return true;
|
||||
if (x.tv_sec < y.tv_sec) return false;
|
||||
return x.tv_nsec >= y.tv_nsec;
|
||||
}
|
31
libc/calls/_timespec_mono.c
Normal file
31
libc/calls/_timespec_mono.c
Normal 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 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/assert.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
struct timespec _timespec_mono(void) {
|
||||
int ax, dx;
|
||||
struct timespec ts;
|
||||
ax = clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
|
||||
assert(!ax);
|
||||
return ts;
|
||||
}
|
31
libc/calls/_timespec_real.c
Normal file
31
libc/calls/_timespec_real.c
Normal 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 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/assert.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
struct timespec _timespec_real(void) {
|
||||
int ax, dx;
|
||||
struct timespec ts;
|
||||
ax = clock_gettime(CLOCK_REALTIME_FAST, &ts);
|
||||
assert(!ax);
|
||||
return ts;
|
||||
}
|
32
libc/calls/_timespec_tomicros.c
Normal file
32
libc/calls/_timespec_tomicros.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Converts timespec interval to microseconds.
|
||||
*/
|
||||
int64_t _timespec_tomicros(struct timespec x) {
|
||||
int64_t us;
|
||||
if (!__builtin_add_overflow(x.tv_sec, x.tv_nsec / 1000, &us)) {
|
||||
return us;
|
||||
} else {
|
||||
return INT64_MAX;
|
||||
}
|
||||
}
|
32
libc/calls/_timespec_tomillis.c
Normal file
32
libc/calls/_timespec_tomillis.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Converts timespec interval to milliseconds.
|
||||
*/
|
||||
int64_t _timespec_tomillis(struct timespec x) {
|
||||
int64_t us;
|
||||
if (!__builtin_add_overflow(x.tv_sec, x.tv_nsec / 1000000, &us)) {
|
||||
return us;
|
||||
} else {
|
||||
return INT64_MAX;
|
||||
}
|
||||
}
|
|
@ -179,6 +179,15 @@ o//libc/calls/getcwd-xnu.greg.o: \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
# we always want -O2 because:
|
||||
# division is expensive if not optimized
|
||||
o/$(MODE)/libc/calls/_timespec_tomillis.o \
|
||||
o/$(MODE)/libc/calls/_timespec_tomicros.o \
|
||||
o/$(MODE)/libc/calls/_timespec_frommillis.o \
|
||||
o/$(MODE)/libc/calls/_timespec_frommicros.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-O2
|
||||
|
||||
o/$(MODE)/libc/calls/pledge.o \
|
||||
o/$(MODE)/libc/calls/unveil.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
|
|
|
@ -8,9 +8,16 @@ struct timespec {
|
|||
};
|
||||
|
||||
int sys_futex(int *, int, int, const struct timespec *, int *);
|
||||
bool _timespec_gt(struct timespec, struct timespec);
|
||||
struct timespec _timespec_add(struct timespec, struct timespec);
|
||||
struct timespec _timespec_sub(struct timespec, struct timespec);
|
||||
int64_t _timespec_tomicros(struct timespec) pureconst;
|
||||
int64_t _timespec_tomillis(struct timespec) pureconst;
|
||||
struct timespec _timespec_frommicros(int64_t) pureconst;
|
||||
struct timespec _timespec_frommillis(int64_t) pureconst;
|
||||
bool _timespec_eq(struct timespec, struct timespec) pureconst;
|
||||
bool _timespec_gte(struct timespec, struct timespec) pureconst;
|
||||
struct timespec _timespec_add(struct timespec, struct timespec) pureconst;
|
||||
struct timespec _timespec_sub(struct timespec, struct timespec) pureconst;
|
||||
struct timespec _timespec_real(void);
|
||||
struct timespec _timespec_mono(void);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMESPEC_H_ */
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
struct timespec _timespec_add(struct timespec x, struct timespec y) {
|
||||
x.tv_sec += y.tv_sec;
|
||||
x.tv_nsec += y.tv_nsec;
|
||||
if (x.tv_nsec >= 10000000000) {
|
||||
x.tv_nsec -= 10000000000;
|
||||
if (x.tv_nsec >= 1000000000) {
|
||||
x.tv_nsec -= 1000000000;
|
||||
x.tv_sec += 1;
|
||||
}
|
||||
return x;
|
||||
|
|
|
@ -85,35 +85,39 @@ static void vflogf_onfail(FILE *f) {
|
|||
void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
||||
const char *fmt, va_list va) {
|
||||
int bufmode;
|
||||
int64_t dots;
|
||||
struct tm tm;
|
||||
long double t2;
|
||||
const char *prog;
|
||||
bool issamesecond;
|
||||
char buf32[32];
|
||||
int64_t secs, nsec, dots;
|
||||
const char *prog;
|
||||
const char *sign;
|
||||
bool issamesecond;
|
||||
struct timespec t2;
|
||||
if (!f) f = __log_file;
|
||||
if (!f) return;
|
||||
flockfile(f);
|
||||
--__strace;
|
||||
|
||||
t2 = nowl();
|
||||
secs = t2;
|
||||
nsec = (t2 - secs) * 1e9L;
|
||||
issamesecond = secs == vflogf_ts.tv_sec;
|
||||
dots = issamesecond ? nsec - vflogf_ts.tv_nsec : nsec;
|
||||
vflogf_ts.tv_sec = secs;
|
||||
vflogf_ts.tv_nsec = nsec;
|
||||
// We display TIMESTAMP.MICROS normally. However, when we log multiple
|
||||
// times in the same second, we display TIMESTAMP+DELTAMICROS instead.
|
||||
t2 = _timespec_real();
|
||||
if (t2.tv_sec == vflogf_ts.tv_sec) {
|
||||
sign = "+";
|
||||
dots = t2.tv_nsec - vflogf_ts.tv_nsec;
|
||||
} else {
|
||||
sign = ".";
|
||||
dots = t2.tv_nsec;
|
||||
}
|
||||
vflogf_ts = t2;
|
||||
|
||||
localtime_r(&secs, &tm);
|
||||
strcpy(iso8601(buf32, &tm), issamesecond ? "+" : ".");
|
||||
localtime_r(&t2.tv_sec, &tm);
|
||||
strcpy(iso8601(buf32, &tm), sign);
|
||||
prog = basename(firstnonnull(program_invocation_name, "unknown"));
|
||||
bufmode = f->bufmode;
|
||||
if (bufmode == _IOLBF) f->bufmode = _IOFBF;
|
||||
|
||||
if ((fprintf_unlocked)(f, "%r%c%s%06ld:%s:%d:%.*s:%d] ",
|
||||
"FEWIVDNT"[level & 7], buf32, dots / 1000 % 1000000,
|
||||
file, line, strchrnul(prog, '.') - prog, prog,
|
||||
getpid()) <= 0) {
|
||||
"FEWIVDNT"[level & 7], buf32, dots / 1000, file, line,
|
||||
strchrnul(prog, '.') - prog, prog, getpid()) <= 0) {
|
||||
vflogf_onfail(f);
|
||||
}
|
||||
(vfprintf_unlocked)(f, fmt, va);
|
||||
|
|
76
test/libc/calls/_timespec_test.c
Normal file
76
test/libc/calls/_timespec_test.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*-*- 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 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/calls/struct/timespec.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(_timespec_gte, test) {
|
||||
EXPECT_FALSE(_timespec_gte((struct timespec){1}, (struct timespec){2}));
|
||||
EXPECT_TRUE(_timespec_gte((struct timespec){2}, (struct timespec){2}));
|
||||
EXPECT_TRUE(_timespec_gte((struct timespec){2}, (struct timespec){1}));
|
||||
EXPECT_FALSE(_timespec_gte((struct timespec){2}, (struct timespec){2, 1}));
|
||||
EXPECT_TRUE(_timespec_gte((struct timespec){2, 1}, (struct timespec){2}));
|
||||
}
|
||||
|
||||
TEST(_timespec_sub, test) {
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){-1},
|
||||
_timespec_sub((struct timespec){1}, (struct timespec){2})));
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){1},
|
||||
_timespec_sub((struct timespec){2}, (struct timespec){1})));
|
||||
EXPECT_TRUE(_timespec_eq(
|
||||
(struct timespec){1, 1},
|
||||
_timespec_sub((struct timespec){2, 2}, (struct timespec){1, 1})));
|
||||
EXPECT_TRUE(_timespec_eq(
|
||||
(struct timespec){0, 999999999},
|
||||
_timespec_sub((struct timespec){2, 1}, (struct timespec){1, 2})));
|
||||
}
|
||||
|
||||
TEST(_timespec_frommillis, test) {
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){0, 1000000}, _timespec_frommillis(1)));
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){0, 2000000}, _timespec_frommillis(2)));
|
||||
EXPECT_TRUE(_timespec_eq((struct timespec){1}, _timespec_frommillis(1000)));
|
||||
}
|
||||
|
||||
TEST(_timespec_frommicros, test) {
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){0, 1000}, _timespec_frommicros(1)));
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){0, 2000}, _timespec_frommicros(2)));
|
||||
EXPECT_TRUE(
|
||||
_timespec_eq((struct timespec){1}, _timespec_frommicros(1000000)));
|
||||
}
|
||||
|
||||
static long mod(long x, long y) {
|
||||
if (y == -1) return 0;
|
||||
return x - y * (x / y - (x % y && (x ^ y) < 0));
|
||||
}
|
||||
|
||||
TEST(_timespec_sub, math) {
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
struct timespec x = {mod(lemur64(), 10), mod(lemur64(), 10)};
|
||||
struct timespec y = {mod(lemur64(), 10), mod(lemur64(), 10)};
|
||||
struct timespec z = _timespec_add(_timespec_sub(x, y), y);
|
||||
EXPECT_TRUE(_timespec_eq(x, _timespec_add(_timespec_sub(x, y), y)));
|
||||
}
|
||||
}
|
|
@ -55,6 +55,7 @@ BENCH(clock_gettime, bench) {
|
|||
EZBENCH2("nowl", donothing, nowl());
|
||||
EZBENCH2("rdtsc", donothing, rdtsc());
|
||||
EZBENCH2("gettimeofday", donothing, gettimeofday(&tv, 0));
|
||||
EZBENCH2("_timespec_real", donothing, _timespec_real());
|
||||
EZBENCH2("clock_gettime 0", donothing,
|
||||
clock_gettime(CLOCK_REALTIME_FAST, &ts));
|
||||
EZBENCH2("clock_gettime 1", donothing,
|
||||
|
|
|
@ -1374,9 +1374,10 @@ FUNCTIONS
|
|||
as Content-Range and Date, which are abstracted by the transport
|
||||
layer.
|
||||
|
||||
ProgramHeartbeatInterval(milliseconds:int)
|
||||
Sets the heartbeat interval (in milliseconds). 5000ms is the default
|
||||
and 100ms is the minimum.
|
||||
ProgramHeartbeatInterval([milliseconds:int])
|
||||
Sets the heartbeat interval (in milliseconds). 5000ms is the
|
||||
default and 100ms is the minimum. If `milliseconds` is not
|
||||
specified, then the current interval is returned.
|
||||
|
||||
ProgramTimeout(milliseconds:int|seconds:int)
|
||||
Default timeout is 60000ms. Minimal value of timeout is 10(ms).
|
||||
|
|
|
@ -328,9 +328,9 @@ static struct Assets {
|
|||
|
||||
static struct Shared {
|
||||
int workers;
|
||||
long double nowish;
|
||||
long double lastreindex;
|
||||
long double lastmeltdown;
|
||||
struct timespec nowish;
|
||||
struct timespec lastreindex;
|
||||
struct timespec lastmeltdown;
|
||||
char currentdate[32];
|
||||
struct rusage server;
|
||||
struct rusage children;
|
||||
|
@ -430,7 +430,6 @@ static int sslpskindex;
|
|||
static int oldloglevel;
|
||||
static int messageshandled;
|
||||
static int sslticketlifetime;
|
||||
static int heartbeatint = 5000; // ms
|
||||
static uint32_t clientaddrsize;
|
||||
|
||||
static size_t zsize;
|
||||
|
@ -470,16 +469,17 @@ static struct Buffer oldin;
|
|||
static struct Buffer hdrbuf;
|
||||
static struct timeval timeout;
|
||||
static struct Buffer effectivepath;
|
||||
static struct timespec heartbeatinterval;
|
||||
|
||||
static struct Url url;
|
||||
|
||||
static struct stat zst;
|
||||
static long double startread;
|
||||
static long double lastrefresh;
|
||||
static long double startserver;
|
||||
static long double startrequest;
|
||||
static long double lastheartbeat;
|
||||
static long double startconnection;
|
||||
static struct timespec startread;
|
||||
static struct timespec lastrefresh;
|
||||
static struct timespec startserver;
|
||||
static struct timespec startrequest;
|
||||
static struct timespec lastheartbeat;
|
||||
static struct timespec startconnection;
|
||||
static struct sockaddr_in clientaddr;
|
||||
static struct sockaddr_in *serveraddr;
|
||||
|
||||
|
@ -1314,6 +1314,11 @@ static ssize_t ReadAll(int fd, char *p, size_t n) {
|
|||
return i;
|
||||
}
|
||||
|
||||
static bool IsTakingTooLong(void) {
|
||||
return meltdown && _timespec_gte(_timespec_sub(_timespec_real(), startread),
|
||||
(struct timespec){2});
|
||||
}
|
||||
|
||||
static ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) {
|
||||
int i;
|
||||
ssize_t rc;
|
||||
|
@ -1340,7 +1345,7 @@ static ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) {
|
|||
} else if (errno == EINTR) {
|
||||
errno = 0;
|
||||
LockInc(&shared->c.writeinterruputs);
|
||||
if (killed || (meltdown && nowl() - startread > 2)) {
|
||||
if (killed || IsTakingTooLong()) {
|
||||
return total ? total : -1;
|
||||
}
|
||||
} else {
|
||||
|
@ -1556,7 +1561,6 @@ static void CertsDestroy(void) {
|
|||
|
||||
static void WipeServingKeys(void) {
|
||||
size_t i;
|
||||
long double t = nowl();
|
||||
if (uniprocess) return;
|
||||
mbedtls_ssl_ticket_free(&ssltick);
|
||||
mbedtls_ssl_key_cert_free(conf.key_cert), conf.key_cert = 0;
|
||||
|
@ -1675,7 +1679,7 @@ static bool TlsSetup(void) {
|
|||
return true;
|
||||
} else if (r == MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
LockInc(&shared->c.handshakeinterrupts);
|
||||
if (terminated || killed || (meltdown && nowl() - startread > 2)) {
|
||||
if (terminated || killed || IsTakingTooLong()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -1935,10 +1939,10 @@ char *FormatUnixHttpDateTime(char *s, int64_t t) {
|
|||
return s;
|
||||
}
|
||||
|
||||
static void UpdateCurrentDate(long double now) {
|
||||
static void UpdateCurrentDate(struct timespec now) {
|
||||
int64_t t;
|
||||
struct tm tm;
|
||||
t = now;
|
||||
t = now.tv_sec;
|
||||
shared->nowish = now;
|
||||
gmtime_r(&t, &tm);
|
||||
FormatHttpDateTime(shared->currentdate, &tm);
|
||||
|
@ -2169,7 +2173,7 @@ static char *AppendCache(char *p, int64_t seconds) {
|
|||
p = stpcpy(p, ", must-revalidate");
|
||||
}
|
||||
p = AppendCrlf(p);
|
||||
return AppendExpires(p, (int64_t)shared->nowish + seconds);
|
||||
return AppendExpires(p, shared->nowish.tv_sec + seconds);
|
||||
}
|
||||
|
||||
static inline char *AppendContentLength(char *p, size_t n) {
|
||||
|
@ -2923,7 +2927,7 @@ td { padding-right: 3em; }\r\n\
|
|||
}
|
||||
appends(&cpm.outbuf, "<td valign=\"top\">\r\n");
|
||||
and = "";
|
||||
x = nowl() - startserver;
|
||||
x = _timespec_sub(_timespec_real(), startserver).tv_sec;
|
||||
y = ldiv(x, 24L * 60 * 60);
|
||||
if (y.quot) {
|
||||
appendf(&cpm.outbuf, "%,ld day%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
|
@ -3012,12 +3016,12 @@ static char *ServeStatusz(void) {
|
|||
}
|
||||
AppendLong1("pid", getpid());
|
||||
AppendLong1("ppid", getppid());
|
||||
AppendLong1("now", nowl());
|
||||
AppendLong1("nowish", shared->nowish);
|
||||
AppendLong1("now", _timespec_real().tv_sec);
|
||||
AppendLong1("nowish", shared->nowish.tv_sec);
|
||||
AppendLong1("gmtoff", gmtoff);
|
||||
AppendLong1("CLK_TCK", CLK_TCK);
|
||||
AppendLong1("startserver", startserver);
|
||||
AppendLong1("lastmeltdown", shared->lastmeltdown);
|
||||
AppendLong1("startserver", startserver.tv_sec);
|
||||
AppendLong1("lastmeltdown", shared->lastmeltdown.tv_sec);
|
||||
AppendLong1("workers", shared->workers);
|
||||
AppendLong1("assets.n", assets.n);
|
||||
#ifndef STATIC
|
||||
|
@ -3436,7 +3440,7 @@ static void StoreAsset(char *path, size_t pathlen, char *data, size_t datalen,
|
|||
int i;
|
||||
uint32_t crc;
|
||||
char *comp, *p;
|
||||
long double now;
|
||||
struct timespec now;
|
||||
struct Asset *a;
|
||||
struct iovec v[13];
|
||||
uint8_t *cdir, era;
|
||||
|
@ -3479,14 +3483,14 @@ static void StoreAsset(char *path, size_t pathlen, char *data, size_t datalen,
|
|||
return;
|
||||
}
|
||||
OpenZip(false);
|
||||
now = nowl();
|
||||
now = _timespec_real();
|
||||
a = GetAssetZip(path, pathlen);
|
||||
if (!mode) mode = a ? GetMode(a) : 0644;
|
||||
if (!(mode & S_IFMT)) mode |= S_IFREG;
|
||||
if (pathlen > 1 && path[0] == '/') ++path, --pathlen;
|
||||
dosmode = !(mode & 0200) ? kNtFileAttributeReadonly : 0;
|
||||
ft = (now + MODERNITYSECONDS) * HECTONANOSECONDS;
|
||||
GetDosLocalTime(now, &mtime, &mdate);
|
||||
ft = (now.tv_sec + MODERNITYSECONDS) * HECTONANOSECONDS;
|
||||
GetDosLocalTime(now.tv_sec, &mtime, &mdate);
|
||||
// local file header
|
||||
if (uselen >= 0xffffffff || datalen >= 0xffffffff) {
|
||||
era = kZipEra2001;
|
||||
|
@ -4169,7 +4173,7 @@ VerifyFailed:
|
|||
}
|
||||
|
||||
static int LuaGetDate(lua_State *L) {
|
||||
lua_pushinteger(L, shared->nowish);
|
||||
lua_pushinteger(L, shared->nowish.tv_sec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -4753,12 +4757,14 @@ static int LuaProgramUniprocess(lua_State *L) {
|
|||
}
|
||||
|
||||
static int LuaProgramHeartbeatInterval(lua_State *L) {
|
||||
int64_t millis;
|
||||
OnlyCallFromMainProcess(L, "ProgramHeartbeatInterval");
|
||||
if (!lua_isinteger(L, 1) && !lua_isnoneornil(L, 1)) {
|
||||
return luaL_argerror(L, 1, "invalid heartbeat interval; integer expected");
|
||||
if (!lua_isnoneornil(L, 1)) {
|
||||
millis = luaL_checkinteger(L, 1);
|
||||
millis = MAX(100, millis);
|
||||
heartbeatinterval = _timespec_frommillis(millis);
|
||||
}
|
||||
lua_pushinteger(L, heartbeatint);
|
||||
if (lua_isinteger(L, 1)) heartbeatint = MAX(100, lua_tointeger(L, 1));
|
||||
lua_pushinteger(L, _timespec_tomillis(heartbeatinterval));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -5634,10 +5640,13 @@ Content-Length: 0\r\n\
|
|||
}
|
||||
|
||||
static void EnterMeltdownMode(void) {
|
||||
if (shared->lastmeltdown && nowl() - shared->lastmeltdown < 1) return;
|
||||
if (shared->lastmeltdown.tv_sec &&
|
||||
!_timespec_gte(_timespec_sub(_timespec_real(), shared->lastmeltdown),
|
||||
(struct timespec){1}))
|
||||
return;
|
||||
WARNF("(srvr) server is melting down (%,d workers)", shared->workers);
|
||||
LOGIFNEG1(kill(0, SIGUSR2));
|
||||
shared->lastmeltdown = nowl();
|
||||
shared->lastmeltdown = _timespec_real();
|
||||
++shared->c.meltdowns;
|
||||
}
|
||||
|
||||
|
@ -5767,8 +5776,7 @@ static void HandleReload(void) {
|
|||
static void HandleHeartbeat(void) {
|
||||
size_t i;
|
||||
sigset_t mask;
|
||||
if (nowl() - lastrefresh > 60 * 60) RefreshTime();
|
||||
UpdateCurrentDate(nowl());
|
||||
UpdateCurrentDate(_timespec_real());
|
||||
Reindex();
|
||||
getrusage(RUSAGE_SELF, &shared->server);
|
||||
#ifndef STATIC
|
||||
|
@ -5866,7 +5874,9 @@ static char *ReadMore(void) {
|
|||
amtread += got;
|
||||
} else if (errno == EINTR) {
|
||||
LockInc(&shared->c.readinterrupts);
|
||||
if (killed || ((meltdown || terminated) && nowl() - startread > 1)) {
|
||||
if (killed || ((meltdown || terminated) &&
|
||||
_timespec_gte(_timespec_sub(_timespec_real(), startread),
|
||||
(struct timespec){1}))) {
|
||||
return HandlePayloadDrop();
|
||||
}
|
||||
} else {
|
||||
|
@ -6347,7 +6357,7 @@ static bool HandleMessageActual(void) {
|
|||
int rc;
|
||||
long reqtime, contime;
|
||||
char *p;
|
||||
long double now;
|
||||
struct timespec now;
|
||||
if ((rc = ParseHttpMessage(&cpm.msg, inbuf.p, amtread)) != -1) {
|
||||
if (!rc) return false;
|
||||
hdrsize = rc;
|
||||
|
@ -6387,9 +6397,9 @@ static bool HandleMessageActual(void) {
|
|||
p = stpcpy(p, "\r\n");
|
||||
}
|
||||
if (loglatency || LOGGABLE(kLogDebug) || hasonloglatency) {
|
||||
now = nowl();
|
||||
reqtime = (long)((now - startrequest) * 1e6L);
|
||||
contime = (long)((now - startconnection) * 1e6L);
|
||||
now = _timespec_real();
|
||||
reqtime = _timespec_tomicros(_timespec_sub(now, startrequest));
|
||||
contime = _timespec_tomicros(_timespec_sub(now, startconnection));
|
||||
if (hasonloglatency) LuaOnLogLatency(reqtime, contime);
|
||||
if (loglatency || LOGGABLE(kLogDebug))
|
||||
LOGF(kLogDebug, "(stat) %`'.*s latency r: %,ldµs c: %,ldµs",
|
||||
|
@ -6431,14 +6441,14 @@ static void HandleMessages(void) {
|
|||
size_t got;
|
||||
for (once = false;;) {
|
||||
InitRequest();
|
||||
startread = nowl();
|
||||
startread = _timespec_real();
|
||||
for (;;) {
|
||||
if (!cpm.msg.i && amtread) {
|
||||
startrequest = nowl();
|
||||
startrequest = _timespec_real();
|
||||
if (HandleMessage()) break;
|
||||
}
|
||||
if ((rc = reader(client, inbuf.p + amtread, inbuf.n - amtread)) != -1) {
|
||||
startrequest = nowl();
|
||||
startrequest = _timespec_real();
|
||||
got = rc;
|
||||
amtread += got;
|
||||
if (amtread) {
|
||||
|
@ -6496,7 +6506,10 @@ static void HandleMessages(void) {
|
|||
return;
|
||||
}
|
||||
if (killed || (terminated && !amtread) ||
|
||||
(meltdown && (!amtread || nowl() - startread > 1))) {
|
||||
(meltdown &&
|
||||
(!amtread ||
|
||||
_timespec_gte(_timespec_sub(_timespec_real(), startread),
|
||||
(struct timespec){1})))) {
|
||||
if (amtread) {
|
||||
LockInc(&shared->c.dropped);
|
||||
SendServiceUnavailable();
|
||||
|
@ -6754,7 +6767,7 @@ static int HandleConnection(size_t i) {
|
|||
clientaddrsize = sizeof(clientaddr);
|
||||
if ((client = accept4(servers.p[i].fd, &clientaddr, &clientaddrsize,
|
||||
SOCK_CLOEXEC)) != -1) {
|
||||
startconnection = nowl();
|
||||
startconnection = _timespec_real();
|
||||
if (UNLIKELY(maxworkers) && shared->workers >= maxworkers) {
|
||||
EnterMeltdownMode();
|
||||
SendServiceUnavailable();
|
||||
|
@ -6807,8 +6820,9 @@ static int HandleConnection(size_t i) {
|
|||
CloseServerFds();
|
||||
}
|
||||
HandleMessages();
|
||||
DEBUGF("(stat) %s closing after %,ldµs", DescribeClient(),
|
||||
(long)((nowl() - startconnection) * 1e6L));
|
||||
DEBUGF(
|
||||
"(stat) %s closing after %,ldµs", DescribeClient(),
|
||||
_timespec_tomicros(_timespec_sub(_timespec_real(), startconnection)));
|
||||
if (!pid) {
|
||||
if (hasonworkerstop) {
|
||||
CallSimpleHook("OnWorkerStop");
|
||||
|
@ -7087,7 +7101,7 @@ static void HandleShutdown(void) {
|
|||
|
||||
// this function coroutines with linenoise
|
||||
static int EventLoop(int ms) {
|
||||
long double t;
|
||||
struct timespec t;
|
||||
DEBUGF("(repl) event loop");
|
||||
while (!terminated) {
|
||||
errno = 0;
|
||||
|
@ -7105,7 +7119,9 @@ static int EventLoop(int ms) {
|
|||
EnterMeltdownMode();
|
||||
lua_repl_unlock();
|
||||
meltdown = false;
|
||||
} else if ((t = nowl()) - lastheartbeat > heartbeatint / 1000.) {
|
||||
} else if (_timespec_gte(
|
||||
_timespec_sub((t = _timespec_real()), lastheartbeat),
|
||||
heartbeatinterval)) {
|
||||
lastheartbeat = t;
|
||||
HandleHeartbeat();
|
||||
} else if (HandlePoll(ms) == -1) {
|
||||
|
@ -7341,8 +7357,9 @@ void RedBean(int argc, char *argv[]) {
|
|||
}
|
||||
reader = read;
|
||||
writer = WritevAll;
|
||||
gmtoff = GetGmtOffset((lastrefresh = startserver = nowl()));
|
||||
gmtoff = GetGmtOffset((lastrefresh = startserver = _timespec_real()).tv_sec);
|
||||
mainpid = getpid();
|
||||
heartbeatinterval.tv_sec = 5;
|
||||
CHECK_GT(CLK_TCK, 0);
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE),
|
||||
|
@ -7392,7 +7409,7 @@ void RedBean(int argc, char *argv[]) {
|
|||
close(fd);
|
||||
}
|
||||
ChangeUser();
|
||||
UpdateCurrentDate(nowl());
|
||||
UpdateCurrentDate(_timespec_real());
|
||||
CollectGarbage();
|
||||
hdrbuf.n = 4 * 1024;
|
||||
hdrbuf.p = xmalloc(hdrbuf.n);
|
||||
|
@ -7410,12 +7427,12 @@ void RedBean(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
#ifdef STATIC
|
||||
EventLoop(heartbeatint);
|
||||
EventLoop(_timespec_tomillis(heartbeatinterval));
|
||||
#else
|
||||
GetHostsTxt(); // for effect
|
||||
GetResolvConf(); // for effect
|
||||
if (daemonize || uniprocess || !linenoiseIsTerminal()) {
|
||||
EventLoop(heartbeatint);
|
||||
EventLoop(_timespec_tomillis(heartbeatinterval));
|
||||
} else if (IsWindows()) {
|
||||
CHECK_NE(-1, _spawn(WindowsReplThread, 0, &replth));
|
||||
EventLoop(100);
|
||||
|
|
Loading…
Reference in a new issue