From 5460f080e92d6bc3c3ef8dac5b88089111fd3236 Mon Sep 17 00:00:00 2001 From: David Jones Date: Tue, 9 Jun 1998 15:36:42 +0100 Subject: [PATCH] Merging mmdevel_drj_commit_limit, change.epcore.minnow.160073 Copied from Perforce Change: 19647 ServerID: perforce.ravenbrook.com --- mps/src/arena.c | 29 +++++++++++++++++++++++++++-- mps/src/arenacl.c | 15 ++++++++++++--- mps/src/arenavm.c | 20 ++++++++++++++++++-- mps/src/mpm.h | 5 ++++- mps/src/mpmst.h | 4 +++- mps/src/mpmtypes.h | 13 ++++++++----- mps/src/mps.h | 8 ++++++-- mps/src/mpsi.c | 30 +++++++++++++++++++++++++++--- 8 files changed, 105 insertions(+), 19 deletions(-) diff --git a/mps/src/arena.c b/mps/src/arena.c index 461b441c3bb..412ccfa012a 100644 --- a/mps/src/arena.c +++ b/mps/src/arena.c @@ -1,6 +1,6 @@ /* impl.c.arena: ARENA IMPLEMENTATION * - * $HopeName: MMsrc!arena.c(trunk.39) $ + * $HopeName: MMsrc!arena.c(trunk.40) $ * Copyright (C) 1998. Harlequin Group plc. All rights reserved. * * .readership: Any MPS developer @@ -36,7 +36,7 @@ #include "poolmrg.h" #include "mps.h" -SRCID(arena, "$HopeName: MMsrc!arena.c(trunk.39) $"); +SRCID(arena, "$HopeName: MMsrc!arena.c(trunk.40) $"); /* All static data objects are declared here. See .static */ @@ -114,6 +114,9 @@ Bool ArenaCheck(Arena arena) arena->allocMutatorSize); CHECKL(arena->fillInternalSize >= 0.0); CHECKL(arena->emptyInternalSize >= 0.0); + /* commitLimit is arbitrary, can't be checked. */ + /* (it's probably >= ArenaCommitted(), but we can't call that */ + /* due to recursion problems) */ CHECKL(ShiftCheck(arena->zoneShift)); CHECKL(AlignCheck(arena->alignment)); @@ -246,6 +249,9 @@ void ArenaInit(Arena arena, ArenaClass class) arena->allocMutatorSize = 0.0; arena->fillInternalSize = 0.0; arena->emptyInternalSize = 0.0; + /* commitLimit may be overrideen by init (but probably not */ + /* as there's not much point) */ + arena->commitLimit = (Size)-1; /* usually overridden by init */ arena->alignment = MPS_PF_ALIGN; /* usually overridden by init */ @@ -705,6 +711,7 @@ Res ArenaDescribe(Arena arena, mps_lib_FILE *stream) return res; res = WriteF(stream, + " commitLimit $W\n", (WriteFW)arena->commitLimit, " zoneShift $U\n", (WriteFU)arena->zoneShift, " alignment $W\n", (WriteFW)arena->alignment, " poolSerial $U\n", (WriteFU)arena->poolSerial, @@ -961,6 +968,24 @@ Size ArenaCommitted(Arena arena) return (*arena->class->committed)(arena); } +Size ArenaCommitLimit(Arena arena) +{ + AVERT(Arena, arena); + return arena->commitLimit; +} + +Res ArenaSetCommitLimit(Arena arena, Size limit) +{ + AVERT(Arena, arena); + AVER(ArenaCommitted(arena) <= arena->commitLimit); + + if(limit < ArenaCommitted(arena)) { + /* Attempt to set the limit below current committed */ + return ResFAIL; + } + arena->commitLimit = limit; + return ResOK; +} double ArenaMutatorAllocSize(Arena arena) { diff --git a/mps/src/arenacl.c b/mps/src/arenacl.c index d23559e9c4b..4036875dd43 100644 --- a/mps/src/arenacl.c +++ b/mps/src/arenacl.c @@ -1,6 +1,6 @@ /* impl.c.arenacl: ARENA IMPLEMENTATION USING CLIENT MEMORY * - * $HopeName: MMsrc!arenacl.c(trunk.11) $ + * $HopeName: MMsrc!arenacl.c(trunk.12) $ * Copyright (C) 1997. Harlequin Group plc. All rights reserved. * * .readership: MM developers @@ -17,7 +17,7 @@ #include "mpsacl.h" -SRCID(arenacl, "$HopeName: MMsrc!arenacl.c(trunk.11) $"); +SRCID(arenacl, "$HopeName: MMsrc!arenacl.c(trunk.12) $"); typedef struct ClientArenaStruct *ClientArena; @@ -487,6 +487,14 @@ static Res ChunkSegAlloc(Seg *segReturn, SegPref pref, Size pages, if (!b) return ResRESOURCE; + + /* check commit limit, note that if there are multiple reasons */ + /* for failing the allocation we attempt to return other result codes */ + /* in preference to ResCOMMIT_LIMIT. See design.mps.arena.commit-limit */ + if(ClientArenaCommitted(PoolArena(pool)) + pages*clientArena->pageSize > + PoolArena(pool)->commitLimit) { + return ResCOMMIT_LIMIT; + } /* Initialize the generic segment structure. */ seg = PageSeg(&chunk->pageTable[baseIndex]); @@ -548,8 +556,9 @@ static Res ClientSegAlloc(Seg *segReturn, SegPref pref, RING_FOR(node, &clientArena->chunkRing, nextNode) { Chunk chunk = RING_ELT(Chunk, arenaRing, node); res = ChunkSegAlloc(segReturn, pref, pages, pool, chunk); - if (res == ResOK) + if(res == ResOK || res == ResCOMMIT_LIMIT) { return res; + } } return ResRESOURCE; } diff --git a/mps/src/arenavm.c b/mps/src/arenavm.c index 80a3a8f3838..abed091c6b2 100644 --- a/mps/src/arenavm.c +++ b/mps/src/arenavm.c @@ -1,6 +1,6 @@ /* impl.c.arenavm: VIRTUAL MEMORY BASED ARENA IMPLEMENTATION * - * $HopeName: MMsrc!arenavm.c(trunk.38) $ + * $HopeName: MMsrc!arenavm.c(trunk.39) $ * Copyright (C) 1998. Harlequin Group plc. All rights reserved. * * This is the implementation of the Segment abstraction from the VM @@ -29,7 +29,7 @@ #include "mpm.h" #include "mpsavm.h" -SRCID(arenavm, "$HopeName: MMsrc!arenavm.c(trunk.38) $"); +SRCID(arenavm, "$HopeName: MMsrc!arenavm.c(trunk.39) $"); typedef struct VMArenaStruct *VMArena; @@ -700,6 +700,13 @@ static Res VMSegAlloc(Seg *segReturn, SegPref pref, Size size, } } + /* test commit limit */ + /* Assumes VMArenaCommitted will increase by size after the call */ + /* to VMMap */ + if(VMArenaCommitted(arena) + size > arena->commitLimit) { + return ResCOMMIT_LIMIT; + } + /* .alloc.early-map: Map in the segment memory before actually */ /* allocating the pages, so that we can exit straight away if */ /* we fail. */ @@ -714,6 +721,15 @@ static Res VMSegAlloc(Seg *segReturn, SegPref pref, Size size, /* Ensure that the page descriptors we need are on mapped pages. */ if(unusedTablePages(&unmappedPagesBase, &unmappedPagesLimit, vmArena, base, base + pages)) { + /* test commit limit */ + /* Assumes VMArenaCommitted will increase by unmappedPagesLimit - */ + /* unmappedPagesBase after the call to VMMap */ + if(VMArenaCommitted(arena) + + AddrOffset(unmappedPagesBase, unmappedPagesLimit) > + arena->commitLimit) { + res = ResCOMMIT_LIMIT; + goto failTableMap; + } res = VMMap(vmArena->vm, unmappedPagesBase, unmappedPagesLimit); if(res != ResOK) goto failTableMap; diff --git a/mps/src/mpm.h b/mps/src/mpm.h index 58d90dcc564..a591fbc4e26 100644 --- a/mps/src/mpm.h +++ b/mps/src/mpm.h @@ -1,6 +1,6 @@ /* impl.h.mpm: MEMORY POOL MANAGER DEFINITIONS * - * $HopeName$ + * $HopeName: MMsrc!mpm.h(trunk.88) $ * Copyright (C) 1998. Harlequin Group plc. All rights reserved. */ @@ -557,6 +557,9 @@ Ref ArenaRead(Arena arena, Addr addr); extern Size ArenaReserved(Arena arena); extern Size ArenaCommitted(Arena arena); +extern Size ArenaCommitLimit(Arena arena); +extern Res ArenaSetCommitLimit(Arena arena, Size limit); + extern double ArenaMutatorAllocSize(Arena arena); extern Res ArenaExtend(Arena, Addr base, Size size); diff --git a/mps/src/mpmst.h b/mps/src/mpmst.h index ee2d3c75dc6..c2675ff8a0d 100644 --- a/mps/src/mpmst.h +++ b/mps/src/mpmst.h @@ -1,6 +1,6 @@ /* impl.h.mpmst: MEMORY POOL MANAGER DATA STRUCTURES * - * $HopeName$ + * $HopeName: MMsrc!mpmst.h(trunk.58) $ * Copyright (C) 1998 Harlequin Group plc. All rights reserved. * * .readership: MM developers. @@ -615,6 +615,8 @@ typedef struct ArenaStruct { double fillInternalSize; /* total bytes filled, internal buffers */ double emptyInternalSize; /* total bytes emptied, internal buffers */ + Size commitLimit; /* Client configurable commit limit */ + Shift zoneShift; /* see also impl.c.ref */ Align alignment; /* minimum alignment of segments */ diff --git a/mps/src/mpmtypes.h b/mps/src/mpmtypes.h index bda84c9c0fc..37aa6649dbf 100644 --- a/mps/src/mpmtypes.h +++ b/mps/src/mpmtypes.h @@ -1,6 +1,6 @@ /* impl.h.mpmtypes: MEMORY POOL MANAGER TYPES * - * $HopeName: MMsrc!mpmtypes.h(trunk.48) $ + * $HopeName: MMsrc!mpmtypes.h(trunk.49) $ * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * .readership: MM developers. @@ -278,9 +278,11 @@ enum { }; -/* Result Codes -- see design.mps.type.res */ -/* These definitions must match impl.h.mps.res. */ -/* This is checked by impl.c.mpsi.check. */ +/* .result-codes: Result Codes -- see design.mps.type.res */ +/* These definitions must match impl.h.mps.result-codes. */ +/* This is checked by impl.c.mpsi.check.rc. */ +/* Changing this list entails changing the list in */ +/* impl.h.mps.result-codes and the check in impl.c.mpsi.check.rc */ enum { ResOK = 0, @@ -289,7 +291,8 @@ enum { ResMEMORY, ResLIMIT, ResUNIMPL, - ResIO + ResIO, + ResCOMMIT_LIMIT }; diff --git a/mps/src/mps.h b/mps/src/mps.h index 1ef2b4cfce6..1e67271a818 100644 --- a/mps/src/mps.h +++ b/mps/src/mps.h @@ -1,6 +1,6 @@ /* impl.h.mps: HARLEQUIN MEMORY POOL SYSTEM C INTERFACE * - * $HopeName: MMsrc!mps.h(trunk.38) $ + * $HopeName: MMsrc!mps.h(trunk.39) $ * Copyright (C) 1997, 1998 The Harlequin Group Limited. All rights reserved. * * .readership: customers, MPS developers. @@ -46,6 +46,7 @@ typedef unsigned mps_message_type_t; /* message type (unsigned) */ /* Result Codes */ /* .result-codes: Keep in sync with impl.h.mpmtypes.result-codes */ +/* and the check in impl.c.mpsi.check.rc */ enum { MPS_RES_OK = 0, /* success (always zero) */ @@ -54,7 +55,8 @@ enum { MPS_RES_MEMORY, /* unable to obtain memory */ MPS_RES_LIMIT, /* limitation reached */ MPS_RES_UNIMPL, /* unimplemented facility */ - MPS_RES_IO /* system I/O error */ + MPS_RES_IO, /* system I/O error */ + MPS_RES_COMMIT_LIMIT /* arena commit limit exceeded */ }; /* .message.types: Keep in sync with impl.h.mpmtypes.message.types */ @@ -200,6 +202,8 @@ extern void mps_space_destroy(mps_space_t); extern size_t mps_arena_reserved(mps_arena_t); extern size_t mps_arena_committed(mps_arena_t); +extern size_t mps_arena_commit_limit(mps_arena_t); +extern mps_res_t mps_arena_commit_limit_set(mps_arena_t, size_t); extern size_t mps_space_reserved(mps_space_t); extern size_t mps_space_committed(mps_space_t); diff --git a/mps/src/mpsi.c b/mps/src/mpsi.c index 59a1c817084..3758fcdd9a1 100644 --- a/mps/src/mpsi.c +++ b/mps/src/mpsi.c @@ -1,6 +1,6 @@ /* impl.c.mpsi: MEMORY POOL SYSTEM C INTERFACE LAYER * - * $HopeName: MMsrc!mpsi.c(trunk.47) $ + * $HopeName: MMsrc!mpsi.c(trunk.48) $ * Copyright (C) 1997. Harlequin Group plc. All rights reserved. * * .purpose: This code bridges between the MPS interface to C, @@ -52,7 +52,7 @@ #include "mps.h" #include "mpsavm.h" /* only for mps_space_create */ -SRCID(mpsi, "$HopeName: MMsrc!mpsi.c(trunk.47) $"); +SRCID(mpsi, "$HopeName: MMsrc!mpsi.c(trunk.48) $"); /* mpsi_check -- check consistency of interface mappings @@ -70,7 +70,7 @@ SRCID(mpsi, "$HopeName: MMsrc!mpsi.c(trunk.47) $"); static Bool mpsi_check(void) { - /* Check that external and internal result codes match. */ + /* .check.rc: Check that external and internal result codes match. */ /* See impl.h.mps.result-codes and impl.h.mpmtypes.result-codes. */ /* Also see .check.enum.cast. */ CHECKL(CHECKTYPE(mps_res_t, Res)); @@ -81,6 +81,7 @@ static Bool mpsi_check(void) CHECKL((int)MPS_RES_LIMIT == (int)ResLIMIT); CHECKL((int)MPS_RES_UNIMPL == (int)ResUNIMPL); CHECKL((int)MPS_RES_IO == (int)ResIO); + CHECKL((int)MPS_RES_COMMIT_LIMIT == (int)ResCOMMIT_LIMIT); /* Check that external and internal rank numbers match. */ /* See impl.h.mps.ranks and impl.h.mpmtypes.ranks. */ @@ -214,6 +215,29 @@ size_t mps_space_committed(mps_space_t mps_space) return mps_arena_committed(mps_space); } +size_t mps_arena_commit_limit(mps_arena_t mps_arena) +{ + Arena arena = (Arena)mps_arena; + Size size; + + ArenaEnter(arena); + size = ArenaCommitLimit(arena); + ArenaLeave(arena); + + return size; +} + +mps_res_t mps_arena_commit_limit_set(mps_arena_t mps_arena, size_t limit) +{ + Res res; + Arena arena = (Arena)mps_arena; + + ArenaEnter(arena); + res = ArenaSetCommitLimit(arena, limit); + ArenaLeave(arena); + + return res; +} void mps_arena_clamp(mps_arena_t mps_arena) {