From f8a402fa0f4d7c70a157bc980a3b075fc07b44ea Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 11 Aug 2015 12:03:45 +0100 Subject: [PATCH] New macro arenachunkring encapsulates getting the chunk ring for an arena. RingLength now returns Count, not Size. New test case checks that chunks are added and removed from the arena as memory is allocated and freed. Copied from Perforce Change: 188133 ServerID: perforce.ravenbrook.com --- mps/code/arena.c | 14 +++++----- mps/code/gcbench.c | 3 +- mps/code/mpm.h | 1 + mps/code/ring.c | 8 +++--- mps/code/ring.h | 2 +- mps/design/ring.txt | 2 +- mps/test/function/232.c | 59 +++++++++++++++++++++++++++++++++++++++ mps/test/testsets/passing | 3 +- 8 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 mps/test/function/232.c diff --git a/mps/code/arena.c b/mps/code/arena.c index fee56d6378a..e4e7c5e1973 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -164,7 +164,7 @@ Bool ArenaCheck(Arena arena) if (arena->primary != NULL) { CHECKD(Chunk, arena->primary); } - CHECKD_NOSIG(Ring, &arena->chunkRing); + CHECKD_NOSIG(Ring, ArenaChunkRing(arena)); /* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */ CHECKL(TreeCheck(ArenaChunkTree(arena))); /* TODO: check that the chunkRing and chunkTree have identical members */ @@ -225,7 +225,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args) arena->zoned = zoned; arena->primary = NULL; - RingInit(&arena->chunkRing); + RingInit(ArenaChunkRing(arena)); arena->chunkTree = TreeEMPTY; arena->chunkSerial = (Serial)0; @@ -372,7 +372,7 @@ void ArenaFinish(Arena arena) arena->sig = SigInvalid; GlobalsFinish(ArenaGlobals(arena)); LocusFinish(arena); - RingFinish(&arena->chunkRing); + RingFinish(ArenaChunkRing(arena)); AVER(ArenaChunkTree(arena) == TreeEMPTY); } @@ -587,7 +587,7 @@ Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResFAIL; - RING_FOR(node, &arena->chunkRing, next) { + RING_FOR(node, ArenaChunkRing(arena), next) { Chunk chunk = RING_ELT(Chunk, arenaRing, node); res = arenaDescribeTractsInChunk(chunk, stream, depth); if (res != ResOK) @@ -678,7 +678,7 @@ void ArenaChunkInsert(Arena arena, Chunk chunk) { AVER(updatedTree); TreeBalance(&updatedTree); arena->chunkTree = updatedTree; - RingAppend(&arena->chunkRing, &chunk->arenaRing); + RingAppend(ArenaChunkRing(arena), &chunk->arenaRing); arena->reserved += ChunkReserved(chunk); @@ -707,7 +707,7 @@ void ArenaChunkRemoved(Arena arena, Chunk chunk) if (chunk == arena->primary) { /* The primary chunk must be the last chunk to be removed. */ - AVER(RingIsSingle(&arena->chunkRing)); + AVER(RingIsSingle(ArenaChunkRing(arena))); AVER(arena->reserved == 0); arena->primary = NULL; } @@ -762,7 +762,7 @@ static Res arenaAllocPage(Addr *baseReturn, Arena arena, Pool pool) res = arenaAllocPageInChunk(baseReturn, arena->primary, pool); if (res != ResOK) { Ring node, next; - RING_FOR(node, &arena->chunkRing, next) { + RING_FOR(node, ArenaChunkRing(arena), next) { Chunk chunk = RING_ELT(Chunk, arenaRing, node); if (chunk != arena->primary) { res = arenaAllocPageInChunk(baseReturn, chunk, pool); diff --git a/mps/code/gcbench.c b/mps/code/gcbench.c index 2ae97104930..7aa28eb4561 100644 --- a/mps/code/gcbench.c +++ b/mps/code/gcbench.c @@ -248,8 +248,7 @@ static void arena_setup(gcthread_fn_t fn, } MPS_ARGS_END(args); watch(fn, name); mps_arena_park(arena); - printf("%u chunks\n", (unsigned)TreeDebugCount(ArenaChunkTree(arena), - ChunkCompare, ChunkKey)); + printf("%u chunks\n", (unsigned)RingLength(ArenaChunkRing(arena))); mps_pool_destroy(pool); mps_fmt_destroy(format); if (ngen > 0) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index a5ac16b41a2..6f34cd4e020 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -528,6 +528,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals); #define ArenaGreyRing(arena, rank) (&(arena)->greyRing[rank]) #define ArenaPoolRing(arena) (&ArenaGlobals(arena)->poolRing) #define ArenaChunkTree(arena) RVALUE((arena)->chunkTree) +#define ArenaChunkRing(arena) RVALUE(&(arena)->chunkRing) extern Bool ArenaGrainSizeCheck(Size size); #define AddrArenaGrainUp(addr, arena) AddrAlignUp(addr, ArenaGrainSize(arena)) diff --git a/mps/code/ring.c b/mps/code/ring.c index 2f4be5066f2..9ceeecfa232 100644 --- a/mps/code/ring.c +++ b/mps/code/ring.c @@ -65,14 +65,14 @@ Bool RingIsSingle(Ring ring) * See */ -Size RingLength(Ring ring) +Count RingLength(Ring ring) { - Size size = 0; + Count length = 0; Ring node, next; AVERT(Ring, ring); RING_FOR(node, ring, next) - ++ size; - return size; + ++ length; + return length; } diff --git a/mps/code/ring.h b/mps/code/ring.h index 9cb915f4bf4..c7d154dbe5c 100644 --- a/mps/code/ring.h +++ b/mps/code/ring.h @@ -30,7 +30,7 @@ typedef struct RingStruct { /* double-ended queue structure */ extern Bool RingCheck(Ring ring); extern Bool RingCheckSingle(Ring ring); extern Bool RingIsSingle(Ring ring); -extern Size RingLength(Ring ring); +extern Count RingLength(Ring ring); /* .ring.init: See */ extern void (RingInit)(Ring ring); diff --git a/mps/design/ring.txt b/mps/design/ring.txt index c0f4d9adfd4..1935cd02b29 100644 --- a/mps/design/ring.txt +++ b/mps/design/ring.txt @@ -112,7 +112,7 @@ additionally checks that ``ring`` is a singleton (see _`.is.single`: Return ``TRUE`` if ``ring`` is a singleton (see `.def.singleton`_). -``Size RingLength(Ring ring)`` +``Count RingLength(Ring ring)`` _`.length`: Return the number of elements in the ring, not counting ``ring`` itself. This therefore returns 0 for singleton rings, and for diff --git a/mps/test/function/232.c b/mps/test/function/232.c new file mode 100644 index 00000000000..398f1586dd9 --- /dev/null +++ b/mps/test/function/232.c @@ -0,0 +1,59 @@ +/* +TEST_HEADER + id = $Id: //info.ravenbrook.com/project/mps/branch/2015-08-11/compact/test/function/229.c#1 $ + summary = test arena extension and compaction + language = c + link = testlib.o + parameters = SIZE=1024*1024 ITERATIONS=100 +END_HEADER +*/ + +#include "mpm.h" +#include "mpscmvff.h" +#include "testlib.h" + +static void check_chunks(mps_arena_t arena, unsigned expected) +{ + unsigned chunks = (unsigned)RingLength(ArenaChunkRing((Arena)arena)); + asserts(chunks == expected, "expected %u chunks, got %u", expected, chunks); +} + +static void test(void) +{ + mps_arena_t arena; + mps_pool_t pool; + mps_addr_t block[ITERATIONS]; + unsigned i; + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, SIZE); + die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); + } MPS_ARGS_END(args); + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_SPARE, 0); + die(mps_pool_create_k(&pool, arena, mps_class_mvff(), args), "pool_create"); + } MPS_ARGS_END(args); + check_chunks(arena, 1); + + for (i = 0; i < ITERATIONS; ++i) { + die(mps_alloc(&block[i], pool, SIZE), "mps_alloc"); + check_chunks(arena, i + 2); + } + + for (i = ITERATIONS; i > 0; --i) { + mps_free(pool, block[i - 1], SIZE); + mps_arena_collect(arena); /* ensure ArenaCompact called via TraceReclaim */ + check_chunks(arena, i); + } + + mps_pool_destroy(pool); + mps_arena_destroy(arena); +} + +int main(void) +{ + easy_tramp(test); + pass(); + return 0; +} diff --git a/mps/test/testsets/passing b/mps/test/testsets/passing index fde2ca5de8d..b29ffc686cd 100644 --- a/mps/test/testsets/passing +++ b/mps/test/testsets/passing @@ -168,4 +168,5 @@ function/224.c % 225 -- no such test function/226.c function/227.c -function/229.c \ No newline at end of file +function/229.c +function/232.c