mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-02 23:18:44 +00:00
Make mappings unlimited on NT
This change might also fix fork() in certain cases on NT.
This commit is contained in:
parent
ab64c746cc
commit
34b68f1945
31 changed files with 356 additions and 127 deletions
24
examples/defer-statements.c
Normal file
24
examples/defer-statements.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#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/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Cosmopolitan C is just as awesome as Go!
|
||||
* Example contributed by @Keithcat1 (#266)
|
||||
*/
|
||||
main() {
|
||||
_defer(printf, "Done!\n");
|
||||
for (long i = 0; i < 100000; i++) {
|
||||
printf("%i ", i);
|
||||
_defer(free, malloc(100)); // longhand for _gc(malloc(100))
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/dns/hoststxt.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
@ -70,10 +71,12 @@ const struct HostsTxt *GetHostsTxt(void) {
|
|||
if (IsWindows()) {
|
||||
path = firstnonnull(GetNtHostsTxtPath(pathbuf, ARRAYLEN(pathbuf)), path);
|
||||
}
|
||||
if (!(f = fopen(path, "r")) || ParseHostsTxt(g_hoststxt, f) == -1) {
|
||||
/* TODO(jart): Elevate robustness. */
|
||||
if (fileexists(path) && (f = fopen(path, "r"))) {
|
||||
if (ParseHostsTxt(g_hoststxt, f) == -1) {
|
||||
/* TODO(jart): Elevate robustness. */
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
return g_hoststxt;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
|
|
@ -1,2 +1,12 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp kernel32,__imp_GlobalAlloc,GlobalAlloc,0
|
||||
|
||||
.text.windows
|
||||
GlobalAlloc:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_GlobalAlloc(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn GlobalAlloc,globl
|
||||
.previous
|
||||
|
|
|
@ -1,2 +1,15 @@
|
|||
.include "o/libc/nt/codegen.inc"
|
||||
.imp kernel32,__imp_GlobalFree,GlobalFree,0
|
||||
|
||||
.text.windows
|
||||
GlobalFree:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov %rdi,%rcx
|
||||
sub $32,%rsp
|
||||
call *__imp_GlobalFree(%rip)
|
||||
leave
|
||||
ret
|
||||
.endfn GlobalFree,globl
|
||||
.previous
|
||||
|
|
|
@ -2785,14 +2785,14 @@ imp 'GlobalAddAtomA' GlobalAddAtomA kernel32 815
|
|||
imp 'GlobalAddAtomExA' GlobalAddAtomExA kernel32 816
|
||||
imp 'GlobalAddAtomEx' GlobalAddAtomExW kernel32 817
|
||||
imp 'GlobalAddAtom' GlobalAddAtomW kernel32 818
|
||||
imp 'GlobalAlloc' GlobalAlloc kernel32 0 # KernelBase
|
||||
imp 'GlobalAlloc' GlobalAlloc kernel32 0 2 # KernelBase
|
||||
imp 'GlobalCompact' GlobalCompact kernel32 820
|
||||
imp 'GlobalDeleteAtom' GlobalDeleteAtom kernel32 821
|
||||
imp 'GlobalFindAtomA' GlobalFindAtomA kernel32 822
|
||||
imp 'GlobalFindAtom' GlobalFindAtomW kernel32 823
|
||||
imp 'GlobalFix' GlobalFix kernel32 824
|
||||
imp 'GlobalFlags' GlobalFlags kernel32 825
|
||||
imp 'GlobalFree' GlobalFree kernel32 0 # KernelBase
|
||||
imp 'GlobalFree' GlobalFree kernel32 0 1 # KernelBase
|
||||
imp 'GlobalGetAtomNameA' GlobalGetAtomNameA kernel32 827
|
||||
imp 'GlobalGetAtomName' GlobalGetAtomNameW kernel32 828
|
||||
imp 'GlobalHandle' GlobalHandle kernel32 829
|
||||
|
|
|
@ -70,6 +70,9 @@ bool32 PrefetchVirtualMemory(int64_t hProcess, const uint32_t *NumberOfEntries,
|
|||
bool32 OfferVirtualMemory(void *inout_VirtualAddress, size_t Size,
|
||||
int Priority);
|
||||
|
||||
void *GlobalAlloc(uint32_t uFlags, uint64_t dwBytes) nodiscard;
|
||||
void *GlobalFree(void *hMem);
|
||||
|
||||
#if ShouldUseMsabiAttribute()
|
||||
#include "libc/nt/thunk/memory.inc"
|
||||
#endif /* ShouldUseMsabiAttribute() */
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
|
||||
unsigned l, m, r;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nt/dll.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/memflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/enum/wt.h"
|
||||
|
@ -37,7 +38,7 @@
|
|||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
|
@ -46,6 +47,51 @@
|
|||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows noasan void NtDebug(const char *fmt, ...) {
|
||||
return;
|
||||
int i;
|
||||
va_list va;
|
||||
uint32_t w, u;
|
||||
const char *s;
|
||||
unsigned long d;
|
||||
char c, b[256], *p;
|
||||
va_start(va, fmt);
|
||||
for (p = b;;) {
|
||||
switch ((c = *fmt++)) {
|
||||
case '\0':
|
||||
va_end(va);
|
||||
WriteFile(GetStdHandle(kNtStdErrorHandle), b, p - b, &w, 0);
|
||||
return;
|
||||
case '%':
|
||||
switch ((c = *fmt++)) {
|
||||
case 's':
|
||||
for (s = va_arg(va, const char *); s && *s;) *p++ = *s++;
|
||||
break;
|
||||
case 'd':
|
||||
d = va_arg(va, unsigned long);
|
||||
for (i = 16; i--;) {
|
||||
u = (d >> (i * 4)) & 0xf;
|
||||
if (u < 10) {
|
||||
c = '0' + u;
|
||||
} else {
|
||||
u -= 10;
|
||||
c = 'a' + u;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*p++ = c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*p++ = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows noasan char16_t *ParseInt(char16_t *p, int64_t *x) {
|
||||
*x = 0;
|
||||
while (*p == ' ') p++;
|
||||
|
@ -56,33 +102,42 @@ static textwindows noasan char16_t *ParseInt(char16_t *p, int64_t *x) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static noinline textwindows noasan void ForkIo(int64_t h, void *buf, size_t n,
|
||||
static noinline textwindows noasan bool ForkIo(int64_t h, void *buf, size_t n,
|
||||
bool32 (*f)()) {
|
||||
char *p;
|
||||
size_t i;
|
||||
uint32_t x;
|
||||
for (p = buf, i = 0; i < n; i += x) {
|
||||
f(h, p + i, n - i, &x, NULL);
|
||||
if (!f(h, p + i, n - i, &x, NULL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static noinline textwindows noasan void WriteAll(int64_t h, void *buf,
|
||||
size_t n) {
|
||||
ForkIo(h, buf, n, WriteFile);
|
||||
if (!ForkIo(h, buf, n, WriteFile)) {
|
||||
NtDebug("fork() WriteFile(%zu) failed %d\n", n, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows noinline noasan void ReadAll(int64_t h, void *buf,
|
||||
size_t n) {
|
||||
ForkIo(h, buf, n, ReadFile);
|
||||
if (!ForkIo(h, buf, n, ReadFile)) {
|
||||
NtDebug("fork() ReadFile(%zu) failed %d\n", n, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
textwindows noasan void WinMainForked(void) {
|
||||
void *addr;
|
||||
jmp_buf jb;
|
||||
long mapcount;
|
||||
uint64_t size;
|
||||
uint32_t i, varlen;
|
||||
struct DirectMap dm;
|
||||
int64_t reader, writer;
|
||||
struct MemoryInterval *maps;
|
||||
char16_t var[21 + 1 + 21 + 1];
|
||||
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
|
||||
if (!varlen) return;
|
||||
|
@ -90,29 +145,33 @@ textwindows noasan void WinMainForked(void) {
|
|||
SetEnvironmentVariable(u"_FORK", NULL);
|
||||
ParseInt(ParseInt(var, &reader), &writer);
|
||||
ReadAll(reader, jb, sizeof(jb));
|
||||
ReadAll(reader, &_mmi.i, sizeof(_mmi.i));
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
ReadAll(reader, &_mmi.p[i], sizeof(_mmi.p[i]));
|
||||
addr = (void *)((uint64_t)_mmi.p[i].x << 16);
|
||||
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
|
||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||
CloseHandle(_mmi.p[i].h);
|
||||
_mmi.p[i].h =
|
||||
sys_mmap_nt(addr, size, _mmi.p[i].prot, _mmi.p[i].flags, -1, 0)
|
||||
.maphandle;
|
||||
ReadAll(reader, &mapcount, sizeof(_mmi.i));
|
||||
maps = GlobalAlloc(0, mapcount * sizeof(*_mmi.p));
|
||||
ReadAll(reader, maps, mapcount * sizeof(*_mmi.p));
|
||||
for (i = 0; i < mapcount; ++i) {
|
||||
addr = (void *)((uint64_t)maps[i].x << 16);
|
||||
size = ((uint64_t)(maps[i].y - maps[i].x) << 16) + FRAMESIZE;
|
||||
if (maps[i].flags & MAP_PRIVATE) {
|
||||
CloseHandle(maps[i].h);
|
||||
maps[i].h =
|
||||
sys_mmap_nt(addr, size, maps[i].prot, maps[i].flags, -1, 0).maphandle;
|
||||
ReadAll(reader, addr, size);
|
||||
} else {
|
||||
MapViewOfFileExNuma(
|
||||
_mmi.p[i].h,
|
||||
(_mmi.p[i].prot & PROT_WRITE)
|
||||
maps[i].h,
|
||||
(maps[i].prot & PROT_WRITE)
|
||||
? kNtFileMapWrite | kNtFileMapExecute | kNtFileMapRead
|
||||
: kNtFileMapExecute | kNtFileMapRead,
|
||||
0, 0, size, addr, kNtNumaNoPreferredNode);
|
||||
}
|
||||
}
|
||||
ReadAll(reader, _edata, _end - _edata);
|
||||
ReadAll(reader, _etext, _end - _etext);
|
||||
for (i = 0; i < mapcount; ++i) {
|
||||
_mmi.p[i].h = maps[i].h;
|
||||
}
|
||||
CloseHandle(reader);
|
||||
CloseHandle(writer);
|
||||
GlobalFree(maps);
|
||||
if (weaken(__wincrash_nt)) {
|
||||
AddVectoredExceptionHandler(1, (void *)weaken(__wincrash_nt));
|
||||
}
|
||||
|
@ -156,14 +215,14 @@ textwindows int sys_fork_nt(void) {
|
|||
}
|
||||
WriteAll(writer, jb, sizeof(jb));
|
||||
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
|
||||
WriteAll(writer, _mmi.p, _mmi.i * sizeof(*_mmi.p));
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
WriteAll(writer, &_mmi.p[i], sizeof(_mmi.p[i]));
|
||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||
WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
|
||||
((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE);
|
||||
}
|
||||
}
|
||||
WriteAll(writer, _edata, _end - _edata);
|
||||
WriteAll(writer, _etext, _end - _etext);
|
||||
CloseHandle(writer);
|
||||
} else {
|
||||
rc = -1;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -167,18 +170,38 @@ static noasan void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i,
|
|||
mm->i -= n;
|
||||
}
|
||||
|
||||
static noasan void CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
|
||||
static noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
|
||||
int rc;
|
||||
void *p;
|
||||
size_t n;
|
||||
static bool noreentry;
|
||||
rc = 0;
|
||||
assert(i >= 0);
|
||||
assert(i <= mm->i);
|
||||
assert(mm->i < ARRAYLEN(mm->p));
|
||||
assert(mm->i < mm->n);
|
||||
MoveMemoryNoAsan(mm->p + i + 1, mm->p + i,
|
||||
(intptr_t)(mm->p + mm->i) - (intptr_t)(mm->p + i));
|
||||
++mm->i;
|
||||
if (++mm->i > (mm->n >> 1) && cmpxchg(&noreentry, false, true)) {
|
||||
n = mm->n << 1;
|
||||
p = weaken(malloc) ? weaken(malloc)(n * sizeof(*mm->p)) : 0;
|
||||
if (p) {
|
||||
memcpy(p, mm->p, mm->i * sizeof(*mm->p));
|
||||
if (mm->p != mm->s && weaken(free)) {
|
||||
weaken(free)(mm->p);
|
||||
}
|
||||
mm->p = p;
|
||||
mm->n = n;
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
noreentry = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static noasan int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
|
||||
if (mm->i == ARRAYLEN(mm->p)) return enomem();
|
||||
CreateMemoryInterval(mm, i);
|
||||
if (mm->i == mm->n) return enomem();
|
||||
if (CreateMemoryInterval(mm, i) == -1) return -1;
|
||||
mm->p[i].y = x - 1;
|
||||
mm->p[i + 1].x = y + 1;
|
||||
return 0;
|
||||
|
@ -242,8 +265,8 @@ noasan int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
|
|||
prot == mm->p[i].prot && flags == mm->p[i].flags) {
|
||||
mm->p[i].x = x;
|
||||
} else {
|
||||
if (mm->i == ARRAYLEN(mm->p)) return enomem();
|
||||
CreateMemoryInterval(mm, i);
|
||||
if (mm->i == mm->n) return enomem();
|
||||
if (CreateMemoryInterval(mm, i) == -1) return -1;
|
||||
mm->p[i].x = x;
|
||||
mm->p[i].y = y;
|
||||
mm->p[i].h = h;
|
||||
|
|
|
@ -21,15 +21,18 @@ COSMOPOLITAN_C_START_
|
|||
#define kAutomapSize MEMTRACK_ADDRESS(_kAutomapSize, 0x40000000)
|
||||
#define kFixedmapStart MEMTRACK_ADDRESS(_kFixedmapStart, 0x40000000)
|
||||
|
||||
struct MemoryInterval {
|
||||
int x;
|
||||
int y;
|
||||
long h;
|
||||
int prot;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct MemoryIntervals {
|
||||
long i;
|
||||
struct MemoryInterval {
|
||||
int x;
|
||||
int y;
|
||||
long h;
|
||||
int prot;
|
||||
int flags;
|
||||
} p[128];
|
||||
long i, n;
|
||||
struct MemoryInterval *p;
|
||||
struct MemoryInterval s[OPEN_MAX];
|
||||
};
|
||||
|
||||
extern hidden struct MemoryIntervals _mmi;
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
static noasan void *GetFrameAddr(int f) {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
STATIC_YOINK("_init__mmi");
|
||||
|
||||
struct MemoryIntervals _mmi;
|
||||
|
|
24
libc/runtime/mmi.init.S
Normal file
24
libc/runtime/mmi.init.S
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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/macros.internal.h"
|
||||
|
||||
.init.start 200,_init__mmi
|
||||
movb $OPEN_MAX,_mmi+8
|
||||
movl $_mmi+24,_mmi+16
|
||||
.init.end 200,_init__mmi
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
textwindows int sys_msync_nt(void *addr, size_t size, int flags) {
|
||||
int x, y, l, r, i;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
|
||||
int i, frames, maptally, gaptally;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
int UntrackMemoryIntervals(void *addr, size_t size) {
|
||||
int a, b;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
|
@ -108,6 +108,8 @@ static noasan textwindows wontreturn void WinMainNew(void) {
|
|||
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
}
|
||||
_mmi.p = _mmi.s;
|
||||
_mmi.n = OPEN_MAX;
|
||||
addr = version < 10 ? 0xff00000 : 0x777000000000;
|
||||
size = ROUNDUP(STACKSIZE + sizeof(struct WinArgs), FRAMESIZE);
|
||||
MapViewOfFileExNuma((_mmi.p[0].h = CreateFileMappingNuma(
|
||||
|
|
|
@ -357,10 +357,10 @@ _init_systemfive_stack: # determinism ftw!
|
|||
shr $16,%r11 # for the stack range
|
||||
shr $16,%r9
|
||||
movb $1,(%rcx) # _mmi.i
|
||||
mov %r11d,8(%rcx) # _mmi.p[0].x
|
||||
mov %r9d,12(%rcx) # _mmi.p[0].y
|
||||
mov %edx,20(%rcx) # _mmi.p[0].prot
|
||||
mov %r10d,24(%rcx) # _mmi.p[0].flags
|
||||
mov %r11d,24(%rcx) # _mmi.s[0].x
|
||||
mov %r9d,28(%rcx) # _mmi.s[0].y
|
||||
mov %edx,36(%rcx) # _mmi.s[0].prot
|
||||
mov %r10d,40(%rcx) # _mmi.s[0].flags
|
||||
3: pop %r9 # restore stack size
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
|
@ -73,3 +74,22 @@ TEST(gclongjmp, test) {
|
|||
free(y);
|
||||
free(x);
|
||||
}
|
||||
|
||||
void F1(void) {
|
||||
/* 3x slower than F2() but sooo worth it */
|
||||
_gc(malloc(16));
|
||||
}
|
||||
|
||||
void F2(void) {
|
||||
void *volatile p;
|
||||
p = malloc(16);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void (*F1p)(void) = F1;
|
||||
void (*F2p)(void) = F2;
|
||||
|
||||
BENCH(gc, bench) {
|
||||
EZBENCH2("gc(malloc(16))", donothing, F1p());
|
||||
EZBENCH2("free(malloc(16))", donothing, F2p());
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -86,10 +86,12 @@ static int RunReleaseMemoryIntervalsTest(const struct MemoryIntervals t[2],
|
|||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestEmpty) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{0, {}},
|
||||
{1, {{2, 2, 0}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{0, OPEN_MAX, 0, {}},
|
||||
{1, OPEN_MAX, 0, {{2, 2, 0}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 2, 2, 0);
|
||||
}
|
||||
|
||||
|
@ -97,7 +99,7 @@ TEST(TrackMemoryInterval, TestFull) {
|
|||
int i;
|
||||
struct MemoryIntervals *mm;
|
||||
mm = calloc(1, sizeof(struct MemoryIntervals));
|
||||
for (i = 0; i < ARRAYLEN(mm->p); ++i) {
|
||||
for (i = 0; i < mm->n; ++i) {
|
||||
CheckMemoryIntervalsAreOk(mm);
|
||||
CHECK_NE(-1, TrackMemoryInterval(mm, i, i, i, 0, 0));
|
||||
CheckMemoryIntervalsAreOk(mm);
|
||||
|
@ -109,57 +111,71 @@ TEST(TrackMemoryInterval, TestFull) {
|
|||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestAppend) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{2, 2}}},
|
||||
{1, {{2, 3}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{2, 2}}},
|
||||
{1, OPEN_MAX, 0, {{2, 3}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 3, 3, 0);
|
||||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestPrepend) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{2, 2}}},
|
||||
{1, {{1, 2}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{2, 2}}},
|
||||
{1, OPEN_MAX, 0, {{1, 2}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 1, 1, 0);
|
||||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestFillHole) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{4, {{1, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
|
||||
{3, {{1, 4}, {5, 5, 1}, {6, 8}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{4, OPEN_MAX, 0, {{1, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
|
||||
{3, OPEN_MAX, 0, {{1, 4}, {5, 5, 1}, {6, 8}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 2, 2, 0);
|
||||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestAppend2) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{2, 2}}},
|
||||
{2, {{2, 2}, {3, 3, 1}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{2, 2}}},
|
||||
{2, OPEN_MAX, 0, {{2, 2}, {3, 3, 1}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 3, 3, 1);
|
||||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestPrepend2) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{2, 2}}},
|
||||
{2, {{1, 1, 1}, {2, 2}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{2, 2}}},
|
||||
{2, OPEN_MAX, 0, {{1, 1, 1}, {2, 2}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 1, 1, 1);
|
||||
}
|
||||
|
||||
TEST(TrackMemoryInterval, TestFillHole2) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{4, {{1, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
|
||||
{5, {{1, 1}, {2, 2, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{4, OPEN_MAX, 0, {{1, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
|
||||
{5, OPEN_MAX, 0, {{1, 1}, {2, 2, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
RunTrackMemoryIntervalTest(mm, 2, 2, 1);
|
||||
}
|
||||
|
||||
TEST(FindMemoryInterval, Test) {
|
||||
static const struct MemoryIntervals mm[1] = {
|
||||
static struct MemoryIntervals mm[1] = {
|
||||
{
|
||||
4,
|
||||
OPEN_MAX,
|
||||
0,
|
||||
{
|
||||
[0] = {1, 1},
|
||||
[1] = {3, 4},
|
||||
|
@ -168,6 +184,7 @@ TEST(FindMemoryInterval, Test) {
|
|||
},
|
||||
},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
EXPECT_EQ(0, FindMemoryInterval(mm, 0));
|
||||
EXPECT_EQ(0, FindMemoryInterval(mm, 1));
|
||||
EXPECT_EQ(1, FindMemoryInterval(mm, 2));
|
||||
|
@ -181,115 +198,141 @@ TEST(FindMemoryInterval, Test) {
|
|||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestEmpty) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{0, {}},
|
||||
{0, {}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{0, OPEN_MAX, 0, {}},
|
||||
{0, OPEN_MAX, 0, {}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 2, 2));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestRemoveElement_UsesInclusiveRange) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{3, {{0, 0}, {2, 2}, {4, 4}}},
|
||||
{2, {{0, 0}, {4, 4}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{3, OPEN_MAX, 0, {{0, 0}, {2, 2}, {4, 4}}},
|
||||
{2, OPEN_MAX, 0, {{0, 0}, {4, 4}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 2, 2));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestPunchHole) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{0, 9}}},
|
||||
{2, {{0, 3}, {6, 9}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{0, 9}}},
|
||||
{2, OPEN_MAX, 0, {{0, 3}, {6, 9}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 4, 5));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestShortenLeft) {
|
||||
if (IsWindows()) return;
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{0, 9}}},
|
||||
{1, {{0, 7}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{0, 9}}},
|
||||
{1, OPEN_MAX, 0, {{0, 7}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 8, 9));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestShortenRight) {
|
||||
if (IsWindows()) return;
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{0, 9}}},
|
||||
{1, {{3, 9}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{0, 9}}},
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 0, 2));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestShortenLeft2) {
|
||||
if (IsWindows()) return;
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{0, 9}}},
|
||||
{1, {{0, 7}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{0, 9}}},
|
||||
{1, OPEN_MAX, 0, {{0, 7}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 8, 11));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestShortenRight2) {
|
||||
if (IsWindows()) return;
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{0, 9}}},
|
||||
{1, {{3, 9}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{0, 9}}},
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, -3, 2));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestZeroZero) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{3, 9}}},
|
||||
{1, {{3, 9}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 0, 0));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestNoopLeft) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{3, 9}}},
|
||||
{1, {{3, 9}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 1, 2));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestNoopRight) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{1, {{3, 9}}},
|
||||
{1, {{3, 9}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
{1, OPEN_MAX, 0, {{3, 9}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 10, 10));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestBigFree) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{2, {{0, 3}, {6, 9}}},
|
||||
{0, {}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{2, OPEN_MAX, 0, {{0, 3}, {6, 9}}},
|
||||
{0, OPEN_MAX, 0, {}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, INT_MIN, INT_MAX));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestWeirdGap) {
|
||||
static const struct MemoryIntervals mm[2] = {
|
||||
{3, {{10, 10}, {20, 20}, {30, 30}}},
|
||||
{2, {{10, 10}, {30, 30}}},
|
||||
static struct MemoryIntervals mm[2] = {
|
||||
{3, OPEN_MAX, 0, {{10, 10}, {20, 20}, {30, 30}}},
|
||||
{2, OPEN_MAX, 0, {{10, 10}, {30, 30}}},
|
||||
};
|
||||
mm[0].p = mm[0].s;
|
||||
mm[1].p = mm[1].s;
|
||||
EXPECT_NE(-1, RunReleaseMemoryIntervalsTest(mm, 15, 25));
|
||||
}
|
||||
|
||||
TEST(ReleaseMemoryIntervals, TestOutOfMemory) {
|
||||
TEST(ReleaseMemoryIntervals, TestOutOfMemory_AllocatesMore) {
|
||||
int i;
|
||||
struct MemoryIntervals *mm;
|
||||
mm = calloc(1, sizeof(struct MemoryIntervals));
|
||||
for (i = 0; i < ARRAYLEN(mm->p); ++i) {
|
||||
mm->n = OPEN_MAX;
|
||||
mm->p = mm->s;
|
||||
for (i = 0; i < OPEN_MAX * 2; ++i) {
|
||||
CHECK_NE(-1, TrackMemoryInterval(mm, i * 10, i * 10 + 8, 0, 0, 0));
|
||||
}
|
||||
CheckMemoryIntervalsAreOk(mm);
|
||||
CHECK_EQ(-1, ReleaseMemoryIntervals(mm, 4, 4, NULL));
|
||||
CHECK_EQ(ENOMEM, errno);
|
||||
CHECK_EQ(0, ReleaseMemoryIntervals(mm, 4, 4, NULL));
|
||||
CheckMemoryIntervalsAreOk(mm);
|
||||
free(mm->p);
|
||||
free(mm);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/mem/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/mremap.h"
|
||||
|
|
|
@ -388,7 +388,7 @@ int RunOnHost(char *spec) {
|
|||
do {
|
||||
Connect();
|
||||
EzFd(g_sock);
|
||||
EzHandshake();
|
||||
EzHandshake(); /* TODO(jart): Backoff on MBEDTLS_ERR_NET_CONN_RESET */
|
||||
SendRequest();
|
||||
} while ((rc = ReadResponse()) == -1);
|
||||
return rc;
|
||||
|
|
Loading…
Add table
Reference in a new issue