1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-12 09:51:05 -07:00

Encapsulate the artifical ageing and reclaiming that's need to ensure that all the memory in a segment is accounted as free. addresses point made by rb in <https://info.ravenbrook.com/mail/2014/06/02/15-43-00/0/>

Copied from Perforce
 Change: 186428
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-06-08 13:12:12 +01:00
parent c9aef36d67
commit 03f8b41b44
7 changed files with 63 additions and 49 deletions

View file

@ -1,7 +1,7 @@
/* chain.h: GENERATION CHAINS
*
* $Id$
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*/
#ifndef chain_h
@ -90,7 +90,8 @@ extern Res PoolGenInit(PoolGen pgen, GenDesc gen, Pool pool);
extern void PoolGenFinish(PoolGen pgen);
extern Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class,
Size size, Bool withReservoirPermit, ArgList args);
extern void PoolGenFree(PoolGen pgen, Seg seg);
extern void PoolGenFree(PoolGen pgen, Seg seg, Size freeSize, Size oldSize,
Size newSize, Bool deferred);
extern void PoolGenAccountForFill(PoolGen pgen, Size size, Bool deferred);
extern void PoolGenAccountForEmpty(PoolGen pgen, Size unused, Bool deferred);
extern void PoolGenAccountForAge(PoolGen pgen, Size aged, Bool deferred);
@ -104,7 +105,7 @@ extern void PoolGenAccountForSegMerge(PoolGen pgen);
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -630,13 +630,15 @@ void PoolGenAccountForSegMerge(PoolGen pgen)
/* PoolGenFree -- free a segment and update accounting
*
* Call this when all the memory in the segment is accounted as free.
* (If not, call PoolGenAccountForAge and then PoolGenAccountForReclaim first.)
* Pass the amount of memory in the segment that is accounted as free,
* old, or new, respectively. The deferred flag is as for
* PoolGenAccountForFill.
*
* See <design/strategy/#accounting.op.free>
*/
void PoolGenFree(PoolGen pgen, Seg seg)
void PoolGenFree(PoolGen pgen, Seg seg, Size freeSize, Size oldSize,
Size newSize, Bool deferred)
{
Size size;
@ -644,6 +646,13 @@ void PoolGenFree(PoolGen pgen, Seg seg)
AVERT(Seg, seg);
size = SegSize(seg);
AVER(freeSize + oldSize + newSize == size);
/* Pretend to age and reclaim the contents of the segment to ensure
* that the entire segment is accounted as free. */
PoolGenAccountForAge(pgen, newSize, deferred);
PoolGenAccountForReclaim(pgen, oldSize + newSize, deferred);
AVER(pgen->totalSize >= size);
pgen->totalSize -= size;
STATISTIC_STAT ({

View file

@ -953,13 +953,12 @@ static void AMCFinish(Pool pool)
Seg seg = SegOfPoolRing(node);
amcGen gen = amcSegGen(seg);
amcSeg amcseg = Seg2amcSeg(seg);
if (!amcseg->old) {
PoolGenAccountForAge(&gen->pgen, SegSize(seg), amcseg->deferred);
amcseg->old = TRUE;
}
PoolGenAccountForReclaim(&gen->pgen, SegSize(seg), amcseg->deferred);
PoolGenFree(&gen->pgen, seg);
AVERT(amcSeg, amcseg);
PoolGenFree(&gen->pgen, seg,
0,
amcseg->old ? SegSize(seg) : 0,
amcseg->old ? 0 : SegSize(seg),
amcseg->deferred);
}
/* Disassociate forwarding buffers from gens before they are */
@ -2004,8 +2003,7 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
/* We may not free a buffered seg. */
AVER(SegBuffer(seg) == NULL);
PoolGenAccountForReclaim(&gen->pgen, SegSize(seg), Seg2amcSeg(seg)->deferred);
PoolGenFree(&gen->pgen, seg);
PoolGenFree(&gen->pgen, seg, 0, SegSize(seg), 0, Seg2amcSeg(seg)->deferred);
} else {
/* Seg retained */
STATISTIC_STAT( {
@ -2083,8 +2081,7 @@ static void AMCReclaim(Pool pool, Trace trace, Seg seg)
trace->reclaimSize += SegSize(seg);
PoolGenAccountForReclaim(&gen->pgen, SegSize(seg), Seg2amcSeg(seg)->deferred);
PoolGenFree(&gen->pgen, seg);
PoolGenFree(&gen->pgen, seg, 0, SegSize(seg), 0, Seg2amcSeg(seg)->deferred);
}

View file

@ -736,16 +736,14 @@ static void AMSSegsDestroy(AMS ams)
RING_FOR(node, ring, next) {
Seg seg = SegOfPoolRing(node);
AMSSeg amsseg = Seg2AMSSeg(seg);
AVERT(AMSSeg, amsseg);
AVER(amsseg->ams == ams);
AMSSegFreeCheck(amsseg);
PoolGenAccountForAge(&ams->pgen, AMSGrainsSize(ams, amsseg->newGrains), FALSE);
amsseg->oldGrains += amsseg->newGrains;
amsseg->newGrains = 0;
PoolGenAccountForReclaim(&ams->pgen, AMSGrainsSize(ams, amsseg->oldGrains), FALSE);
amsseg->freeGrains += amsseg->oldGrains;
amsseg->oldGrains = 0;
AVER(amsseg->freeGrains == amsseg->grains);
PoolGenFree(&ams->pgen, seg);
PoolGenFree(&ams->pgen, seg,
AMSGrainsSize(ams, amsseg->freeGrains),
AMSGrainsSize(ams, amsseg->oldGrains),
AMSGrainsSize(ams, amsseg->newGrains),
FALSE);
}
}
@ -1636,7 +1634,11 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg)
if (amsseg->freeGrains == grains && SegBuffer(seg) == NULL)
/* No survivors */
PoolGenFree(&ams->pgen, seg);
PoolGenFree(&ams->pgen, seg,
AMSGrainsSize(ams, amsseg->freeGrains),
AMSGrainsSize(ams, amsseg->oldGrains),
AMSGrainsSize(ams, amsseg->newGrains),
FALSE);
}

View file

@ -609,14 +609,12 @@ static void AWLFinish(Pool pool)
RING_FOR(node, ring, nextNode) {
Seg seg = SegOfPoolRing(node);
AWLSeg awlseg = Seg2AWLSeg(seg);
PoolGenAccountForAge(&awl->pgen, AWLGrainsSize(awl, awlseg->newGrains), FALSE);
awlseg->oldGrains += awlseg->newGrains;
awlseg->newGrains = 0;
PoolGenAccountForReclaim(&awl->pgen, AWLGrainsSize(awl, awlseg->oldGrains), FALSE);
awlseg->freeGrains += awlseg->oldGrains;
awlseg->oldGrains = 0;
AVER(awlseg->freeGrains == awlseg->grains);
PoolGenFree(&awl->pgen, seg);
AVERT(AWLSeg, awlseg);
PoolGenFree(&awl->pgen, seg,
AWLGrainsSize(awl, awlseg->freeGrains),
AWLGrainsSize(awl, awlseg->oldGrains),
AWLGrainsSize(awl, awlseg->newGrains),
FALSE);
}
awl->sig = SigInvalid;
PoolGenFinish(&awl->pgen);
@ -1175,7 +1173,11 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
if (awlseg->freeGrains == awlseg->grains && buffer == NULL)
/* No survivors */
PoolGenFree(&awl->pgen, seg);
PoolGenFree(&awl->pgen, seg,
AWLGrainsSize(awl, awlseg->freeGrains),
AWLGrainsSize(awl, awlseg->oldGrains),
AWLGrainsSize(awl, awlseg->newGrains),
FALSE);
}

View file

@ -391,7 +391,11 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
if (!marked)
PoolGenFree(&lo->pgen, seg);
PoolGenFree(&lo->pgen, seg,
LOGrainsSize(lo, loseg->freeGrains),
LOGrainsSize(lo, loseg->oldGrains),
LOGrainsSize(lo, loseg->newGrains),
FALSE);
}
/* This walks over _all_ objects in the heap, whether they are */
@ -536,18 +540,12 @@ static void LOFinish(Pool pool)
RING_FOR(node, &pool->segRing, nextNode) {
Seg seg = SegOfPoolRing(node);
LOSeg loseg = SegLOSeg(seg);
AVERT(LOSeg, loseg);
UNUSED(loseg); /* <code/mpm.c#check.unused> */
PoolGenAccountForAge(&lo->pgen, LOGrainsSize(lo, loseg->newGrains), FALSE);
loseg->oldGrains += loseg->newGrains;
loseg->newGrains = 0;
PoolGenAccountForReclaim(&lo->pgen, LOGrainsSize(lo, loseg->oldGrains), FALSE);
loseg->freeGrains += loseg->oldGrains;
loseg->oldGrains = 0;
AVER(loseg->freeGrains == loSegGrains(loseg));
PoolGenFree(&lo->pgen, seg);
PoolGenFree(&lo->pgen, seg,
LOGrainsSize(lo, loseg->freeGrains),
LOGrainsSize(lo, loseg->oldGrains),
LOGrainsSize(lo, loseg->newGrains),
FALSE);
}
PoolGenFinish(&lo->pgen);

View file

@ -270,8 +270,13 @@ _`.accounting.op`: The following operations are provided:
_`.accounting.op.alloc`: Allocate a segment in a pool generation.
Debit *total*, credit *free*. (But see `.account.total.negated`_.)
_`.accounting.op.free`: Free a segment. Debit *free*, credit *total*.
(But see `.account.total.negated`_.)
_`.accounting.op.free`: Free a segment. First, ensure that the
contents of the segment are accounted as free, by artificially ageing
any memory accounted as *new* or *newDeferred* (see
`.accounting.op.age`_) and then artifically reclaiming any memory
accounted as *old* or *oldDeferred* (see `.accounting.op.reclaim`_).
Finally, debit *free*, credit *total*. (But see
`.account.total.negated`_.)
_`.accounting.op.fill`: Allocate memory, for example by filling a
buffer. Debit *free*, credit *new* or *newDeferred*.