Make mappings unlimited on NT

This change might also fix fork() in certain cases on NT.
This commit is contained in:
Justine Tunney 2021-09-04 13:20:47 -07:00
parent ab64c746cc
commit 34b68f1945
31 changed files with 356 additions and 127 deletions

View file

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

View file

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

View file

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

View file

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