mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-24 06:20:43 -08:00
Merge branch/2016-04-11/job003998.
Copied from Perforce Change: 191388 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
ffcd3f0b7b
4 changed files with 92 additions and 38 deletions
|
|
@ -954,6 +954,7 @@ Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
|
|||
Res res;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVER(base < limit);
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = arenaFreeLandInsertExtend(&oldRange, arena, &range);
|
||||
|
|
|
|||
|
|
@ -308,8 +308,7 @@ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
|
|||
if (res != ResOK)
|
||||
goto failBootInit;
|
||||
|
||||
/* Allocate and map the descriptor. */
|
||||
/* See <design/arena/>.@@@@ */
|
||||
/* .overhead.chunk-struct: Allocate and map the chunk structure. */
|
||||
res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN);
|
||||
if (res != ResOK)
|
||||
goto failChunkAlloc;
|
||||
|
|
@ -361,11 +360,13 @@ static Res VMChunkInit(Chunk chunk, BootBlock boot)
|
|||
vmChunk = Chunk2VMChunk(chunk);
|
||||
AVERT(BootBlock, boot);
|
||||
|
||||
/* .overhead.sa-mapped: Chunk overhead for sparse array 'mapped' table. */
|
||||
res = BootAlloc(&p, boot, BTSize(chunk->pages), MPS_PF_ALIGN);
|
||||
if (res != ResOK)
|
||||
goto failSaMapped;
|
||||
saMapped = p;
|
||||
|
||||
/* .overhead.sa-pages: Chunk overhead for sparse array 'pages' table. */
|
||||
res = BootAlloc(&p, boot, BTSize(chunk->pageTablePages), MPS_PF_ALIGN);
|
||||
if (res != ResOK)
|
||||
goto failSaPages;
|
||||
|
|
@ -373,8 +374,8 @@ static Res VMChunkInit(Chunk chunk, BootBlock boot)
|
|||
|
||||
overheadLimit = AddrAdd(chunk->base, (Size)BootAllocated(boot));
|
||||
|
||||
/* Put the page table as late as possible, as in VM systems we don't want */
|
||||
/* to map it. */
|
||||
/* .overhead.page-table: Put the page table as late as possible, as
|
||||
* in VM systems we don't want to map it. */
|
||||
res = BootAlloc(&p, boot, chunk->pageTablePages << chunk->pageShift, chunk->pageSize);
|
||||
if (res != ResOK)
|
||||
goto failAllocPageTable;
|
||||
|
|
@ -491,6 +492,64 @@ static void vmArenaTrivContracted(Arena arena, Addr base, Size size)
|
|||
}
|
||||
|
||||
|
||||
/* vmArenaChunkSize -- compute chunk size
|
||||
*
|
||||
* Compute the size of the smallest chunk that has size bytes of usable
|
||||
* address space (that is, after all overheads are accounted for).
|
||||
*
|
||||
* If successful, update *chunkSizeReturn with the computed chunk size
|
||||
* and return ResOK. If size is too large for a chunk, leave
|
||||
* *chunkSizeReturn unchanged and return ResRESOURCE.
|
||||
*/
|
||||
static Res vmArenaChunkSize(Size *chunkSizeReturn, VMArena vmArena, Size size)
|
||||
{
|
||||
Size grainSize; /* Arena grain size. */
|
||||
Shift grainShift; /* The corresponding Shift. */
|
||||
Count pages; /* Number of usable pages in chunk. */
|
||||
Size pageTableSize; /* Size of the page table. */
|
||||
Count pageTablePages; /* Number of pages in the page table. */
|
||||
Size chunkSize; /* Size of the chunk. */
|
||||
Size overhead; /* Total overheads for the chunk. */
|
||||
|
||||
AVER(chunkSizeReturn != NULL);
|
||||
AVERT(VMArena, vmArena);
|
||||
AVER(size > 0);
|
||||
|
||||
grainSize = ArenaGrainSize(VMArena2Arena(vmArena));
|
||||
grainShift = SizeLog2(grainSize);
|
||||
|
||||
overhead = 0;
|
||||
do {
|
||||
chunkSize = size + overhead;
|
||||
|
||||
/* See .overhead.chunk-struct. */
|
||||
overhead = SizeAlignUp(sizeof(VMChunkStruct), MPS_PF_ALIGN);
|
||||
|
||||
/* See <code/tract.c#overhead.pages>, */
|
||||
pages = chunkSize >> grainShift;
|
||||
overhead += SizeAlignUp(BTSize(pages), MPS_PF_ALIGN);
|
||||
|
||||
/* See .overhead.sa-mapped. */
|
||||
overhead += SizeAlignUp(BTSize(pages), MPS_PF_ALIGN);
|
||||
|
||||
/* See .overhead.sa-pages. */
|
||||
pageTableSize = SizeAlignUp(pages * sizeof(PageUnion), grainSize);
|
||||
pageTablePages = pageTableSize >> grainShift;
|
||||
overhead += SizeAlignUp(BTSize(pageTablePages), MPS_PF_ALIGN);
|
||||
|
||||
/* See .overhead.page-table. */
|
||||
overhead = SizeAlignUp(overhead, grainSize);
|
||||
overhead += SizeAlignUp(pageTableSize, grainSize);
|
||||
|
||||
if (SizeMAX - overhead < size)
|
||||
return ResRESOURCE;
|
||||
} while (chunkSize < size + overhead);
|
||||
|
||||
*chunkSizeReturn = chunkSize;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* VMArenaInit -- create and initialize the VM arena
|
||||
*
|
||||
* .arena.init: Once the arena has been allocated, we call ArenaInit
|
||||
|
|
@ -589,6 +648,19 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
if (res != ResOK)
|
||||
goto failChunkCreate;
|
||||
|
||||
#if defined(AVER_AND_CHECK_ALL)
|
||||
/* Check that the computation of the chunk size in vmArenaChunkSize
|
||||
* was correct, now that we have the actual chunk for comparison. */
|
||||
{
|
||||
Size usableSize, computedChunkSize;
|
||||
usableSize = AddrOffset(PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
res = vmArenaChunkSize(&computedChunkSize, vmArena, usableSize);
|
||||
AVER(res == ResOK);
|
||||
AVER(computedChunkSize == ChunkSize(chunk));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* .zoneshift: Set the zone shift to divide the chunk into the same */
|
||||
/* number of stripes as will fit into a reference set (the number of */
|
||||
/* bits in a word). Fail if the chunk is so small stripes are smaller */
|
||||
|
|
@ -655,42 +727,16 @@ static void VMArenaFinish(Arena arena)
|
|||
}
|
||||
|
||||
|
||||
/* vmArenaChunkSize -- choose chunk size for arena extension
|
||||
*
|
||||
* .vmchunk.overhead: This code still lacks a proper estimate of
|
||||
* the overhead required by a vmChunk for chunkStruct, page tables
|
||||
* etc. For now, estimate it as 10%. RHSK 2007-12-21
|
||||
*/
|
||||
static Size vmArenaChunkSize(VMArena vmArena, Size size)
|
||||
{
|
||||
Size fraction = 10; /* 10% -- see .vmchunk.overhead */
|
||||
Size chunkSize;
|
||||
Size chunkOverhead;
|
||||
|
||||
/* 1: use extendBy, if it is big enough for size + overhead */
|
||||
chunkSize = vmArena->extendBy;
|
||||
chunkOverhead = chunkSize / fraction;
|
||||
if(chunkSize > size && (chunkSize - size) >= chunkOverhead)
|
||||
return chunkSize;
|
||||
|
||||
/* 2: use size + overhead (unless it overflows SizeMAX) */
|
||||
chunkOverhead = size / (fraction - 1);
|
||||
if((SizeMAX - size) >= chunkOverhead)
|
||||
return size + chunkOverhead;
|
||||
|
||||
/* 3: use SizeMAX */
|
||||
return SizeMAX;
|
||||
}
|
||||
|
||||
|
||||
/* VMArenaGrow -- Extend the arena by making a new chunk
|
||||
*
|
||||
* The size arg specifies how much we wish to allocate after the extension.
|
||||
* size specifies how much we wish to allocate after the extension.
|
||||
* pref specifies the preference for the location of the allocation.
|
||||
*/
|
||||
static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
||||
{
|
||||
Chunk newChunk;
|
||||
Size chunkSize;
|
||||
Size chunkMin;
|
||||
Res res;
|
||||
VMArena vmArena;
|
||||
|
||||
|
|
@ -702,7 +748,10 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
|||
AVERT(LocusPref, pref);
|
||||
UNUSED(pref);
|
||||
|
||||
chunkSize = vmArenaChunkSize(vmArena, size);
|
||||
res = vmArenaChunkSize(&chunkMin, vmArena, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
chunkSize = vmArena->extendBy;
|
||||
|
||||
EVENT3(vmArenaExtendStart, size, chunkSize,
|
||||
ArenaReserved(VMArena2Arena(vmArena)));
|
||||
|
|
@ -711,7 +760,6 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
|||
{
|
||||
unsigned fidelity = 8; /* max fraction of addr-space we may 'waste' */
|
||||
Size chunkHalf;
|
||||
Size chunkMin = 4 * 1024; /* typical single page */
|
||||
Size sliceSize;
|
||||
|
||||
if (vmArena->extendMin > chunkMin)
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ Res LandInsert(Range rangeReturn, Land land, Range range)
|
|||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, land->alignment));
|
||||
AVER(!RangeIsEmpty(range));
|
||||
landEnter(land);
|
||||
|
||||
res = (*land->class->insert)(rangeReturn, land, range);
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
|
|||
Count pages;
|
||||
Shift pageShift;
|
||||
Size pageTableSize;
|
||||
Addr allocBase;
|
||||
void *p;
|
||||
Res res;
|
||||
|
||||
|
|
@ -196,6 +197,7 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
|
|||
chunk->reserved = reserved;
|
||||
size = ChunkSize(chunk);
|
||||
|
||||
/* .overhead.pages: Chunk overhead for the page allocation table. */
|
||||
chunk->pages = pages = size >> pageShift;
|
||||
res = BootAlloc(&p, boot, (size_t)BTSize(pages), MPS_PF_ALIGN);
|
||||
if (res != ResOK)
|
||||
|
|
@ -219,12 +221,14 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
|
|||
/* Init allocTable after class init, because it might be mapped there. */
|
||||
BTResRange(chunk->allocTable, 0, pages);
|
||||
|
||||
/* Check that there is some usable address space remaining in the chunk. */
|
||||
allocBase = PageIndexBase(chunk, chunk->allocBase);
|
||||
AVER(allocBase < chunk->limit);
|
||||
|
||||
/* Add the chunk's free address space to the arena's freeLand, so that
|
||||
we can allocate from it. */
|
||||
if (arena->hasFreeLand) {
|
||||
res = ArenaFreeLandInsert(arena,
|
||||
PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
res = ArenaFreeLandInsert(arena, allocBase, chunk->limit);
|
||||
if (res != ResOK)
|
||||
goto failLandInsert;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue