From f7f4e4a7f0bb1af38ef58bf20e8015c54ec3eaaa Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 8 Oct 2014 22:16:56 +0100 Subject: [PATCH] If you try to create a client arena that's too small for the full complement of zones, return mps_res_memory instead of asserting. If you try to create a virtual memory arena that's too small for the full complement of zones, round up the size to the minimum instead of asserting. Copied from Perforce Change: 187164 ServerID: perforce.ravenbrook.com --- mps/code/arenacl.c | 4 ++++ mps/code/arenavm.c | 16 +++++++++++----- mps/manual/source/topic/arena.rst | 21 ++++++++++++++++----- mps/test/testsets/passing | 2 +- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/mps/code/arenacl.c b/mps/code/arenacl.c index 15bdcc6fcfb..f98398a468a 100644 --- a/mps/code/arenacl.c +++ b/mps/code/arenacl.c @@ -257,6 +257,10 @@ static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args) AVER(base != (Addr)0); AVERT(ArenaGrainSize, grainSize); + if (size < grainSize * MPS_WORD_SHIFT) + /* Not enough room for a full complement of zones. */ + return ResMEMORY; + clArenaSize = SizeAlignUp(sizeof(ClientArenaStruct), MPS_PF_ALIGN); if (size < clArenaSize) return ResMEMORY; diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index 97d2efe3e95..347b0576a66 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -507,6 +507,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args) { Size size = VM_ARENA_SIZE_DEFAULT; /* initial arena size */ Align grainSize = MPS_PF_ALIGN; /* arena grain size */ + Size pageSize = PageSize(); /* operating system page size */ Size chunkSize; /* size actually created */ Size vmArenaSize; /* aligned size of VMArenaStruct */ Res res; @@ -522,14 +523,19 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args) AVER(class == VMArenaClassGet()); AVERT(ArgList, args); - if (ArgPick(&arg, args, MPS_KEY_ARENA_SIZE)) - size = arg.val.size; if (ArgPick(&arg, args, MPS_KEY_ARENA_GRAIN_SIZE)) grainSize = arg.val.size; - grainSize = SizeAlignUp(grainSize, PageSize()); - - AVER(size > 0); + if (grainSize < pageSize) + /* Make it easier to write portable programs by rounding up. */ + grainSize = pageSize; AVERT(ArenaGrainSize, grainSize); + + if (ArgPick(&arg, args, MPS_KEY_ARENA_SIZE)) + size = arg.val.size; + if (size < grainSize * MPS_WORD_WIDTH) + /* There has to be enough room in the chunk for a full complement of + zones. Make it easier to write portable programs by rounding up. */ + size = grainSize * MPS_WORD_WIDTH; /* Parse remaining arguments, if any, into VM parameters. We must do this into some stack-allocated memory for the moment, since we diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst index ce313166161..a309a950ac8 100644 --- a/mps/manual/source/topic/arena.rst +++ b/mps/manual/source/topic/arena.rst @@ -254,6 +254,14 @@ Virtual memory arenas necessary. The MPS is most efficient if you reserve an address space that is several times larger than your peak memory usage. + If you specify a value for :c:macro:`MPS_KEY_ARENA_SIZE` that's + too small for the virtual memory arena, then the MPS rounds it + up to the minimum and continues. The minimum size for the + virtual memory arena is :c:macro:`MPS_WORD_WIDTH` × + :c:macro:`MPS_KEY_ARENA_GRAIN_SIZE` bytes. For example, on a + 64-bit platform with a 4\ :term:`kilobyte` page size, this is + 256\ :term:`kilobytes`. + .. note:: The MPS asks for more address space if it runs out, but the @@ -262,11 +270,14 @@ Virtual memory arenas * :c:macro:`MPS_KEY_ARENA_GRAIN_SIZE` (type :c:type:`size_t`) is the granularity with which the arena will manage memory - internally. It must be a power of 2. It will be aligned up to a - multiple of the operating system's page size if necessary. If - not provided, the operating system's page size is used. Larger - granularity reduces overheads, but increases - :term:`fragmentation` and :term:`retention`. + internally. It must be a power of 2. If not provided, the + operating system's page size is used. Larger granularity reduces + overheads, but increases :term:`fragmentation` and + :term:`retention`. + + If you specify a value of :c:macro:`MPS_KEY_ARENA_GRAIN_SIZE` + that's smaller than the operating system page size, the MPS + rounds it up to the page size and continues. A second optional :term:`keyword argument` may be passed, but it only has any effect on the Windows operating system: diff --git a/mps/test/testsets/passing b/mps/test/testsets/passing index 4b0a0cbe1b5..70330de1e82 100644 --- a/mps/test/testsets/passing +++ b/mps/test/testsets/passing @@ -109,7 +109,7 @@ function/117.c function/118.c function/119.c function/120.c -% function/121.c -- job003495 +function/121.c -- job003495 function/122.c function/123.c function/124.c