1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-25 08:12:11 -07:00

Catch-up merge from branch/2015-08-10/arena-create to branch/2015-08-06/config.

Copied from Perforce
 Change: 188104
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2015-08-10 12:49:36 +01:00
commit 56e56e4ff4
15 changed files with 310 additions and 138 deletions

View file

@ -41,6 +41,7 @@ Bool ArenaGrainSizeCheck(Size size)
static void ArenaTrivCompact(Arena arena, Trace trace);
static void arenaFreePage(Arena arena, Addr base, Pool pool);
static void arenaFreeLandFinish(Arena arena);
/* ArenaTrivDescribe -- produce trivial description of an arena */
@ -85,7 +86,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 +113,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 +141,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 +208,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) */
@ -301,6 +304,26 @@ ARG_DEFINE_KEY(ARENA_SIZE, Size);
ARG_DEFINE_KEY(ARENA_SPARE_COMMIT_LIMIT, Size);
ARG_DEFINE_KEY(ARENA_ZONED, Bool);
static Res arenaFreeLandInit(Arena arena)
{
Res res;
AVERT(Arena, arena);
AVER(!arena->hasFreeLand);
AVER(arena->primary != NULL);
/* With the primary chunk initialised we can add page memory to the freeLand
* that describes the free address space in the primary chunk. */
res = ArenaFreeLandInsert(arena,
PageIndexBase(arena->primary,
arena->primary->allocBase),
arena->primary->limit);
if (res != ResOK)
return res;
arena->hasFreeLand = TRUE;
return ResOK;
}
Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
{
Arena arena;
@ -326,15 +349,9 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
goto failStripeSize;
}
/* With the primary chunk initialised we can add page memory to the freeLand
that describes the free address space in the primary chunk. */
res = ArenaFreeLandInsert(arena,
PageIndexBase(arena->primary,
arena->primary->allocBase),
arena->primary->limit);
res = arenaFreeLandInit(arena);
if (res != ResOK)
goto failPrimaryLand;
arena->hasFreeLand = TRUE;
goto failFreeLandInit;
res = ControlInit(arena);
if (res != ResOK)
@ -357,7 +374,8 @@ failConfigure:
failGlobalsCompleteCreate:
ControlFinish(arena);
failControlInit:
failPrimaryLand:
arenaFreeLandFinish(arena);
failFreeLandInit:
failStripeSize:
(*class->finish)(arena);
failInit:
@ -423,6 +441,20 @@ static void arenaMFSPageFreeVisitor(Pool pool, Addr base, Size size,
arenaFreePage(PoolArena(pool), base, pool);
}
static void arenaFreeLandFinish(Arena arena)
{
/* We must tear down the freeLand before the chunks, because pages
* containing CBS blocks might be allocated in those chunks. */
AVER(arena->hasFreeLand);
arena->hasFreeLand = FALSE;
LandFinish(ArenaFreeLand(arena));
/* The CBS block pool can't free its own memory via ArenaFree because
* that would use the freeLand. */
MFSFinishTracts(ArenaCBSBlockPool(arena), arenaMFSPageFreeVisitor,
UNUSED_POINTER, UNUSED_SIZE);
}
void ArenaDestroy(Arena arena)
{
AVERT(Arena, arena);
@ -432,19 +464,9 @@ void ArenaDestroy(Arena arena)
/* Empty the reservoir - see <code/reserv.c#reservoir.finish> */
ReservoirSetLimit(ArenaReservoir(arena), 0);
arena->poolReady = FALSE;
ControlFinish(arena);
/* We must tear down the freeLand before the chunks, because pages
containing CBS blocks might be allocated in those chunks. */
AVER(arena->hasFreeLand);
arena->hasFreeLand = FALSE;
LandFinish(ArenaFreeLand(arena));
/* The CBS block pool can't free its own memory via ArenaFree because
that would use the freeLand. */
MFSFinishTracts(ArenaCBSBlockPool(arena), arenaMFSPageFreeVisitor,
UNUSED_POINTER, UNUSED_SIZE);
arenaFreeLandFinish(arena);
/* Call class-specific finishing. This will call ArenaFinish. */
(*arena->class->finish)(arena);
@ -460,6 +482,7 @@ Res ControlInit(Arena arena)
Res res;
AVERT(Arena, arena);
AVER(!arena->poolReady);
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, CONTROL_EXTEND_BY);
res = PoolInit(MVPool(&arena->controlPoolStruct), arena,
@ -477,6 +500,7 @@ Res ControlInit(Arena arena)
void ControlFinish(Arena arena)
{
AVERT(Arena, arena);
AVER(arena->poolReady);
arena->poolReady = FALSE;
PoolFinish(MVPool(&arena->controlPoolStruct));
}
@ -487,7 +511,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;
@ -509,20 +532,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,
@ -702,7 +714,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;
@ -720,6 +735,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)
@ -727,6 +744,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
@ -1264,7 +1306,7 @@ allDeposited:
Size ArenaReserved(Arena arena)
{
AVERT(Arena, arena);
return (*arena->class->reserved)(arena);
return arena->reserved;
}
Size ArenaCommitted(Arena arena)

View file

@ -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);
@ -257,7 +274,7 @@ static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
AVER(base != (Addr)0);
AVERT(ArenaGrainSize, grainSize);
if (size < grainSize * MPS_WORD_SHIFT)
if (size < grainSize * MPS_WORD_WIDTH)
/* Not enough room for a full complement of zones. */
return ResMEMORY;
@ -334,6 +351,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> */
}
@ -358,27 +379,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,
@ -386,9 +386,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);
@ -397,15 +400,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" */
@ -446,6 +451,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;
}
@ -462,10 +469,9 @@ DEFINE_ARENA_CLASS(ClientArenaClass, this)
this->init = ClientArenaInit;
this->configure = ClientArenaConfigure;
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);

View file

@ -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. */
@ -650,6 +652,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;
@ -664,25 +667,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
@ -733,7 +717,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 */
{
@ -757,7 +741,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);
@ -768,7 +752,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));
@ -816,16 +800,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;
}
@ -1154,7 +1145,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>
@ -1164,7 +1155,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 */
@ -1215,7 +1206,6 @@ DEFINE_ARENA_CLASS(VMArenaClass, this)
this->init = VMArenaInit;
this->configure = VMArenaConfigure;
this->finish = VMArenaFinish;
this->reserved = VMArenaReserved;
this->purgeSpare = VMPurgeSpare;
this->grow = VMArenaGrow;
this->free = VMFree;

View file

@ -569,6 +569,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);

View file

@ -527,7 +527,6 @@ typedef struct mps_arena_class_s {
ArenaInitMethod init;
ArenaConfigureMethod configure;
ArenaFinishMethod finish;
ArenaReservedMethod reserved;
ArenaPurgeSpareMethod purgeSpare;
ArenaExtendMethod extend;
ArenaGrowMethod grow;
@ -715,7 +714,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 */

View file

@ -121,7 +121,6 @@ typedef Res (*ArenaInitMethod)(Arena *arenaReturn,
ArenaClass class, ArgList args);
typedef Res (*ArenaConfigureMethod)(Arena arena, 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);

View file

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

View file

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

View file

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