mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-23 07:12:12 -07:00
Merge branch/2014-09-29/reserved into the master sources.
Copied from Perforce Change: 188090 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
84347b9bbe
11 changed files with 142 additions and 96 deletions
|
|
@ -85,7 +85,6 @@ DEFINE_CLASS(AbstractArenaClass, class)
|
|||
class->varargs = ArgTrivVarargs;
|
||||
class->init = NULL;
|
||||
class->finish = NULL;
|
||||
class->reserved = NULL;
|
||||
class->purgeSpare = ArenaNoPurgeSpare;
|
||||
class->extend = ArenaNoExtend;
|
||||
class->grow = ArenaNoGrow;
|
||||
|
|
@ -113,7 +112,6 @@ Bool ArenaClassCheck(ArenaClass class)
|
|||
CHECKL(FUNCHECK(class->varargs));
|
||||
CHECKL(FUNCHECK(class->init));
|
||||
CHECKL(FUNCHECK(class->finish));
|
||||
CHECKL(FUNCHECK(class->reserved));
|
||||
CHECKL(FUNCHECK(class->purgeSpare));
|
||||
CHECKL(FUNCHECK(class->extend));
|
||||
CHECKL(FUNCHECK(class->grow));
|
||||
|
|
@ -142,9 +140,12 @@ Bool ArenaCheck(Arena arena)
|
|||
CHECKD(Reservoir, &arena->reservoirStruct);
|
||||
}
|
||||
|
||||
/* Can't check that limit>=size because we may call ArenaCheck */
|
||||
/* while the size is being adjusted. */
|
||||
|
||||
/* .reserved.check: Would like to check that arena->committed <=
|
||||
* arena->reserved, but that isn't always true in the VM arena.
|
||||
* Memory is committed early on when VMChunkCreate calls vmArenaMap
|
||||
* (to provide a place for the chunk struct) but is not recorded as
|
||||
* reserved until ChunkInit calls ArenaChunkInsert.
|
||||
*/
|
||||
CHECKL(arena->committed <= arena->commitLimit);
|
||||
CHECKL(arena->spareCommitted <= arena->committed);
|
||||
|
||||
|
|
@ -206,6 +207,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
|
|||
|
||||
arena->class = class;
|
||||
|
||||
arena->reserved = (Size)0;
|
||||
arena->committed = (Size)0;
|
||||
/* commitLimit may be overridden by init (but probably not */
|
||||
/* as there's not much point) */
|
||||
|
|
@ -454,7 +456,6 @@ void ControlFinish(Arena arena)
|
|||
Res ArenaDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
Size reserved;
|
||||
|
||||
if (!TESTT(Arena, arena))
|
||||
return ResFAIL;
|
||||
|
|
@ -476,20 +477,9 @@ Res ArenaDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* Note: this Describe clause calls a function */
|
||||
reserved = ArenaReserved(arena);
|
||||
res = WriteF(stream, depth + 2,
|
||||
"reserved $W <-- "
|
||||
"total size of address-space reserved\n",
|
||||
(WriteFW)reserved,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"committed $W <-- "
|
||||
"total bytes currently stored (in RAM or swap)\n",
|
||||
(WriteFW)arena->committed,
|
||||
"reserved $W\n", (WriteFW)arena->reserved,
|
||||
"committed $W\n", (WriteFW)arena->committed,
|
||||
"commitLimit $W\n", (WriteFW)arena->commitLimit,
|
||||
"spareCommitted $W\n", (WriteFW)arena->spareCommitted,
|
||||
"spareCommitLimit $W\n", (WriteFW)arena->spareCommitLimit,
|
||||
|
|
@ -669,7 +659,10 @@ Res ControlDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
|
|||
}
|
||||
|
||||
|
||||
/* ArenaChunkInsert -- insert chunk into arena's chunk tree and ring */
|
||||
/* ArenaChunkInsert -- insert chunk into arena's chunk tree and ring,
|
||||
* update the total reserved address space, and set the primary chunk
|
||||
* if not already set.
|
||||
*/
|
||||
|
||||
void ArenaChunkInsert(Arena arena, Chunk chunk) {
|
||||
Bool inserted;
|
||||
|
|
@ -687,6 +680,8 @@ void ArenaChunkInsert(Arena arena, Chunk chunk) {
|
|||
arena->chunkTree = updatedTree;
|
||||
RingAppend(&arena->chunkRing, &chunk->arenaRing);
|
||||
|
||||
arena->reserved += ChunkReserved(chunk);
|
||||
|
||||
/* As part of the bootstrap, the first created chunk becomes the primary
|
||||
chunk. This step allows ArenaFreeLandInsert to allocate pages. */
|
||||
if (arena->primary == NULL)
|
||||
|
|
@ -694,6 +689,31 @@ void ArenaChunkInsert(Arena arena, Chunk chunk) {
|
|||
}
|
||||
|
||||
|
||||
/* ArenaChunkRemoved -- chunk was removed from the arena and is being
|
||||
* finished, so update the total reserved address space, and unset the
|
||||
* primary chunk if necessary.
|
||||
*/
|
||||
|
||||
void ArenaChunkRemoved(Arena arena, Chunk chunk)
|
||||
{
|
||||
Size size;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Chunk, chunk);
|
||||
|
||||
size = ChunkReserved(chunk);
|
||||
AVER(arena->reserved >= size);
|
||||
arena->reserved -= size;
|
||||
|
||||
if (chunk == arena->primary) {
|
||||
/* The primary chunk must be the last chunk to be removed. */
|
||||
AVER(RingIsSingle(&arena->chunkRing));
|
||||
AVER(arena->reserved == 0);
|
||||
arena->primary = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* arenaAllocPage -- allocate one page from the arena
|
||||
*
|
||||
* This is a primitive allocator used to allocate pages for the arena
|
||||
|
|
@ -1231,7 +1251,7 @@ allDeposited:
|
|||
Size ArenaReserved(Arena arena)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
return (*arena->class->reserved)(arena);
|
||||
return arena->reserved;
|
||||
}
|
||||
|
||||
Size ArenaCommitted(Arena arena)
|
||||
|
|
|
|||
|
|
@ -81,8 +81,15 @@ static Bool ClientChunkCheck(ClientChunk clChunk)
|
|||
ATTRIBUTE_UNUSED
|
||||
static Bool ClientArenaCheck(ClientArena clientArena)
|
||||
{
|
||||
Arena arena;
|
||||
|
||||
CHECKS(ClientArena, clientArena);
|
||||
CHECKD(Arena, ClientArena2Arena(clientArena));
|
||||
arena = ClientArena2Arena(clientArena);
|
||||
CHECKD(Arena, arena);
|
||||
/* See <code/arena.c#.reserved.check> */
|
||||
CHECKL(arena->committed <= arena->reserved);
|
||||
CHECKL(arena->spareCommitted == 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -125,12 +132,13 @@ static Res clientChunkCreate(Chunk *chunkReturn, ClientArena clientArena,
|
|||
chunk = ClientChunk2Chunk(clChunk);
|
||||
|
||||
res = ChunkInit(chunk, arena, alignedBase,
|
||||
AddrAlignDown(limit, ArenaGrainSize(arena)), boot);
|
||||
AddrAlignDown(limit, ArenaGrainSize(arena)),
|
||||
AddrOffset(base, limit), boot);
|
||||
if (res != ResOK)
|
||||
goto failChunkInit;
|
||||
|
||||
ClientArena2Arena(clientArena)->committed +=
|
||||
AddrOffset(base, PageIndexBase(chunk, chunk->allocBase));
|
||||
arena->committed += ChunkPagesToSize(chunk, chunk->allocBase);
|
||||
|
||||
BootBlockFinish(boot);
|
||||
|
||||
clChunk->sig = ClientChunkSig;
|
||||
|
|
@ -176,8 +184,10 @@ static Res ClientChunkInit(Chunk chunk, BootBlock boot)
|
|||
|
||||
static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
|
||||
{
|
||||
Arena arena;
|
||||
Chunk chunk;
|
||||
ClientChunk clChunk;
|
||||
Size size;
|
||||
|
||||
AVERT(Tree, tree);
|
||||
AVER(closureP == UNUSED_POINTER);
|
||||
|
|
@ -187,8 +197,15 @@ static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
|
|||
|
||||
chunk = ChunkOfTree(tree);
|
||||
AVERT(Chunk, chunk);
|
||||
arena = ChunkArena(chunk);
|
||||
AVERT(Arena, arena);
|
||||
clChunk = Chunk2ClientChunk(chunk);
|
||||
AVERT(ClientChunk, clChunk);
|
||||
AVER(chunk->pages == clChunk->freePages);
|
||||
|
||||
size = ChunkPagesToSize(chunk, chunk->allocBase);
|
||||
AVER(arena->committed >= size);
|
||||
arena->committed -= size;
|
||||
|
||||
clChunk->sig = SigInvalid;
|
||||
ChunkFinish(chunk);
|
||||
|
|
@ -324,6 +341,10 @@ static void ClientArenaFinish(Arena arena)
|
|||
|
||||
clientArena->sig = SigInvalid;
|
||||
|
||||
/* Destroying the chunks should leave nothing behind. */
|
||||
AVER(arena->reserved == 0);
|
||||
AVER(arena->committed == 0);
|
||||
|
||||
ArenaFinish(arena); /* <code/arena.c#finish.caller> */
|
||||
}
|
||||
|
||||
|
|
@ -348,27 +369,6 @@ static Res ClientArenaExtend(Arena arena, Addr base, Size size)
|
|||
}
|
||||
|
||||
|
||||
/* ClientArenaReserved -- return the amount of reserved address space */
|
||||
|
||||
static Size ClientArenaReserved(Arena arena)
|
||||
{
|
||||
Size size;
|
||||
Ring node, nextNode;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
|
||||
size = 0;
|
||||
/* .req.extend.slow */
|
||||
RING_FOR(node, &arena->chunkRing, nextNode) {
|
||||
Chunk chunk = RING_ELT(Chunk, arenaRing, node);
|
||||
AVERT(Chunk, chunk);
|
||||
size += ChunkSize(chunk);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* ClientArenaPagesMarkAllocated -- Mark the pages allocated */
|
||||
|
||||
static Res ClientArenaPagesMarkAllocated(Arena arena, Chunk chunk,
|
||||
|
|
@ -376,9 +376,12 @@ static Res ClientArenaPagesMarkAllocated(Arena arena, Chunk chunk,
|
|||
Pool pool)
|
||||
{
|
||||
Index i;
|
||||
ClientChunk clChunk;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Chunk, chunk);
|
||||
clChunk = Chunk2ClientChunk(chunk);
|
||||
AVERT(ClientChunk, clChunk);
|
||||
AVER(chunk->allocBase <= baseIndex);
|
||||
AVER(pages > 0);
|
||||
AVER(baseIndex + pages <= chunk->pages);
|
||||
|
|
@ -387,15 +390,17 @@ static Res ClientArenaPagesMarkAllocated(Arena arena, Chunk chunk,
|
|||
for (i = 0; i < pages; ++i)
|
||||
PageAlloc(chunk, baseIndex + i, pool);
|
||||
|
||||
Chunk2ClientChunk(chunk)->freePages -= pages;
|
||||
arena->committed += ChunkPagesToSize(chunk, pages);
|
||||
AVER(clChunk->freePages >= pages);
|
||||
clChunk->freePages -= pages;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* ClientFree - free a region in the arena */
|
||||
/* ClientArenaFree - free a region in the arena */
|
||||
|
||||
static void ClientFree(Addr base, Size size, Pool pool)
|
||||
static void ClientArenaFree(Addr base, Size size, Pool pool)
|
||||
{
|
||||
Arena arena;
|
||||
Chunk chunk = NULL; /* suppress "may be used uninitialized" */
|
||||
|
|
@ -436,6 +441,8 @@ static void ClientFree(Addr base, Size size, Pool pool)
|
|||
AVER(BTIsSetRange(chunk->allocTable, baseIndex, limitIndex));
|
||||
BTResRange(chunk->allocTable, baseIndex, limitIndex);
|
||||
|
||||
AVER(arena->committed >= size);
|
||||
arena->committed -= size;
|
||||
clChunk->freePages += pages;
|
||||
}
|
||||
|
||||
|
|
@ -451,10 +458,9 @@ DEFINE_ARENA_CLASS(ClientArenaClass, this)
|
|||
this->varargs = ClientArenaVarargs;
|
||||
this->init = ClientArenaInit;
|
||||
this->finish = ClientArenaFinish;
|
||||
this->reserved = ClientArenaReserved;
|
||||
this->extend = ClientArenaExtend;
|
||||
this->pagesMarkAllocated = ClientArenaPagesMarkAllocated;
|
||||
this->free = ClientFree;
|
||||
this->free = ClientArenaFree;
|
||||
this->chunkInit = ClientChunkInit;
|
||||
this->chunkFinish = ClientChunkFinish;
|
||||
AVERT(ArenaClass, this);
|
||||
|
|
|
|||
|
|
@ -323,7 +323,8 @@ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
|
|||
|
||||
/* Copy VM descriptor into its place in the chunk. */
|
||||
VMCopy(VMChunkVM(vmChunk), vm);
|
||||
res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit, boot);
|
||||
res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit,
|
||||
VMReserved(VMChunkVM(vmChunk)), boot);
|
||||
if (res != ResOK)
|
||||
goto failChunkInit;
|
||||
|
||||
|
|
@ -560,6 +561,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
res = ArenaInit(arena, class, grainSize, args);
|
||||
if (res != ResOK)
|
||||
goto failArenaInit;
|
||||
arena->reserved = VMReserved(vm);
|
||||
arena->committed = VMMapped(vm);
|
||||
|
||||
/* Copy VM descriptor into its place in the arena. */
|
||||
|
|
@ -640,6 +642,7 @@ static void VMArenaFinish(Arena arena)
|
|||
RingFinish(&vmArena->spareRing);
|
||||
|
||||
/* Destroying the chunks should leave only the arena's own VM. */
|
||||
AVER(arena->reserved == VMReserved(VMArenaVM(vmArena)));
|
||||
AVER(arena->committed == VMMapped(VMArenaVM(vmArena)));
|
||||
|
||||
vmArena->sig = SigInvalid;
|
||||
|
|
@ -654,25 +657,6 @@ static void VMArenaFinish(Arena arena)
|
|||
}
|
||||
|
||||
|
||||
/* VMArenaReserved -- return the amount of reserved address space
|
||||
*
|
||||
* Add up the reserved space from all the chunks.
|
||||
*/
|
||||
|
||||
static Size VMArenaReserved(Arena arena)
|
||||
{
|
||||
Size reserved;
|
||||
Ring node, next;
|
||||
|
||||
reserved = 0;
|
||||
RING_FOR(node, &arena->chunkRing, next) {
|
||||
VMChunk vmChunk = Chunk2VMChunk(RING_ELT(Chunk, arenaRing, node));
|
||||
reserved += VMReserved(VMChunkVM(vmChunk));
|
||||
}
|
||||
return reserved;
|
||||
}
|
||||
|
||||
|
||||
/* vmArenaChunkSize -- choose chunk size for arena extension
|
||||
*
|
||||
* .vmchunk.overhead: This code still lacks a proper estimate of
|
||||
|
|
@ -723,7 +707,7 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
|||
chunkSize = vmArenaChunkSize(vmArena, size);
|
||||
|
||||
EVENT3(vmArenaExtendStart, size, chunkSize,
|
||||
VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
ArenaReserved(VMArena2Arena(vmArena)));
|
||||
|
||||
/* .chunk-create.fail: If we fail, try again with a smaller size */
|
||||
{
|
||||
|
|
@ -747,7 +731,7 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
|||
for(; chunkSize > chunkHalf; chunkSize -= sliceSize) {
|
||||
if(chunkSize < chunkMin) {
|
||||
EVENT2(vmArenaExtendFail, chunkMin,
|
||||
VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
ArenaReserved(VMArena2Arena(vmArena)));
|
||||
return res;
|
||||
}
|
||||
res = VMChunkCreate(&newChunk, vmArena, chunkSize);
|
||||
|
|
@ -758,7 +742,7 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
|||
}
|
||||
|
||||
vmArenaGrow_Done:
|
||||
EVENT2(vmArenaExtendDone, chunkSize, VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
EVENT2(vmArenaExtendDone, chunkSize, ArenaReserved(VMArena2Arena(vmArena)));
|
||||
vmArena->extended(VMArena2Arena(vmArena),
|
||||
newChunk->base,
|
||||
AddrOffset(newChunk->base, newChunk->limit));
|
||||
|
|
@ -806,16 +790,23 @@ static Res pageDescMap(VMChunk vmChunk, Index basePI, Index limitPI)
|
|||
Size before = VMMapped(VMChunkVM(vmChunk));
|
||||
Arena arena = VMArena2Arena(VMChunkVMArena(vmChunk));
|
||||
Res res = SparseArrayMap(&vmChunk->pages, basePI, limitPI);
|
||||
arena->committed += VMMapped(VMChunkVM(vmChunk)) - before;
|
||||
Size after = VMMapped(VMChunkVM(vmChunk));
|
||||
AVER(before <= after);
|
||||
arena->committed += after - before;
|
||||
return res;
|
||||
}
|
||||
|
||||
static void pageDescUnmap(VMChunk vmChunk, Index basePI, Index limitPI)
|
||||
{
|
||||
Size size, after;
|
||||
Size before = VMMapped(VMChunkVM(vmChunk));
|
||||
Arena arena = VMArena2Arena(VMChunkVMArena(vmChunk));
|
||||
SparseArrayUnmap(&vmChunk->pages, basePI, limitPI);
|
||||
arena->committed += VMMapped(VMChunkVM(vmChunk)) - before;
|
||||
after = VMMapped(VMChunkVM(vmChunk));
|
||||
AVER(after <= before);
|
||||
size = before - after;
|
||||
AVER(arena->committed >= size);
|
||||
arena->committed -= size;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1144,7 +1135,7 @@ static void VMCompact(Arena arena, Trace trace)
|
|||
AVERT(VMArena, vmArena);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
vmem1 = VMArenaReserved(arena);
|
||||
vmem1 = ArenaReserved(arena);
|
||||
|
||||
/* Destroy chunks that are completely free, but not the primary
|
||||
* chunk. See <design/arena/#chunk.delete>
|
||||
|
|
@ -1154,7 +1145,7 @@ static void VMCompact(Arena arena, Trace trace)
|
|||
|
||||
{
|
||||
Size vmem0 = trace->preTraceArenaReserved;
|
||||
Size vmem2 = VMArenaReserved(arena);
|
||||
Size vmem2 = ArenaReserved(arena);
|
||||
|
||||
/* VMCompact event: emit for all client-requested collections, */
|
||||
/* plus any others where chunks were gained or lost during the */
|
||||
|
|
@ -1204,7 +1195,6 @@ DEFINE_ARENA_CLASS(VMArenaClass, this)
|
|||
this->varargs = VMArenaVarargs;
|
||||
this->init = VMArenaInit;
|
||||
this->finish = VMArenaFinish;
|
||||
this->reserved = VMArenaReserved;
|
||||
this->purgeSpare = VMPurgeSpare;
|
||||
this->grow = VMArenaGrow;
|
||||
this->free = VMFree;
|
||||
|
|
|
|||
|
|
@ -568,6 +568,7 @@ extern Res ArenaCollect(Globals globals, int why);
|
|||
extern Bool ArenaHasAddr(Arena arena, Addr addr);
|
||||
extern Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr);
|
||||
extern void ArenaChunkInsert(Arena arena, Chunk chunk);
|
||||
extern void ArenaChunkRemoved(Arena arena, Chunk chunk);
|
||||
|
||||
extern void ArenaSetEmergency(Arena arena, Bool emergency);
|
||||
extern Bool ArenaEmergency(Arena arean);
|
||||
|
|
|
|||
|
|
@ -526,7 +526,6 @@ typedef struct mps_arena_class_s {
|
|||
ArenaVarargsMethod varargs;
|
||||
ArenaInitMethod init;
|
||||
ArenaFinishMethod finish;
|
||||
ArenaReservedMethod reserved;
|
||||
ArenaPurgeSpareMethod purgeSpare;
|
||||
ArenaExtendMethod extend;
|
||||
ArenaGrowMethod grow;
|
||||
|
|
@ -714,7 +713,8 @@ typedef struct mps_arena_s {
|
|||
|
||||
ReservoirStruct reservoirStruct; /* <design/reservoir/> */
|
||||
|
||||
Size committed; /* amount of committed RAM */
|
||||
Size reserved; /* total reserved address space */
|
||||
Size committed; /* total committed memory */
|
||||
Size commitLimit; /* client-configurable commit limit */
|
||||
|
||||
Size spareCommitted; /* Amount of memory in hysteresis fund */
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ typedef void (*ArenaVarargsMethod)(ArgStruct args[], va_list varargs);
|
|||
typedef Res (*ArenaInitMethod)(Arena *arenaReturn,
|
||||
ArenaClass class, ArgList args);
|
||||
typedef void (*ArenaFinishMethod)(Arena arena);
|
||||
typedef Size (*ArenaReservedMethod)(Arena arena);
|
||||
typedef Size (*ArenaPurgeSpareMethod)(Arena arena, Size size);
|
||||
typedef Res (*ArenaExtendMethod)(Arena arena, Addr base, Size size);
|
||||
typedef Res (*ArenaGrowMethod)(Arena arena, LocusPref pref, Size size);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ Bool ReservoirCheck(Reservoir reservoir)
|
|||
}
|
||||
CHECKL(SizeIsArenaGrains(reservoir->reservoirLimit, arena));
|
||||
CHECKL(SizeIsArenaGrains(reservoir->reservoirSize, arena));
|
||||
CHECKL(reservoir->reservoirSize <= reservoir->reservoirLimit);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,8 @@ Bool ChunkCheck(Chunk chunk)
|
|||
|
||||
/* ChunkInit -- initialize generic part of chunk */
|
||||
|
||||
Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, BootBlock boot)
|
||||
Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
|
||||
BootBlock boot)
|
||||
{
|
||||
Size size;
|
||||
Count pages;
|
||||
|
|
@ -192,6 +193,7 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, BootBlock boot)
|
|||
chunk->pageShift = pageShift = SizeLog2(chunk->pageSize);
|
||||
chunk->base = base;
|
||||
chunk->limit = limit;
|
||||
chunk->reserved = reserved;
|
||||
size = ChunkSize(chunk);
|
||||
|
||||
chunk->pages = pages = size >> pageShift;
|
||||
|
|
@ -262,17 +264,16 @@ void ChunkFinish(Chunk chunk)
|
|||
PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
|
||||
ArenaChunkRemoved(arena, chunk);
|
||||
|
||||
chunk->sig = SigInvalid;
|
||||
|
||||
TreeFinish(&chunk->chunkTree);
|
||||
RingRemove(&chunk->arenaRing);
|
||||
|
||||
if (chunk->arena->primary == chunk)
|
||||
chunk->arena->primary = NULL;
|
||||
|
||||
/* Finish all other fields before class finish, because they might be */
|
||||
/* unmapped there. */
|
||||
(chunk->arena->class->chunkFinish)(chunk);
|
||||
(*arena->class->chunkFinish)(chunk);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,9 @@ typedef struct ChunkStruct {
|
|||
BT allocTable; /* page allocation table */
|
||||
Page pageTable; /* the page table */
|
||||
Count pageTablePages; /* number of pages occupied by page table */
|
||||
Size reserved; /* reserved address space for chunk (including overhead
|
||||
such as losses due to alignment): must not change
|
||||
(or arena reserved calculation will break) */
|
||||
} ChunkStruct;
|
||||
|
||||
|
||||
|
|
@ -159,10 +162,11 @@ typedef struct ChunkStruct {
|
|||
#define ChunkSizeToPages(chunk, size) ((Count)((size) >> (chunk)->pageShift))
|
||||
#define ChunkPage(chunk, pi) (&(chunk)->pageTable[pi])
|
||||
#define ChunkOfTree(tree) PARENT(ChunkStruct, chunkTree, tree)
|
||||
#define ChunkReserved(chunk) RVALUE((chunk)->reserved)
|
||||
|
||||
extern Bool ChunkCheck(Chunk chunk);
|
||||
extern Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit,
|
||||
BootBlock boot);
|
||||
Size reserved, BootBlock boot);
|
||||
extern void ChunkFinish(Chunk chunk);
|
||||
extern Compare ChunkCompare(Tree tree, TreeKey key);
|
||||
extern TreeKey ChunkKey(Tree tree);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,16 @@ Interface changes
|
|||
:c:func:`mps_pool_free_size` and :c:func:`mps_pool_total_size`.
|
||||
|
||||
|
||||
Other changes
|
||||
.............
|
||||
|
||||
#. :c:func:`mps_arena_committed` now returns a meaningful value (the
|
||||
amount of memory marked as in use in the page tables) for
|
||||
:term:`client arenas`. See job001887_.
|
||||
|
||||
.. _job001887: https://www.ravenbrook.com/project/mps/issue/job001887/
|
||||
|
||||
|
||||
.. _release-notes-1.114:
|
||||
|
||||
Release 1.114.0
|
||||
|
|
|
|||
|
|
@ -347,9 +347,18 @@ Arena properties
|
|||
|
||||
``arena`` is the arena.
|
||||
|
||||
Returns the total amount of memory that has been committed to RAM
|
||||
Returns the total amount of memory that has been committed for use
|
||||
by the MPS, in :term:`bytes (1)`.
|
||||
|
||||
For a :term:`virtual memory arena`, this is the amount of memory
|
||||
mapped to RAM by the operating system's virtual memory interface.
|
||||
|
||||
For a :term:`client arena`, this is the amount of memory marked as
|
||||
in use in the arena's page tables. This is not particularly
|
||||
meaningful by itself, but it corresponds to the amount of mapped
|
||||
memory that the MPS would use if switched to a virtual memory
|
||||
arena.
|
||||
|
||||
The committed memory is generally larger than the sum of the sizes
|
||||
of the allocated :term:`blocks`. The reasons for this are:
|
||||
|
||||
|
|
@ -379,7 +388,7 @@ Arena properties
|
|||
estimate the size of the heap.
|
||||
|
||||
If you want to know how much memory the MPS is using then you're
|
||||
probably interested in the value :c:func:`mps_arena_committed()` −
|
||||
probably interested in the value :c:func:`mps_arena_committed` −
|
||||
:c:func:`mps_arena_spare_committed`.
|
||||
|
||||
The amount of committed memory can be limited with the function
|
||||
|
|
@ -403,12 +412,12 @@ Arena properties
|
|||
|
||||
.. note::
|
||||
|
||||
For a client arena, the reserved address may be lower than the
|
||||
sum of the :c:macro:`MPS_KEY_ARENA_SIZE` keyword argument
|
||||
passed to :c:func:`mps_arena_create_k` and the ``size``
|
||||
arguments passed to :c:func:`mps_arena_extend`, because the
|
||||
arena may be unable to use the whole of each chunk for reasons
|
||||
of alignment.
|
||||
For a :term:`client arena`, the reserved address space may be
|
||||
lower than the sum of the :c:macro:`MPS_KEY_ARENA_SIZE`
|
||||
keyword argument passed to :c:func:`mps_arena_create_k` and
|
||||
the ``size`` arguments passed to :c:func:`mps_arena_extend`,
|
||||
because the arena may be unable to use the whole of each chunk
|
||||
for reasons of alignment.
|
||||
|
||||
|
||||
.. c:function:: size_t mps_arena_spare_commit_limit(mps_arena_t arena)
|
||||
|
|
@ -473,6 +482,11 @@ Arena properties
|
|||
functions for limiting the amount of :term:`committed <mapped>`
|
||||
memory.
|
||||
|
||||
.. note::
|
||||
|
||||
:term:`Client arenas` do not use spare committed memory, and
|
||||
so this function always returns 0.
|
||||
|
||||
|
||||
.. index::
|
||||
single: arena; states
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue