Make numerous improvements

- Python static hello world now 1.8mb
- Python static fully loaded now 10mb
- Python HTTPS client now uses MbedTLS
- Python REPL now completes import stmts
- Increase stack size for Python for now
- Begin synthesizing posixpath and ntpath
- Restore Python \N{UNICODE NAME} support
- Restore Python NFKD symbol normalization
- Add optimized code path for Intel SHA-NI
- Get more Python unit tests passing faster
- Get Python help() pagination working on NT
- Python hashlib now supports MbedTLS PBKDF2
- Make memcpy/memmove/memcmp/bcmp/etc. faster
- Add Mersenne Twister and Vigna to LIBC_RAND
- Provide privileged __printf() for error code
- Fix zipos opendir() so that it reports ENOTDIR
- Add basic chmod() implementation for Windows NT
- Add Cosmo's best functions to Python cosmo module
- Pin function trace indent depth to that of caller
- Show memory diagram on invalid access in MODE=dbg
- Differentiate stack overflow on crash in MODE=dbg
- Add stb_truetype and tools for analyzing font files
- Upgrade to UNICODE 13 and reduce its binary footprint
- COMPILE.COM now logs resource usage of build commands
- Start implementing basic poll() support on bare metal
- Set getauxval(AT_EXECFN) to GetModuleFileName() on NT
- Add descriptions to strerror() in non-TINY build modes
- Add COUNTBRANCH() macro to help with micro-optimizations
- Make error / backtrace / asan / memory code more unbreakable
- Add fast perfect C implementation of μ-Law and a-Law audio codecs
- Make strtol() functions consistent with other libc implementations
- Improve Linenoise implementation (see also github.com/jart/bestline)
- COMPILE.COM now suppresses stdout/stderr of successful build commands
This commit is contained in:
Justine Tunney 2021-09-27 22:58:51 -07:00
parent fa7b4f5bd1
commit 39bf41f4eb
806 changed files with 77494 additions and 63859 deletions

View file

@ -10,19 +10,21 @@ COSMOPOLITAN_C_START_
*/
#ifndef BENCHLOOP
#define BENCHLOOP(START, STOP, N, INIT, EXPR) \
({ \
unsigned long Iter, Count; \
uint64_t Time1, Time2; \
double Average; \
for (Average = 1, Iter = 1, Count = (N); Iter < Count; ++Iter) { \
INIT; \
Time1 = START(); \
EXPR; \
Time2 = STOP(); \
Average += 1. / Iter * (unsignedsubtract(Time2, Time1) - Average); \
} \
Average; \
#define BENCHLOOP(START, STOP, N, INIT, EXPR) \
({ \
unsigned long Iter, Count; \
uint64_t Time1, Time2; \
double Average; \
for (Average = 1, Iter = 1, Count = (N); Iter < Count; ++Iter) { \
INIT; \
Time1 = START(); \
asm volatile("" ::: "memory"); \
EXPR; \
asm volatile("" ::: "memory"); \
Time2 = STOP(); \
Average += 1. / Iter * ((int)unsignedsubtract(Time2, Time1) - Average); \
} \
Average; \
})
#endif /* BENCHLOOP */

View file

@ -1,37 +1,193 @@
#ifndef COSMOPOLITAN_LIBC_TESTLIB_EZBENCH_H_
#define COSMOPOLITAN_LIBC_TESTLIB_EZBENCH_H_
#include "libc/macros.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/sysv/consts/clock.h"
#include "libc/testlib/bench.h"
#include "libc/testlib/testlib.h"
#include "libc/time/time.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define EZBENCH(INIT, EXPR) EZBENCH2(#EXPR, INIT, EXPR)
#ifndef __STRICT_ANSI__
#define EZBENCH2(NAME, INIT, EXPR) \
do { \
uint64_t Control, Speculative, MemoryStrict; \
Control = __testlib_ezbenchcontrol(); \
INIT; \
EXPR; \
Speculative = BENCHLOOP(__startbench, __endbench, 128, INIT, (EXPR)); \
MemoryStrict = BENCHLOOP(__startbench_m, __endbench_m, 8, ({ \
INIT; \
thrashcodecache(); \
}), \
(EXPR)); \
Control = MIN(Control, MIN(Speculative, MemoryStrict)); \
__testlib_ezbenchreport(NAME, Speculative - Control, \
MemoryStrict - Control); \
#define EZBENCH2(NAME, INIT, EXPR) \
do { \
int Core, Tries, Interrupts; \
int64_t Speculative, MemoryStrict; \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
INIT; \
EXPR; \
Speculative = BENCHLOOP(__startbench, __endbench, 128, ({ \
INIT; \
polluteregisters(); \
}), \
(EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" speculative"); \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
INIT; \
EXPR; \
MemoryStrict = BENCHLOOP(__startbench_m, __endbench_m, 32, ({ \
INIT; \
thrashcodecache(); \
polluteregisters(); \
}), \
(EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" memory strict"); \
__testlib_ezbenchreport( \
NAME, MAX(0, Speculative - __testlib_ezbenchcontrol()), \
MAX(0, MemoryStrict - __testlib_ezbenchcontrol())); \
} while (0)
#else
#define EZBENCH2(NAME, INIT, EXPR) \
do { \
} while (0)
#endif
#define EZBENCH3(NAME, NUM, INIT, EXPR) \
do { \
int Core, Tries, Interrupts; \
int64_t Speculative, MemoryStrict; \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
INIT; \
EXPR; \
Speculative = BENCHLOOP(__startbench, __endbench, NUM, ({ \
INIT; \
polluteregisters(); \
}), \
(EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" speculative"); \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
INIT; \
EXPR; \
MemoryStrict = BENCHLOOP(__startbench_m, __endbench_m, NUM, ({ \
INIT; \
thrashcodecache(); \
polluteregisters(); \
}), \
(EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" memory strict"); \
__testlib_ezbenchreport( \
NAME, MAX(0, Speculative - __testlib_ezbenchcontrol()), \
MAX(0, MemoryStrict - __testlib_ezbenchcontrol())); \
} while (0)
#define EZBENCH_C(NAME, CONTROL, EXPR) \
do { \
int Core, Tries, Interrupts; \
int64_t Control, Speculative, MemoryStrict; \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
Control = BENCHLOOP(__startbench_m, __endbench_m, 128, ({ \
thrashcodecache(); \
polluteregisters(); \
}), \
(CONTROL)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" control"); \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
EXPR; \
Speculative = BENCHLOOP(__startbench, __endbench, 128, \
polluteregisters(), (EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" speculative"); \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
EXPR; \
MemoryStrict = BENCHLOOP(__startbench_m, __endbench_m, 8, ({ \
thrashcodecache(); \
polluteregisters(); \
}), \
(EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(" memory strict"); \
__testlib_ezbenchreport(NAME, MAX(0, Speculative - Control), \
MAX(0, MemoryStrict - Control)); \
} while (0)
#define EZBENCH_N(NAME, N, EXPR) \
do { \
int64_t Speculative, Toto; \
int Core, Tries, Interrupts; \
Tries = 0; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
Interrupts = __testlib_getinterrupts(); \
EXPR; \
Speculative = \
BENCHLOOP(__startbench, __endbench, 32, polluteregisters(), (EXPR)); \
} while (++Tries < 10 && (__testlib_getcore() != Core && \
__testlib_getinterrupts() > Interrupts)); \
if (Tries == 10) __testlib_ezbenchwarn(""); \
__testlib_ezbenchreport_n( \
NAME, 'n', N, MAX(0, Speculative - __testlib_ezbenchcontrol())); \
} while (0)
#define EZBENCH_K(NAME, K, EXPR) \
do { \
int Core; \
int64_t Speculative; \
do { \
__testlib_yield(); \
Core = __testlib_getcore(); \
EXPR; \
Speculative = \
BENCHLOOP(__startbench, __endbench, 128, donothing, (EXPR)); \
} while (Core != __testlib_getcore()); \
__testlib_ezbenchreport_n( \
NAME, 'k', K, MAX(0, Speculative - __testlib_ezbenchcontrol())); \
} while (0)
void polluteregisters(void);
void __testlib_yield(void);
int __testlib_getcore(void);
int64_t __testlib_getinterrupts(void);
int64_t __testlib_ezbenchcontrol(void);
void __testlib_ezbenchwarn(const char *);
void __testlib_ezbenchreport(const char *, uint64_t, uint64_t);
uint64_t __testlib_ezbenchcontrol(void);
void __testlib_ezbenchreport_n(const char *, char, size_t, uint64_t);
#ifdef __STRICT_ANSI__
#undef EZBENCH2
#undef EZBENCH3
#undef EZBENCH_N
#undef EZBENCH_K
#define EZBENCH2(NAME, INIT, EXPR) (void)0
#define EZBENCH3(NAME, NUM, INIT, EXPR) (void)0
#define EZBENCH_N(NAME, N, EXPR) (void)0
#define EZBENCH_K(NAME, K, EXPR) (void)0
#endif
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TESTLIB_EZBENCH_H_ */

View file

@ -16,9 +16,31 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/testlib/bench.h"
#include "libc/stdio/stdio.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
uint64_t __testlib_ezbenchcontrol(void) {
return BENCHLOOP(__startbench, __endbench, 128, donothing, (void)0);
static bool once;
static int64_t g_ezbenchcontrol;
int64_t __testlib_ezbenchcontrol(void) {
if (!once) {
int Core, Tries, Interrupts;
Tries = 0;
do {
__testlib_yield();
Core = __testlib_getcore();
Interrupts = __testlib_getinterrupts();
g_ezbenchcontrol =
BENCHLOOP(__startbench, __endbench, 128, donothing, (void)0);
} while (++Tries < 10 && (__testlib_getcore() != Core &&
__testlib_getinterrupts() > Interrupts));
if (Tries == 10) {
fputs("warning: failed to accurately benchmark control\n", stderr);
}
fprintf(stderr, "will subtract benchmark overhead of %ld cycles\n\n",
g_ezbenchcontrol);
once = true;
}
return g_ezbenchcontrol;
}

View file

@ -16,10 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/fmt.h"
#include "libc/math.h"
#include "libc/runtime/gc.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/testlib/testlib.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
STATIC_YOINK("strnwidth");
@ -27,6 +30,57 @@ void __testlib_ezbenchreport(const char *form, uint64_t c1, uint64_t c2) {
uint64_t ns1, ns2;
ns1 = rintl(ConvertTicksToNanos(c1));
ns2 = rintl(ConvertTicksToNanos(c2));
(fprintf)(stderr, VEIL("r", "%-26s l: %,9lu𝑐 %,9lu𝑛𝑠 m: %,9lu𝑐 %,9lu𝑛𝑠\n"),
(fprintf)(stderr,
VEIL("r", " * %-19s l: %,9lu𝑐 %,9lu𝑛𝑠 m: %,9lu𝑐 %,9lu𝑛𝑠\n"),
form, c1, ns1, c2, ns2);
}
void __testlib_ezbenchreport_n(const char *form, char z, size_t n, uint64_t c) {
char msg[128];
uint64_t bps;
long double cn, lat;
(snprintf)(msg, sizeof(msg), "%s %c=%d", form, z, n);
cn = ConvertTicksToNanos(c);
if (!n) {
(fprintf)(stderr, "\n");
(fprintf)(stderr, " * %-28s", msg);
if (cn < 1) {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)(cn * 1024),
"picoseconds");
} else if (cn > 1024) {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)(cn / 1024),
"microseconds");
} else {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)cn, "nanoseconds");
}
} else {
(fprintf)(stderr, " * %-28s", msg);
bps = n / cn * 1e9;
lat = cn / n;
if (lat < 1e-3) {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)(lat * 1024 * 1024),
"fs/byte");
} else if (lat < 1) {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)(lat * 1024),
"ps/byte");
} else if (lat > 1024) {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)(lat / 1024),
"µs/byte");
} else {
(fprintf)(stderr, VEIL("r", " %,9lu %-12s"), (int64_t)lat, "ns/byte");
}
if (bps < 10 * 1000) {
(fprintf)(stderr, VEIL("r", " %,9lu b/s"), bps);
} else if (bps < 10 * 1000 * 1024) {
(fprintf)(stderr, VEIL("r", " %,9lu kb/s"), bps / 1024);
} else if (bps < 10ul * 1000 * 1024 * 1024) {
(fprintf)(stderr, VEIL("r", " %,9lu mb/s"), bps / (1024 * 1024));
} else if (bps < 10ul * 1000 * 1024 * 1024 * 1024) {
(fprintf)(stderr, VEIL("r", " %,9lu GB/s"), bps / (1024 * 1024 * 1024));
} else {
(fprintf)(stderr, VEIL("r", " %,9lu TB/s"),
bps / (1024ul * 1024 * 1024 * 1024));
}
}
(fprintf)(stderr, "\n", form);
}

View 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 2021 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/stdio/stdio.h"
#include "libc/testlib/testlib.h"
void __testlib_ezbenchwarn(const char *msg) {
fputs("warning: failed to accurately benchmark", stderr);
fputs(msg, stderr);
fputc('\n', stderr);
}

26
libc/testlib/getcore.c Normal file
View 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 2021 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/nexgen32e/rdtscp.h"
#include "libc/testlib/ezbench.h"
int __testlib_getcore(void) {
long tscaux;
tscaux = rdpid();
return TSC_AUX_CORE(tscaux);
}

View file

@ -0,0 +1,34 @@
/*-*- 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 2021 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/calls.h"
#include "libc/calls/struct/rusage.h"
#include "libc/sysv/consts/rusage.h"
#include "libc/testlib/testlib.h"
/**
* Returns involuntary context switch count for process.
*/
int64_t __testlib_getinterrupts(void) {
struct rusage ru;
if (getrusage(RUSAGE_SELF, &ru) != -1) {
return ru.ru_nivcsw;
} else {
return 0;
}
}

View file

@ -0,0 +1,95 @@
/*-*- 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 2021 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/nexgen32e/x86feature.h"
#include "libc/macros.internal.h"
polluteregisters:
.leafprologue
xor %eax,%eax
mov %ecx,%ecx
mov %edx,%edx
mov %r8d,%r8d
mov %r9d,%r9d
mov %r10d,%r10d
mov %r11d,%r11d
testb X86_HAVE(AVX)+kCpuids(%rip)
jz .Lsse
vpxor %xmm0,%xmm0,%xmm0
vpxor %xmm1,%xmm1,%xmm1
vpxor %xmm2,%xmm2,%xmm2
vpxor %xmm3,%xmm3,%xmm3
vpxor %xmm4,%xmm4,%xmm4
vpxor %xmm5,%xmm5,%xmm5
vpxor %xmm6,%xmm6,%xmm6
vpxor %xmm7,%xmm7,%xmm7
.leafepilogue
.Lsse: xorps %xmm0,%xmm0
xorps %xmm1,%xmm1
xorps %xmm2,%xmm2
xorps %xmm3,%xmm3
xorps %xmm4,%xmm4
xorps %xmm5,%xmm5
xorps %xmm6,%xmm6
xorps %xmm7,%xmm7
.leafepilogue
.endfn polluteregisters,globl
.end
// Fill registers with junk data to create false dependencies.
// Which shall create the problem that happens w/o vzeroupper.
// Or the Core Architecture errata regarding BSR/BSF w/ 64bit.
polluteregisters:
.leafprologue
mov $-1,%rax
mov %rax,%rcx
mov %rax,%rdx
mov %rax,%r8
mov %rax,%r9
mov %rax,%r10
mov %rax,%r11
movq %rax,%xmm0
testb X86_HAVE(AVX)+kCpuids(%rip)
jz .Lsse
vmovq %r8,%xmm0
vmovq %r9,%xmm1
vmovq %r10,%xmm2
vmovq %r11,%xmm3
vmovq %r12,%xmm4
vmovq %r13,%xmm5
vmovq %r14,%xmm6
vmovq %r15,%xmm7
vinsertf128 $0x1,%xmm0,%ymm0,%ymm0
vinsertf128 $0x1,%xmm1,%ymm1,%ymm1
vinsertf128 $0x1,%xmm2,%ymm2,%ymm2
vinsertf128 $0x1,%xmm3,%ymm3,%ymm3
vinsertf128 $0x1,%xmm4,%ymm4,%ymm4
vinsertf128 $0x1,%xmm5,%ymm5,%ymm5
vinsertf128 $0x1,%xmm6,%ymm6,%ymm6
vinsertf128 $0x1,%xmm7,%ymm7,%ymm7
.leafepilogue
.Lsse: punpcklqdq %xmm0,%xmm0
punpcklqdq %xmm0,%xmm1
punpcklqdq %xmm0,%xmm2
punpcklqdq %xmm0,%xmm3
punpcklqdq %xmm0,%xmm4
punpcklqdq %xmm0,%xmm5
punpcklqdq %xmm0,%xmm6
punpcklqdq %xmm0,%xmm7
.leafepilogue
.endfn polluteregisters,globl

129
libc/testlib/quota.c Normal file
View file

@ -0,0 +1,129 @@
/*-*- 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 2021 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/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/sigbits.h"
#include "libc/errno.h"
#include "libc/log/internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#include "third_party/dlmalloc/dlmalloc.internal.h"
static noasan relegated uint64_t CountMappedBytes(void) {
size_t i;
uint64_t x, y;
for (x = i = 0; i < _mmi.i; ++i) {
y = _mmi.p[i].y - _mmi.p[i].x;
x += (y + 1) << 16;
}
return x;
}
static relegated void DieBecauseOfQuota(char *p, int rc, const char *message) {
int e;
char hostname[32];
e = errno;
__restore_tty(2);
__stpcpy(hostname, "unknown");
gethostname(hostname, sizeof(hostname));
p = __stpcpy(p, message);
p = __stpcpy(p, " on ");
p = __stpcpy(p, hostname);
p = __stpcpy(p, " pid ");
p = __intcpy(p, __getpid());
p = __stpcpy(p, "\n");
__write(__fatalbuf, p - __fatalbuf);
PrintBacktraceUsingSymbols(2, 0, GetSymbolTable());
exit(rc);
}
static relegated void OnXcpu(int sig) {
DieBecauseOfQuota(__fatalbuf, 23, "\n\nSIGXCPU: ran out of cpu");
}
static relegated void OnXfsz(int sig) {
DieBecauseOfQuota(__fatalbuf, 25, "\n\nSIGXFSZ: exceeded maximum file size");
}
relegated void __oom_hook(size_t request) {
int e;
char *p;
uint64_t toto, newlim;
struct MallocStats stats;
e = errno;
p = __fatalbuf;
toto = CountMappedBytes();
stats = dlmalloc_stats(g_dlmalloc);
p = __stpcpy(p, "\n");
p = __stpcpy(p, "\n");
p = __stpcpy(p, "WE REQUIRE MORE VESPENE GAS");
if (e != ENOMEM) {
p = __stpcpy(p, " (");
p = __stpcpy(p, strerror(e));
p = __stpcpy(p, ")");
}
p = __stpcpy(p, "\n");
p = __stpcpy(p, "mmap last request = ");
p = __intcpy(p, request);
p = __stpcpy(p, "\n");
p = __stpcpy(p, "mmapped system bytes = ");
p = __intcpy(p, toto);
p = __stpcpy(p, "\n");
p = __stpcpy(p, "malloc max system bytes = ");
p = __intcpy(p, stats.maxfp);
p = __stpcpy(p, "\n");
p = __stpcpy(p, "malloc system bytes = ");
p = __intcpy(p, stats.fp);
p = __stpcpy(p, "\n");
p = __stpcpy(p, "malloc in use bytes = ");
p = __intcpy(p, stats.used);
p = __stpcpy(p, "\n");
p = __stpcpy(p, "\n");
if (IsRunningUnderMake()) {
newlim = toto + request;
newlim += newlim >> 1;
newlim = roundup2pow(newlim);
p = __stpcpy(p, "FIX CODE OR TUNE QUOTA += -M");
p = __intcpy(p, newlim / (1024 * 1024));
p = __stpcpy(p, "m\n");
}
p = __stpcpy(p, "\n");
p = __stpcpy(p, "THE STRAW THAT BROKE THE CAMEL'S BACK\n");
DieBecauseOfQuota(p, 42, "MAP_FAILED: exceeded memory quota");
}
static textstartup void InstallQuotaHandlers(void) {
struct sigaction sa;
sa.sa_flags = 0;
sa.sa_handler = OnXcpu;
sigemptyset(&sa.sa_mask);
sigaction(SIGXCPU, &sa, 0);
sa.sa_handler = OnXfsz;
sigaction(SIGXFSZ, &sa, 0);
GetSymbolTable(); /* for effect in case we oom */
}
const void *const testlib_quota_handlers[] initarray = {
InstallQuotaHandlers,
};

View file

@ -16,35 +16,130 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/fmt/fmt.h"
#include "libc/log/color.internal.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/math.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/log/libfatal.internal.h"
#include "libc/testlib/testlib.h"
const char *testlib_showerror_errno;
const char *testlib_showerror_file;
const char *testlib_showerror_func;
const char *testlib_showerror_isfatal;
const char *testlib_showerror_macro;
const char *testlib_showerror_symbol;
testonly void testlib_showerror(const char *file, int line, const char *func,
const char *method, const char *symbol,
const char *code, char *v1, char *v2) {
char *p;
/* TODO(jart): Pay off tech debt re duplication */
sys_getpid(); /* make strace easier to read */
sys_getpid();
fprintf(stderr,
"%s%s%s%s:%s:%d%s: %s() %s %s(%s)\n"
"\t%s\n"
"\t\t%s %s %s\n"
"\t\t%s %s\n"
"\t%s%s\n"
"\t%s%s\n",
RED2, "error", UNBOLD, BLUE1, file, line, RESET, method, "in", func,
g_fixturename, code, "need", v1, symbol, " got", v2, SUBTLE,
strerror(errno), program_invocation_name, RESET);
__getpid(); /* make strace easier to read */
__getpid();
p = __fatalbuf;
p = __stpcpy(p, RED2);
p = __stpcpy(p, "error");
p = __stpcpy(p, UNBOLD);
p = __stpcpy(p, BLUE1);
p = __stpcpy(p, ":");
p = __stpcpy(p, file);
p = __stpcpy(p, ":");
p = __intcpy(p, line);
p = __stpcpy(p, RESET);
p = __stpcpy(p, ": ");
p = __stpcpy(p, method);
p = __stpcpy(p, "() in ");
p = __stpcpy(p, func);
p = __stpcpy(p, "(");
p = __stpcpy(p, g_fixturename);
p = __stpcpy(p, ")\n\t");
p = __stpcpy(p, code);
p = __stpcpy(p, "\n\t\tneed ");
p = __stpcpy(p, v1);
p = __stpcpy(p, " ");
p = __stpcpy(p, symbol);
p = __stpcpy(p, "\n\t\t got ");
p = __stpcpy(p, v2);
p = __stpcpy(p, "\n\t");
p = __stpcpy(p, SUBTLE);
p = __stpcpy(p, strerror(errno));
p = __stpcpy(p, "\n\t");
p = __stpcpy(p, program_invocation_name);
p = __stpcpy(p, RESET);
p = __stpcpy(p, "\n");
__write(__fatalbuf, p - __fatalbuf);
free_s(&v1);
free_s(&v2);
}
/* TODO(jart): Pay off tech debt re duplication */
testonly void testlib_showerror_(int line, const char *wantcode,
const char *gotcode, char *FREED_want,
char *FREED_got, const char *fmt, ...) {
int e;
char *p;
va_list va;
char hostname[32];
__getpid();
__getpid();
p = __fatalbuf;
e = errno;
p = __stpcpy(p, RED2);
p = __stpcpy(p, "error");
p = __stpcpy(p, UNBOLD);
p = __stpcpy(p, ":");
p = __stpcpy(p, BLUE1);
p = __stpcpy(p, testlib_showerror_file);
p = __stpcpy(p, ":");
p = __intcpy(p, line);
p = __stpcpy(p, RESET);
p = __stpcpy(p, ": ");
p = __stpcpy(p, testlib_showerror_func);
p = __stpcpy(p, "(");
p = __stpcpy(p, g_fixturename);
p = __stpcpy(p, ")\n\t");
p = __stpcpy(p, testlib_showerror_macro);
p = __stpcpy(p, "(");
p = __stpcpy(p, wantcode);
p = __stpcpy(p, ", ");
p = __stpcpy(p, gotcode);
if (wantcode) {
p = __stpcpy(p, ")\n\t\tneed ");
p = __stpcpy(p, FREED_want);
p = __stpcpy(p, " ");
p = __stpcpy(p, testlib_showerror_symbol);
p = __stpcpy(p, "\n\t\t got ");
p = __stpcpy(p, FREED_got);
p = __stpcpy(p, "\n");
} else {
p = __stpcpy(p, ")\n\t\t");
p = __stpcpy(p, testlib_showerror_symbol);
p = __stpcpy(p, FREED_want);
p = __stpcpy(p, "\n");
}
if (!isempty(fmt)) {
*p++ = '\t';
va_start(va, fmt);
p += vsprintf(p, fmt, va);
va_end(va);
*p++ = '\n';
}
__stpcpy(hostname, "unknown");
gethostname(hostname, sizeof(hostname));
p = __stpcpy(p, "\t");
p = __stpcpy(p, SUBTLE);
p = __stpcpy(p, strerror(e));
p = __stpcpy(p, RESET);
p = __stpcpy(p, "\n\t");
p = __stpcpy(p, SUBTLE);
p = __stpcpy(p, program_invocation_name);
p = __stpcpy(p, " @ ");
p = __stpcpy(p, hostname);
p = __stpcpy(p, RESET);
p = __stpcpy(p, "\n");
__write(__fatalbuf, p - __fatalbuf);
free_s(&FREED_want);
free_s(&FREED_got);
++g_testlib_failed;
if (testlib_showerror_isfatal) testlib_abort();
}

View file

@ -1,96 +0,0 @@
/*-*- 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/bits/safemacros.internal.h"
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/color.internal.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/math.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
const char *testlib_showerror_errno;
const char *testlib_showerror_file;
const char *testlib_showerror_func;
const char *testlib_showerror_isfatal;
const char *testlib_showerror_macro;
const char *testlib_showerror_symbol;
testonly void testlib_showerror_(int line, const char *wantcode,
const char *gotcode, char *FREED_want,
char *FREED_got, const char *fmt, ...) {
int err;
va_list va;
char hostname[32];
err = errno;
/* make strace easier to read */
getpid();
getpid();
fflush(stdout);
fflush(stderr);
/* TODO(jart): Pay off tech debt re duplication */
fprintf(stderr, "%s%s%s%s:%s:%d%s: %s(%s)\n\t%s(%s", RED2, "error", UNBOLD,
BLUE1, testlib_showerror_file, line, RESET, testlib_showerror_func,
g_fixturename, testlib_showerror_macro, wantcode);
if (wantcode) {
fprintf(stderr,
", %s)\n"
"\t\t%s %s %s\n"
"\t\t%s %s\n",
gotcode, "need", FREED_want, testlib_showerror_symbol, " got",
FREED_got);
} else {
fprintf(stderr,
", %s)\n"
"\t\t→ %s%s\n",
gotcode, testlib_showerror_symbol, FREED_want);
}
if (!isempty(fmt)) {
fputc('\t', stderr);
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
fputc('\n', stderr);
}
strcpy(hostname, "unknown");
gethostname(hostname, sizeof(hostname));
fprintf(stderr,
"\t%s%s%s\n"
"\t%s%s @ %s%s\n",
SUBTLE, strerror(err), RESET, SUBTLE, program_invocation_name,
hostname, RESET);
free_s(&FREED_want);
free_s(&FREED_got);
++g_testlib_failed;
if (testlib_showerror_isfatal) testlib_abort();
}

View file

@ -35,6 +35,7 @@ LIBC_TESTLIB_A_SRCS_S = \
libc/testlib/moby.S \
libc/testlib/testcase.S \
libc/testlib/thrashcodecache.S \
libc/testlib/polluteregisters.S \
libc/testlib/thunks/assert_eq.S \
libc/testlib/thunks/assert_false.S \
libc/testlib/thunks/assert_ne.S \
@ -49,11 +50,16 @@ LIBC_TESTLIB_A_SRCS_S = \
LIBC_TESTLIB_A_SRCS_C = \
libc/testlib/almostequallongdouble.c \
libc/testlib/benchrunner.c \
libc/testlib/getcore.c \
libc/testlib/getinterrupts.c \
libc/testlib/ezbenchwarn.c \
libc/testlib/binequals.c \
libc/testlib/quota.c \
libc/testlib/clearxmmregisters.c \
libc/testlib/comborunner.c \
libc/testlib/contains.c \
libc/testlib/endswith.c \
libc/testlib/yield.c \
libc/testlib/ezbenchcontrol.c \
libc/testlib/ezbenchreport.c \
libc/testlib/fixturerunner.c \
@ -69,7 +75,6 @@ LIBC_TESTLIB_A_SRCS_C = \
libc/testlib/incrementfailed.c \
libc/testlib/shoulddebugbreak.c \
libc/testlib/showerror.c \
libc/testlib/showerror_.c \
libc/testlib/startswith.c \
libc/testlib/strcaseequals.c \
libc/testlib/strequals.c \
@ -86,6 +91,7 @@ LIBC_TESTLIB_A_OBJS = \
LIBC_TESTLIB_A_DIRECTDEPS = \
LIBC_ALG \
LIBC_BITS \
LIBC_CALLS \
LIBC_FMT \
LIBC_INTRIN \
@ -98,12 +104,14 @@ LIBC_TESTLIB_A_DIRECTDEPS = \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X \
LIBC_ZIPOS \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GDTOA
LIBC_TESTLIB_A_DEPS := \

View file

@ -18,14 +18,18 @@
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/testlib.h"
#include "third_party/dlmalloc/dlmalloc.internal.h"
#include "third_party/getopt/getopt.h"
#define USAGE \
@ -38,17 +42,18 @@ Flags:\n\
\n"
STATIC_YOINK("__die");
STATIC_YOINK("testlib_quota_handlers");
static bool runbenchmarks_;
static testonly void PrintUsage(int rc, FILE *f) {
void PrintUsage(int rc, FILE *f) {
fputs("Usage: ", f);
fputs(program_invocation_name, f);
fputs(USAGE, f);
exit(rc);
}
static testonly void GetOpts(int argc, char *argv[]) {
void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?hbv")) != -1) {
switch (opt) {
@ -70,7 +75,7 @@ static testonly void GetOpts(int argc, char *argv[]) {
/**
* Generic test program main function.
*/
testonly int main(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
const char *comdbg;
__log_level = kLogInfo;
GetOpts(argc, argv);
@ -81,6 +86,9 @@ testonly int main(int argc, char *argv[]) {
testlib_runalltests();
if (!g_testlib_failed && runbenchmarks_ && weaken(testlib_runallbenchmarks)) {
weaken(testlib_runallbenchmarks)();
if (!g_testlib_failed) {
return 254; /* compile.com considers this 0 and propagates output */
}
}
return min(255, g_testlib_failed);
}

View file

@ -19,14 +19,17 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/process.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
@ -48,8 +51,12 @@ wontreturn void testlib_abort(void) {
}
static void SetupTmpDir(void) {
snprintf(g_testlib_tmpdir, sizeof(g_testlib_tmpdir), "o/tmp/%s.%d.%d",
program_invocation_short_name, getpid(), x++);
char *p = g_testlib_tmpdir;
p = __stpcpy(p, "o/tmp/");
p = __stpcpy(p, program_invocation_short_name), *p++ = '.';
p = __intcpy(p, __getpid()), *p++ = '.';
p = __intcpy(p, x++);
p[0] = '\0';
CHECK_NE(-1, makedirs(g_testlib_tmpdir, 0755), "%s", g_testlib_tmpdir);
CHECK_EQ(1, isdirectory(g_testlib_tmpdir), "%s", g_testlib_tmpdir);
CHECK_NOTNULL(realpath(g_testlib_tmpdir, g_testlib_tmpdir), "%`'s",

View file

@ -27,12 +27,17 @@ thrashcodecache:
xor %eax,%eax
xor %ecx,%ecx
cpuid
// pushpop 4,%rcx
0: .rept 32768/(8+9)
.byte 0x0f,0x1f,0x84,0,0,0,0,0 # fat nop x8
.byte 0x66,0x0f,0x1f,0x84,0,0,0,0,0 # fat nop x9
add %r9,%r8
// Generate 32kb of junk code clobbering r8,r9,r10,r11
i = 0xdeadbeef
0: .rept 32768/(3+7)
rex.wrb
.byte 0001|(i&030) # ADD/OR/... Evqp Gvqp
.byte 0300|(i&033) # %r8-%r11 to %r8-%r11
.byte 0x49,0x81,0360|(i&003) # XOR immed32,%r8-%r11
.long i
i = ((i * 1103515245 + 12345) >> 16) & 0xffffffff
.endr
// loop 0b
xor %eax,%eax
xor %ecx,%ecx
cpuid

24
libc/testlib/yield.c Normal file
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 2021 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/calls.h"
#include "libc/testlib/ezbench.h"
void __testlib_yield(void) {
sched_yield();
}