mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Catch-up merge from master sources to branch/2014-01-15/nailboard.
Copied from Perforce Change: 185275 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
4e8b76ac54
85 changed files with 1427 additions and 1109 deletions
|
|
@ -186,7 +186,6 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_DONE(args);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* arena.c: ARENA ALLOCATION FEATURES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .sources: <design/arena/> is the main design document. */
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ DEFINE_CLASS(AbstractArenaClass, class)
|
|||
|
||||
Bool ArenaClassCheck(ArenaClass class)
|
||||
{
|
||||
CHECKL(ProtocolClassCheck(&class->protocol));
|
||||
CHECKD(ProtocolClass, &class->protocol);
|
||||
CHECKL(class->name != NULL); /* Should be <=6 char C identifier */
|
||||
CHECKL(class->size >= sizeof(ArenaStruct));
|
||||
/* Offset of generic Pool within class-specific instance cannot be */
|
||||
|
|
@ -147,7 +147,7 @@ Bool ArenaCheck(Arena arena)
|
|||
if (arena->primary != NULL) {
|
||||
CHECKD(Chunk, arena->primary);
|
||||
}
|
||||
CHECKL(RingCheck(&arena->chunkRing));
|
||||
CHECKD_NOSIG(Ring, &arena->chunkRing);
|
||||
/* nothing to check for chunkSerial */
|
||||
CHECKD(ChunkCacheEntry, &arena->chunkCache);
|
||||
|
||||
|
|
@ -155,7 +155,9 @@ Bool ArenaCheck(Arena arena)
|
|||
|
||||
CHECKL(BoolCheck(arena->hasFreeCBS));
|
||||
if (arena->hasFreeCBS)
|
||||
CHECKL(CBSCheck(ArenaFreeCBS(arena)));
|
||||
CHECKD(CBS, ArenaFreeCBS(arena));
|
||||
|
||||
CHECKL(BoolCheck(arena->zoned));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -179,7 +181,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
|
||||
AVER(arena != NULL);
|
||||
AVERT(ArenaClass, class);
|
||||
AVER(AlignCheck(alignment));
|
||||
AVERT(Align, alignment);
|
||||
|
||||
if (ArgPick(&arg, args, MPS_KEY_ARENA_ZONED))
|
||||
zoned = arg.val.b;
|
||||
|
|
@ -224,7 +226,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct));
|
||||
MPS_ARGS_ADD(piArgs, MPS_KEY_EXTEND_BY, arena->alignment);
|
||||
MPS_ARGS_ADD(piArgs, MFSExtendSelf, FALSE);
|
||||
MPS_ARGS_DONE(piArgs);
|
||||
res = PoolInit(ArenaCBSBlockPool(arena), arena, PoolClassMFS(), piArgs);
|
||||
} MPS_ARGS_END(piArgs);
|
||||
AVER(res == ResOK); /* no allocation, no failure expected */
|
||||
|
|
@ -234,7 +235,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
/* Initialise the freeCBS. */
|
||||
MPS_ARGS_BEGIN(cbsiArgs) {
|
||||
MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
|
||||
MPS_ARGS_DONE(cbsiArgs);
|
||||
res = CBSInit(ArenaFreeCBS(arena), arena, arena, alignment,
|
||||
/* fastFind */ TRUE, arena->zoned, cbsiArgs);
|
||||
} MPS_ARGS_END(cbsiArgs);
|
||||
|
|
@ -286,7 +286,7 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
|
||||
AVER(arenaReturn != NULL);
|
||||
AVERT(ArenaClass, class);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
/* We must initialise the event subsystem very early, because event logging
|
||||
will start as soon as anything interesting happens and expect to write
|
||||
|
|
@ -558,7 +558,7 @@ Res ControlAlloc(void **baseReturn, Arena arena, size_t size,
|
|||
AVERT(Arena, arena);
|
||||
AVER(baseReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
AVER(arena->poolReady);
|
||||
|
||||
res = PoolAlloc(&base, ArenaControlPool(arena), (Size)size,
|
||||
|
|
@ -1023,7 +1023,7 @@ Res ArenaAlloc(Addr *baseReturn, SegPref pref, Size size, Pool pool,
|
|||
AVERT(SegPref, pref);
|
||||
AVER(size > (Size)0);
|
||||
AVERT(Pool, pool);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
AVERT(Arena, arena);
|
||||
|
|
@ -1321,7 +1321,7 @@ Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* arenacl.c: ARENA CLASS USING CLIENT MEMORY
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: See <design/arena/#client>.
|
||||
*
|
||||
|
|
@ -67,7 +67,7 @@ static Bool ClientChunkCheck(ClientChunk clChunk)
|
|||
|
||||
CHECKS(ClientChunk, clChunk);
|
||||
chunk = ClientChunk2Chunk(clChunk);
|
||||
CHECKL(ChunkCheck(chunk));
|
||||
CHECKD(Chunk, chunk);
|
||||
CHECKL(clChunk->freePages <= chunk->pages);
|
||||
/* check they don't overlap (knowing the order) */
|
||||
CHECKL((Addr)(chunk + 1) < (Addr)chunk->allocTable);
|
||||
|
|
@ -201,7 +201,7 @@ static void ClientArenaVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[1].key = MPS_KEY_ARENA_CL_BASE;
|
||||
args[1].val.addr = va_arg(varargs, Addr);
|
||||
args[2].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
|
||||
AVER(arenaReturn != NULL);
|
||||
AVER((ArenaClass)mps_arena_class_cl() == class);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
ArgRequire(&arg, args, MPS_KEY_ARENA_SIZE);
|
||||
size = arg.val.size;
|
||||
|
|
@ -434,6 +434,7 @@ DEFINE_ARENA_CLASS(ClientArenaClass, this)
|
|||
this->free = ClientFree;
|
||||
this->chunkInit = ClientChunkInit;
|
||||
this->chunkFinish = ClientChunkFinish;
|
||||
AVERT(ArenaClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -447,7 +448,7 @@ mps_arena_class_t mps_arena_class_cl(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ static Bool VMChunkCheck(VMChunk vmchunk)
|
|||
|
||||
CHECKS(VMChunk, vmchunk);
|
||||
chunk = VMChunk2Chunk(vmchunk);
|
||||
CHECKL(ChunkCheck(chunk));
|
||||
CHECKL(VMCheck(vmchunk->vm));
|
||||
CHECKD(Chunk, chunk);
|
||||
CHECKD_NOSIG(VM, vmchunk->vm); /* <design/check/#hidden-type> */
|
||||
CHECKL(VMAlign(vmchunk->vm) == ChunkPageSize(chunk));
|
||||
CHECKL(vmchunk->overheadMappedLimit <= (Addr)chunk->pageTable);
|
||||
CHECKD(SparseArray, &vmchunk->pages);
|
||||
|
|
@ -174,7 +174,7 @@ static Bool VMArenaCheck(VMArena vmArena)
|
|||
CHECKL(VMMapped(primary->vm) <= arena->committed);
|
||||
}
|
||||
|
||||
CHECKL(RingCheck(&vmArena->spareRing));
|
||||
CHECKD_NOSIG(Ring, &vmArena->spareRing);
|
||||
|
||||
/* FIXME: Can't check VMParams */
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ static void VMArenaVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[0].key = MPS_KEY_ARENA_SIZE;
|
||||
args[0].val.size = va_arg(varargs, Size);
|
||||
args[1].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -493,7 +493,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
|
||||
AVER(arenaReturn != NULL);
|
||||
AVER(class == VMArenaClassGet());
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
ArgRequire(&arg, args, MPS_KEY_ARENA_SIZE);
|
||||
userSize = arg.val.size;
|
||||
|
|
@ -1159,6 +1159,7 @@ DEFINE_ARENA_CLASS(VMArenaClass, this)
|
|||
this->compact = VMCompact;
|
||||
this->describe = VMArenaDescribe;
|
||||
this->pagesMarkAllocated = VMPagesMarkAllocated;
|
||||
AVERT(ArenaClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* arg.c: ARGUMENT LISTS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: See <design/keyword-arguments.rst>.
|
||||
*/
|
||||
|
|
@ -52,7 +52,7 @@ Bool ArgCheckAddr(Arg arg) {
|
|||
}
|
||||
|
||||
Bool ArgCheckPoolDebugOptions(Arg arg) {
|
||||
CHECKL(PoolDebugOptionsCheck((PoolDebugOptions)arg->val.pool_debug_options));
|
||||
CHECKD_NOSIG(PoolDebugOptions, (PoolDebugOptions)arg->val.pool_debug_options);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ Bool ArgListCheck(ArgList args)
|
|||
CHECKL(args != NULL);
|
||||
for (i = 0; args[i].key != MPS_KEY_ARGS_END; ++i) {
|
||||
CHECKL(i < MPS_ARGS_MAX);
|
||||
CHECKL(ArgCheck(&args[i]));
|
||||
CHECKD_NOSIG(Arg, &args[i]);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ Bool ArgPick(ArgStruct *argOut, ArgList args, Key key) {
|
|||
Index i;
|
||||
|
||||
AVER(argOut != NULL);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
AVERT(Key, key);
|
||||
|
||||
for (i = 0; args[i].key != MPS_KEY_ARGS_END; ++i)
|
||||
|
|
@ -185,14 +185,14 @@ void ArgTrivVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
{
|
||||
UNUSED(varargs);
|
||||
args[0].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* boot.c: BOOTSTRAP ALLOCATOR
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .overview: A structure and protocols for allocating memory from a
|
||||
* given block. Very simple, it basically just increments a pointer.
|
||||
|
|
@ -101,7 +101,7 @@ Res BootAlloc(void **pReturn, BootBlock boot, size_t size, size_t align)
|
|||
AVER(pReturn != NULL);
|
||||
AVERT(BootBlock, boot);
|
||||
AVER(size > 0);
|
||||
AVER(AlignCheck((Align)align));
|
||||
AVERT(Align, (Align)align);
|
||||
|
||||
/* Align alloc pointer up and bounds check. */
|
||||
blockBase = PointerAlignUp(boot->alloc, align);
|
||||
|
|
@ -127,7 +127,7 @@ Res BootAlloc(void **pReturn, BootBlock boot, size_t size, size_t align)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* bt.c: BIT TABLES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* READERSHIP
|
||||
*
|
||||
|
|
@ -223,7 +223,7 @@ void BTDestroy(BT bt, Arena arena, Count length)
|
|||
* discussed in review.impl.c.bt.4.
|
||||
*/
|
||||
|
||||
static Bool BTCheck(BT bt)
|
||||
Bool BTCheck(BT bt)
|
||||
{
|
||||
AVER(bt != NULL);
|
||||
AVER(AddrIsAligned((Addr)bt, sizeof(Word)));
|
||||
|
|
@ -252,7 +252,7 @@ Size (BTSize)(Count n)
|
|||
|
||||
Bool (BTGet)(BT t, Index i)
|
||||
{
|
||||
AVER(BTCheck(t));
|
||||
AVERT(BT, t);
|
||||
/* Can't check i */
|
||||
|
||||
/* see macro in <code/mpm.h> */
|
||||
|
|
@ -267,7 +267,7 @@ Bool (BTGet)(BT t, Index i)
|
|||
|
||||
void (BTSet)(BT t, Index i)
|
||||
{
|
||||
AVER(BTCheck(t));
|
||||
AVERT(BT, t);
|
||||
/* Can't check i */
|
||||
|
||||
/* see macro in <code/mpm.h> */
|
||||
|
|
@ -282,7 +282,7 @@ void (BTSet)(BT t, Index i)
|
|||
|
||||
void (BTRes)(BT t, Index i)
|
||||
{
|
||||
AVER(BTCheck(t));
|
||||
AVERT(BT, t);
|
||||
/* Can't check i */
|
||||
|
||||
/* see macro in <code/mpm.h> */
|
||||
|
|
@ -297,7 +297,7 @@ void (BTRes)(BT t, Index i)
|
|||
|
||||
void BTSetRange(BT t, Index base, Index limit)
|
||||
{
|
||||
AVER(BTCheck(t));
|
||||
AVERT(BT, t);
|
||||
AVER(base < limit);
|
||||
|
||||
#define SINGLE_SET_RANGE(i) \
|
||||
|
|
@ -319,7 +319,7 @@ void BTSetRange(BT t, Index base, Index limit)
|
|||
|
||||
Bool BTIsResRange(BT bt, Index base, Index limit)
|
||||
{
|
||||
AVER_CRITICAL(BTCheck(bt)); /* See .aver.critical */
|
||||
AVERT_CRITICAL(BT, bt); /* See .aver.critical */
|
||||
AVER_CRITICAL(base < limit);
|
||||
/* Can't check range of base or limit */
|
||||
|
||||
|
|
@ -343,7 +343,7 @@ Bool BTIsResRange(BT bt, Index base, Index limit)
|
|||
|
||||
Bool BTIsSetRange(BT bt, Index base, Index limit)
|
||||
{
|
||||
AVER(BTCheck(bt));
|
||||
AVERT(BT, bt);
|
||||
AVER(base < limit);
|
||||
/* Can't check range of base or limit */
|
||||
|
||||
|
|
@ -371,7 +371,7 @@ Bool BTIsSetRange(BT bt, Index base, Index limit)
|
|||
|
||||
void BTResRange(BT t, Index base, Index limit)
|
||||
{
|
||||
AVER(BTCheck(t));
|
||||
AVERT(BT, t);
|
||||
AVER(base < limit);
|
||||
|
||||
#define SINGLE_RES_RANGE(i) \
|
||||
|
|
@ -884,8 +884,8 @@ Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn,
|
|||
|
||||
Bool BTRangesSame(BT comparand, BT comparator, Index base, Index limit)
|
||||
{
|
||||
AVER(BTCheck(comparand));
|
||||
AVER(BTCheck(comparator));
|
||||
AVERT(BT, comparand);
|
||||
AVERT(BT, comparator);
|
||||
AVER(base < limit);
|
||||
|
||||
#define SINGLE_RANGES_SAME(i) \
|
||||
|
|
@ -920,8 +920,8 @@ Bool BTRangesSame(BT comparand, BT comparator, Index base, Index limit)
|
|||
|
||||
void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit)
|
||||
{
|
||||
AVER(BTCheck(fromBT));
|
||||
AVER(BTCheck(toBT));
|
||||
AVERT(BT, fromBT);
|
||||
AVERT(BT, toBT);
|
||||
AVER(fromBT != toBT);
|
||||
AVER(base < limit);
|
||||
|
||||
|
|
@ -955,8 +955,8 @@ void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit)
|
|||
|
||||
void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit)
|
||||
{
|
||||
AVER(BTCheck(fromBT));
|
||||
AVER(BTCheck(toBT));
|
||||
AVERT(BT, fromBT);
|
||||
AVERT(BT, toBT);
|
||||
AVER(fromBT != toBT);
|
||||
AVER(base < limit);
|
||||
|
||||
|
|
@ -999,8 +999,8 @@ void BTCopyOffsetRange(BT fromBT, BT toBT,
|
|||
{
|
||||
Index fromBit, toBit;
|
||||
|
||||
AVER(BTCheck(fromBT));
|
||||
AVER(BTCheck(toBT));
|
||||
AVERT(BT, fromBT);
|
||||
AVERT(BT, toBT);
|
||||
AVER(fromBT != toBT);
|
||||
AVER(fromBase < fromLimit);
|
||||
AVER(toBase < toLimit);
|
||||
|
|
@ -1024,7 +1024,7 @@ Count BTCountResRange(BT bt, Index base, Index limit)
|
|||
Count c = 0;
|
||||
Index bit;
|
||||
|
||||
AVER(BTCheck(bt));
|
||||
AVERT(BT, bt);
|
||||
AVER(base < limit);
|
||||
|
||||
for (bit = base; bit < limit; ++bit)
|
||||
|
|
@ -1035,7 +1035,7 @@ Count BTCountResRange(BT bt, Index base, Index limit)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* bt.h: Bit Table Interface
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: <design/bt/>
|
||||
*/
|
||||
|
|
@ -39,6 +39,7 @@ extern void (BTRes)(BT bt, Index index);
|
|||
END
|
||||
|
||||
|
||||
extern Bool BTCheck(BT bt);
|
||||
extern Res BTCreate(BT *btReturn, Arena arena, Count length);
|
||||
extern void BTDestroy(BT bt, Arena arena, Count length);
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ extern Count BTCountResRange(BT bt, Index base, Index limit);
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* buffer.c: ALLOCATION BUFFER IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is (part of) the implementation of allocation buffers.
|
||||
* Several macros which also form part of the implementation are in
|
||||
|
|
@ -45,7 +45,7 @@ Bool BufferCheck(Buffer buffer)
|
|||
CHECKU(Arena, buffer->arena);
|
||||
CHECKU(Pool, buffer->pool);
|
||||
CHECKL(buffer->arena == buffer->pool->arena);
|
||||
CHECKL(RingCheck(&buffer->poolRing)); /* <design/check/#type.no-sig> */
|
||||
CHECKD_NOSIG(Ring, &buffer->poolRing);
|
||||
CHECKL(BoolCheck(buffer->isMutator));
|
||||
CHECKL(buffer->fillSize >= 0.0);
|
||||
CHECKL(buffer->emptySize >= 0.0);
|
||||
|
|
@ -205,7 +205,7 @@ static Res BufferInit(Buffer buffer, BufferClass class,
|
|||
AVERT(BufferClass, class);
|
||||
AVERT(Pool, pool);
|
||||
/* The PoolClass should support buffer protocols */
|
||||
AVER((pool->class->attr & AttrBUF)); /* .trans.mod */
|
||||
AVER(PoolHasAttr(pool, AttrBUF));
|
||||
|
||||
arena = PoolArena(pool);
|
||||
/* Initialize the buffer. See <code/mpmst.h> for a definition of */
|
||||
|
|
@ -383,7 +383,7 @@ void BufferFinish(Buffer buffer)
|
|||
pool = BufferPool(buffer);
|
||||
|
||||
/* The PoolClass should support buffer protocols */
|
||||
AVER((pool->class->attr & AttrBUF)); /* .trans.mod */
|
||||
AVER(PoolHasAttr(pool, AttrBUF));
|
||||
AVER(BufferIsReady(buffer));
|
||||
|
||||
/* <design/alloc-frame/#lw-frame.sync.trip> */
|
||||
|
|
@ -605,7 +605,7 @@ Res BufferReserve(Addr *pReturn, Buffer buffer, Size size,
|
|||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, BufferPool(buffer)->alignment));
|
||||
AVER(BufferIsReady(buffer));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Is there enough room in the unallocated portion of the buffer to */
|
||||
/* satisfy the request? If so, just increase the alloc marker and */
|
||||
|
|
@ -1182,7 +1182,7 @@ static Res bufferTrivDescribe(Buffer buffer, mps_lib_FILE *stream)
|
|||
|
||||
Bool BufferClassCheck(BufferClass class)
|
||||
{
|
||||
CHECKL(ProtocolClassCheck(&class->protocol));
|
||||
CHECKD(ProtocolClass, &class->protocol);
|
||||
CHECKL(class->name != NULL); /* Should be <=6 char C identifier */
|
||||
CHECKL(class->size >= sizeof(BufferStruct));
|
||||
CHECKL(FUNCHECK(class->varargs));
|
||||
|
|
@ -1220,6 +1220,7 @@ DEFINE_CLASS(BufferClass, class)
|
|||
class->setRankSet = bufferNoSetRankSet;
|
||||
class->reassignSeg = bufferNoReassignSeg;
|
||||
class->sig = BufferClassSig;
|
||||
AVERT(BufferClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1240,7 +1241,7 @@ Bool SegBufCheck(SegBuf segbuf)
|
|||
|
||||
CHECKS(SegBuf, segbuf);
|
||||
buffer = &segbuf->bufferStruct;
|
||||
CHECKL(BufferCheck(buffer));
|
||||
CHECKD(Buffer, buffer);
|
||||
CHECKL(RankSetCheck(segbuf->rankSet));
|
||||
|
||||
if (buffer->mode & BufferModeTRANSITION) {
|
||||
|
|
@ -1250,7 +1251,7 @@ Bool SegBufCheck(SegBuf segbuf)
|
|||
} else {
|
||||
/* The buffer is attached to a segment. */
|
||||
CHECKL(segbuf->seg != NULL);
|
||||
CHECKL(SegCheck(segbuf->seg));
|
||||
CHECKD(Seg, segbuf->seg);
|
||||
/* To avoid recursive checking, leave it to SegCheck to make */
|
||||
/* sure the buffer and segment fields tally. */
|
||||
|
||||
|
|
@ -1472,6 +1473,7 @@ DEFINE_CLASS(SegBufClass, class)
|
|||
class->rankSet = segBufRankSet;
|
||||
class->setRankSet = segBufSetRankSet;
|
||||
class->reassignSeg = segBufReassignSeg;
|
||||
AVERT(BufferClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1485,7 +1487,7 @@ static void rankBufVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[0].key = MPS_KEY_RANK;
|
||||
args[0].val.rank = va_arg(varargs, Rank);
|
||||
args[1].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
/* rankBufInit -- RankBufClass init method */
|
||||
|
|
@ -1499,10 +1501,10 @@ static Res rankBufInit(Buffer buffer, Pool pool, ArgList args)
|
|||
|
||||
AVERT(Buffer, buffer);
|
||||
AVERT(Pool, pool);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
if (ArgPick(&arg, args, MPS_KEY_RANK))
|
||||
rank = arg.val.rank;
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = BUFFER_SUPERCLASS(RankBufClass);
|
||||
|
|
@ -1532,12 +1534,13 @@ DEFINE_CLASS(RankBufClass, class)
|
|||
class->name = "RANKBUF";
|
||||
class->varargs = rankBufVarargs;
|
||||
class->init = rankBufInit;
|
||||
AVERT(BufferClass, class);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .intro: This is a portable implementation of coalescing block
|
||||
* structures.
|
||||
|
|
@ -85,6 +85,7 @@ static Bool CBSBlockCheck(CBSBlock block)
|
|||
/* See .enter-leave.simple. */
|
||||
UNUSED(block); /* Required because there is no signature */
|
||||
CHECKL(block != NULL);
|
||||
/* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */
|
||||
CHECKL(TreeCheck(cbsBlockTree(block)));
|
||||
|
||||
/* If the block is in the middle of being deleted, */
|
||||
|
|
@ -245,9 +246,9 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
|
||||
AVERT(Arena, arena);
|
||||
AVER(cbs != NULL);
|
||||
AVER(AlignCheck(alignment));
|
||||
AVER(BoolCheck(fastFind));
|
||||
AVER(BoolCheck(zoned));
|
||||
AVERT(Align, alignment);
|
||||
AVERT(Bool, fastFind);
|
||||
AVERT(Bool, zoned);
|
||||
|
||||
if (ArgPick(&arg, args, CBSBlockPool))
|
||||
blockPool = arg.val.pool;
|
||||
|
|
@ -915,8 +916,8 @@ Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn,
|
|||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(CBS, cbs);
|
||||
/* AVER(ZoneSetCheck(zoneSet)); */
|
||||
AVER(BoolCheck(high));
|
||||
/* AVERT(ZoneSet, zoneSet); */
|
||||
AVERT(Bool, high);
|
||||
|
||||
cbsFind = high ? CBSFindLast : CBSFindFirst;
|
||||
splayFind = high ? SplayFindLast : SplayFindFirst;
|
||||
|
|
@ -1086,7 +1087,7 @@ Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* check.h: ASSERTION INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .aver: This header defines a family of AVER and NOTREACHED macros.
|
||||
|
|
@ -85,9 +85,6 @@
|
|||
*
|
||||
* TODO: Should also allow the check level variable to come from an
|
||||
* environment variable.
|
||||
*
|
||||
* TODO: CheckLevelDEEP asserts on arena creation with bootstrapping
|
||||
* problems. It clearly hasn't been tried for a while. RB 2012-09-01
|
||||
*/
|
||||
|
||||
enum {
|
||||
|
|
@ -327,7 +324,7 @@ extern unsigned CheckLevel;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* clock.h -- Fast clocks and timers
|
||||
*
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
|
@ -15,10 +15,6 @@
|
|||
*
|
||||
* On platforms that support it, we want to stamp events with a very cheap
|
||||
* and fast high-resolution timer.
|
||||
*
|
||||
* TODO: This is a sufficiently complicated nest of ifdefs that it should
|
||||
* be quarantined in its own header with KEEP OUT signs attached.
|
||||
* RB 2012-09-11
|
||||
*/
|
||||
|
||||
/* Microsoft C provides an intrinsic for the Intel rdtsc instruction.
|
||||
|
|
@ -169,7 +165,7 @@ typedef mps_clock_t EventClock;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* dbgpool.c: POOL DEBUG MIXIN
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .source: design.mps.object-debug
|
||||
|
|
@ -34,8 +34,6 @@ typedef tagStruct *Tag;
|
|||
|
||||
/* tag init methods: copying the user-supplied data into the tag */
|
||||
|
||||
#define TagInitMethodCheck(f) FUNCHECK(f)
|
||||
|
||||
static void TagTrivInit(void* tag, va_list args)
|
||||
{
|
||||
UNUSED(tag); UNUSED(args);
|
||||
|
|
@ -75,7 +73,7 @@ Bool PoolDebugMixinCheck(PoolDebugMixin debug)
|
|||
/* Nothing to check about freeTemplate */
|
||||
/* Nothing to check about freeSize */
|
||||
if (debug->tagInit != NULL) {
|
||||
CHECKL(TagInitMethodCheck(debug->tagInit));
|
||||
CHECKL(FUNCHECK(debug->tagInit));
|
||||
/* Nothing to check about tagSize */
|
||||
CHECKD(Pool, debug->tagPool);
|
||||
CHECKL(COMPATTYPE(Addr, void*)); /* tagPool relies on this */
|
||||
|
|
@ -573,7 +571,7 @@ static void TagWalk(Pool pool, ObjectsStepMethod step, void *p)
|
|||
AVERT(PoolDebugMixin, debug);
|
||||
|
||||
node = SplayTreeFirst(&debug->index);
|
||||
while (node != NULL) {
|
||||
while (node != TreeEMPTY) {
|
||||
Tag tag = TagOfTree(node);
|
||||
|
||||
step(tag->addr, tag->size, NULL, pool, &tag->userdata, p);
|
||||
|
|
@ -691,7 +689,7 @@ void PoolClassMixInDebug(PoolClass class)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -264,6 +264,9 @@ static void readLog(FILE *stream)
|
|||
event->EventInit.f5,
|
||||
MPS_WORD_WIDTH);
|
||||
break;
|
||||
default:
|
||||
/* No special treatment needed. */
|
||||
break;
|
||||
}
|
||||
|
||||
(void)EVENT_CLOCK_PRINT(stdout, eventTime);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* <code/eventdef.h> -- Event Logging Definitions
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: <design/telemetry/>
|
||||
*
|
||||
|
|
@ -31,14 +31,13 @@
|
|||
* the median version when changing an existing event,
|
||||
* and the major version when changing the format of the event file.
|
||||
*
|
||||
* TODO: These should go into a header that appears at the start of a
|
||||
* telemetry stream, but they aren't currently used. Keep updating them
|
||||
* anyway. RB 2012-09-07
|
||||
* These are passed as parameters to the EventInit event at the start
|
||||
* of a telemetry stream, allowing that stream to be identified.
|
||||
*/
|
||||
|
||||
#define EVENT_VERSION_MAJOR ((unsigned)1)
|
||||
#define EVENT_VERSION_MEDIAN ((unsigned)1)
|
||||
#define EVENT_VERSION_MINOR ((unsigned)6)
|
||||
#define EVENT_VERSION_MINOR ((unsigned)7)
|
||||
|
||||
|
||||
/* EVENT_LIST -- list of event types and general properties
|
||||
|
|
@ -192,7 +191,8 @@
|
|||
/* new events for performance analysis of large heaps. */ \
|
||||
EVENT(X, TraceCondemnZones , 0x0083, TRUE, Trace) \
|
||||
EVENT(X, ArenaGenZoneAdd , 0x0084, TRUE, Arena) \
|
||||
EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena)
|
||||
EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena) \
|
||||
/* EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena) */
|
||||
|
||||
|
||||
/* Remember to update EventNameMAX and EventCodeMAX above!
|
||||
|
|
@ -745,7 +745,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -432,20 +432,23 @@ static void find(FBMState state, Size size, Bool high, FindDelete findDelete)
|
|||
remainderLimit = origLimit = addrOfIndex(state, expectedLimit);
|
||||
|
||||
switch(findDelete) {
|
||||
case FindDeleteNONE: {
|
||||
case FindDeleteNONE:
|
||||
/* do nothing */
|
||||
} break;
|
||||
case FindDeleteENTIRE: {
|
||||
break;
|
||||
case FindDeleteENTIRE:
|
||||
remainderBase = remainderLimit;
|
||||
} break;
|
||||
case FindDeleteLOW: {
|
||||
break;
|
||||
case FindDeleteLOW:
|
||||
expectedLimit = expectedBase + size;
|
||||
remainderBase = addrOfIndex(state, expectedLimit);
|
||||
} break;
|
||||
case FindDeleteHIGH: {
|
||||
break;
|
||||
case FindDeleteHIGH:
|
||||
expectedBase = expectedLimit - size;
|
||||
remainderLimit = addrOfIndex(state, expectedBase);
|
||||
} break;
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid findDelete");
|
||||
break;
|
||||
}
|
||||
|
||||
if (findDelete != FindDeleteNONE) {
|
||||
|
|
@ -528,9 +531,7 @@ static void test(FBMState state, unsigned n) {
|
|||
size = fbmRnd(ArraySize / 10) + 1;
|
||||
high = fbmRnd(2) ? TRUE : FALSE;
|
||||
switch(fbmRnd(6)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: findDelete = FindDeleteNONE; break;
|
||||
default: findDelete = FindDeleteNONE; break;
|
||||
case 3: findDelete = FindDeleteLOW; break;
|
||||
case 4: findDelete = FindDeleteHIGH; break;
|
||||
case 5: findDelete = FindDeleteENTIRE; break;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpscams.h"
|
||||
#include "mpscawl.h"
|
||||
#include "mpsavm.h"
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
|
|
@ -32,14 +34,8 @@
|
|||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
#define rootCOUNT 20
|
||||
#define maxtreeDEPTH 12
|
||||
#define maxtreeDEPTH 10
|
||||
#define collectionCOUNT 10
|
||||
#define genCOUNT 2
|
||||
|
||||
/* testChain -- generation parameters for the test */
|
||||
|
||||
static mps_gen_param_s testChain[genCOUNT] = {
|
||||
{ 150, 0.85 }, { 170, 0.45 } };
|
||||
|
||||
|
||||
/* global object counter */
|
||||
|
|
@ -123,119 +119,90 @@ static void register_indirect_tree(mps_word_t tree, mps_arena_t arena)
|
|||
}
|
||||
}
|
||||
|
||||
static mps_addr_t test_awl_find_dependent(mps_addr_t addr)
|
||||
{
|
||||
testlib_unused(addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *root[rootCOUNT];
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap,
|
||||
mps_word_t (*make)(mps_word_t, mps_ap_t),
|
||||
void (*reg)(mps_word_t, mps_arena_t))
|
||||
{
|
||||
size_t collections = 0;
|
||||
size_t finals = 0;
|
||||
size_t i;
|
||||
|
||||
object_count = 0;
|
||||
|
||||
printf("Making some %s finalized trees of objects.\n", name);
|
||||
/* make some trees */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = (void *)(*make)(maxtreeDEPTH, ap);
|
||||
(*reg)((mps_word_t)root[i], arena);
|
||||
}
|
||||
|
||||
printf("Losing all pointers to the trees.\n");
|
||||
/* clean out the roots */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = 0;
|
||||
}
|
||||
|
||||
while (finals < object_count && collections < collectionCOUNT) {
|
||||
mps_word_t final_this_time = 0;
|
||||
printf("Collecting...");
|
||||
(void)fflush(stdout);
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
++ collections;
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_message_t message;
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena,
|
||||
mps_message_type_finalization()),
|
||||
"get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
mps_message_discard(arena, message);
|
||||
++ final_this_time;
|
||||
}
|
||||
finals += final_this_time;
|
||||
printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST
|
||||
" of %"PRIuLONGEST"\n", final_this_time, finals, object_count);
|
||||
}
|
||||
cdie(finals == object_count, "Not all objects were finalized.");
|
||||
}
|
||||
|
||||
static void *test(mps_arena_t arena, mps_class_t pool_class)
|
||||
{
|
||||
mps_ap_t ap;
|
||||
mps_fmt_t fmt;
|
||||
mps_chain_t chain;
|
||||
mps_word_t finals;
|
||||
mps_pool_t amc;
|
||||
mps_pool_t pool;
|
||||
mps_root_t mps_root;
|
||||
mps_arena_t arena;
|
||||
mps_message_t message;
|
||||
size_t i;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s;
|
||||
|
||||
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain),
|
||||
"pool_create amc\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent);
|
||||
die(mps_pool_create_k(&pool, arena, pool_class, args),
|
||||
"pool_create\n");
|
||||
} MPS_ARGS_END(args);
|
||||
die(mps_root_create_table(&mps_root, arena, mps_rank_exact(), (mps_rm_t)0,
|
||||
root, (size_t)rootCOUNT),
|
||||
"root_create\n");
|
||||
die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create\n");
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create\n");
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_finalization());
|
||||
|
||||
mps_arena_park(arena);
|
||||
|
||||
object_count = 0;
|
||||
|
||||
printf("Making some finalized trees of objects.\n");
|
||||
/* make some trees */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = (void *)make_numbered_tree(maxtreeDEPTH, ap);
|
||||
register_numbered_tree((mps_word_t)root[i], arena);
|
||||
}
|
||||
|
||||
printf("Losing all pointers to the trees.\n");
|
||||
/* clean out the roots */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = 0;
|
||||
}
|
||||
|
||||
finals = 0;
|
||||
|
||||
while ((finals < object_count) &&
|
||||
(mps_collections(arena) < collectionCOUNT)) {
|
||||
mps_word_t final_this_time = 0;
|
||||
printf("Collecting...");
|
||||
(void)fflush(stdout);
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena,
|
||||
mps_message_type_finalization()),
|
||||
"get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
mps_message_discard(arena, message);
|
||||
++ final_this_time;
|
||||
}
|
||||
finals += final_this_time;
|
||||
printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST
|
||||
" of %"PRIuLONGEST"\n",
|
||||
final_this_time, finals, object_count);
|
||||
}
|
||||
|
||||
object_count = 0;
|
||||
|
||||
printf("Making some indirectly finalized trees of objects.\n");
|
||||
/* make some trees */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = (void *)make_indirect_tree(maxtreeDEPTH, ap);
|
||||
register_indirect_tree((mps_word_t)root[i], arena);
|
||||
}
|
||||
|
||||
printf("Losing all pointers to the trees.\n");
|
||||
/* clean out the roots */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = 0;
|
||||
}
|
||||
|
||||
finals = 0;
|
||||
|
||||
while ((finals < object_count) &&
|
||||
(mps_collections(arena) < collectionCOUNT)) {
|
||||
mps_word_t final_this_time = 0;
|
||||
printf("Collecting...");
|
||||
(void)fflush(stdout);
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena,
|
||||
mps_message_type_finalization()),
|
||||
"get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
mps_message_discard(arena, message);
|
||||
++ final_this_time;
|
||||
}
|
||||
finals += final_this_time;
|
||||
printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST
|
||||
" of %"PRIuLONGEST"\n",
|
||||
final_this_time, finals, object_count);
|
||||
}
|
||||
test_trees("numbered", arena, ap, make_numbered_tree, register_numbered_tree);
|
||||
test_trees("indirect", arena, ap, make_indirect_tree, register_indirect_tree);
|
||||
|
||||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(mps_root);
|
||||
mps_pool_destroy(amc);
|
||||
mps_chain_destroy(chain);
|
||||
mps_pool_destroy(pool);
|
||||
mps_fmt_destroy(fmt);
|
||||
|
||||
return NULL;
|
||||
|
|
@ -246,14 +213,17 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
void *r;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create\n");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg\n");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
|
||||
test(arena, mps_class_amc());
|
||||
/* TODO: test(arena, mps_class_ams()); */
|
||||
/* TODO: test(arena, mps_class_awl()); */
|
||||
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* format.c: OBJECT FORMATS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
|
|
@ -21,7 +21,7 @@ Bool FormatCheck(Format format)
|
|||
CHECKS(Format, format);
|
||||
CHECKU(Arena, format->arena);
|
||||
CHECKL(format->serial < format->arena->formatSerial);
|
||||
CHECKL(RingCheck(&format->arenaRing));
|
||||
CHECKD_NOSIG(Ring, &format->arenaRing);
|
||||
CHECKL(AlignCheck(format->alignment));
|
||||
/* TODO: Define the concept of the maximum alignment it is possible to
|
||||
request from the MPS, document and provide an interface to it, and then
|
||||
|
|
@ -114,7 +114,7 @@ Res FormatCreate(Format *formatReturn, Arena arena, ArgList args)
|
|||
|
||||
AVER(formatReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
if (ArgPick(&arg, args, MPS_KEY_FMT_ALIGN))
|
||||
fmtAlign = arg.val.align;
|
||||
|
|
@ -217,7 +217,7 @@ Res FormatDescribe(Format format, mps_lib_FILE *stream)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ DEFINE_POOL_CLASS(OOMPoolClass, this)
|
|||
{
|
||||
INHERIT_CLASS(this, AbstractAllocFreePoolClass);
|
||||
this->alloc = OOMAlloc;
|
||||
this->size = sizeof(PoolStruct);
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ CFLAGSCOMPILER := \
|
|||
-Wshadow \
|
||||
-Wstrict-aliasing=2 \
|
||||
-Wstrict-prototypes \
|
||||
-Wswitch-default \
|
||||
-Wwrite-strings
|
||||
CFLAGSCOMPILERSTRICT := -ansi -pedantic
|
||||
|
||||
|
|
|
|||
|
|
@ -331,8 +331,8 @@ int main(int argc, char *argv[]) {
|
|||
double mort = 0.0;
|
||||
cap = (size_t)strtoul(optarg, &p, 10);
|
||||
switch(toupper(*p)) {
|
||||
case 'G': cap *= 1024;
|
||||
case 'M': cap *= 1024;
|
||||
case 'G': cap *= 1024; /* fall through */
|
||||
case 'M': cap *= 1024; /* fall through */
|
||||
case 'K': p++; break;
|
||||
default: cap = 0; break;
|
||||
}
|
||||
|
|
@ -356,6 +356,10 @@ int main(int argc, char *argv[]) {
|
|||
case 'G': arenasize *= 1024;
|
||||
case 'M': arenasize *= 1024;
|
||||
case 'K': arenasize *= 1024; break;
|
||||
case '\0': break;
|
||||
default:
|
||||
fprintf(stderr, "Bad arena size %s\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKS(Globals, arenaGlobals);
|
||||
arena = GlobalsArena(arenaGlobals);
|
||||
CHECKL(arena->serial < arenaSerial);
|
||||
CHECKL(RingCheck(&arenaGlobals->globalRing));
|
||||
CHECKD_NOSIG(Ring, &arenaGlobals->globalRing);
|
||||
|
||||
CHECKL(MPSVersion() == arenaGlobals->mpsVersionString);
|
||||
|
||||
|
|
@ -138,16 +138,17 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKL(arenaGlobals->emptyInternalSize >= 0.0);
|
||||
|
||||
CHECKL(BoolCheck(arenaGlobals->bufferLogging));
|
||||
CHECKL(RingCheck(&arenaGlobals->poolRing));
|
||||
CHECKL(RingCheck(&arenaGlobals->rootRing));
|
||||
CHECKL(RingCheck(&arenaGlobals->rememberedSummaryRing));
|
||||
CHECKD_NOSIG(Ring, &arenaGlobals->poolRing);
|
||||
CHECKD_NOSIG(Ring, &arenaGlobals->rootRing);
|
||||
CHECKD_NOSIG(Ring, &arenaGlobals->rememberedSummaryRing);
|
||||
CHECKL(arenaGlobals->rememberedSummaryIndex < RememberedSummaryBLOCK);
|
||||
/* <code/global.c#remembered.summary> RingIsSingle imples index == 0 */
|
||||
CHECKL(!RingIsSingle(&arenaGlobals->rememberedSummaryRing) ||
|
||||
arenaGlobals->rememberedSummaryIndex == 0);
|
||||
CHECKL(RingCheck(&arena->formatRing));
|
||||
CHECKL(RingCheck(&arena->messageRing));
|
||||
/* Don't check enabledMessageTypes */
|
||||
CHECKD_NOSIG(Ring, &arena->formatRing);
|
||||
CHECKD_NOSIG(Ring, &arena->messageRing);
|
||||
if (arena->enabledMessageTypes != NULL)
|
||||
CHECKD_NOSIG(BT, arena->enabledMessageTypes);
|
||||
CHECKL(BoolCheck(arena->isFinalPool));
|
||||
if (arena->isFinalPool) {
|
||||
CHECKD(Pool, arena->finalPool);
|
||||
|
|
@ -155,7 +156,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKL(arena->finalPool == NULL);
|
||||
}
|
||||
|
||||
CHECKL(RingCheck(&arena->threadRing));
|
||||
CHECKD_NOSIG(Ring, &arena->threadRing);
|
||||
|
||||
CHECKL(BoolCheck(arena->insideShield));
|
||||
CHECKL(arena->shCacheLimit <= ShieldCacheSIZE);
|
||||
|
|
@ -189,8 +190,8 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena);
|
||||
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
CHECKL(RingCheck(&arena->greyRing[rank]));
|
||||
CHECKL(RingCheck(&arena->chainRing));
|
||||
CHECKD_NOSIG(Ring, &arena->greyRing[rank]);
|
||||
CHECKD_NOSIG(Ring, &arena->chainRing);
|
||||
|
||||
CHECKL(arena->tracedSize >= 0.0);
|
||||
CHECKL(arena->tracedTime >= 0.0);
|
||||
|
|
@ -212,7 +213,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
|
||||
/* we also check the statics now. <design/arena/#static.check> */
|
||||
CHECKL(BoolCheck(arenaRingInit));
|
||||
CHECKL(RingCheck(&arenaRing));
|
||||
CHECKD_NOSIG(Ring, &arenaRing);
|
||||
|
||||
CHECKL(BoolCheck(arena->emergency));
|
||||
|
||||
|
|
@ -632,7 +633,7 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context)
|
|||
|
||||
arenaClaimRingLock(); /* <design/arena/#lock.ring> */
|
||||
mps_exception_info = context;
|
||||
AVER(RingCheck(&arenaRing));
|
||||
AVERT(Ring, &arenaRing);
|
||||
|
||||
RING_FOR(node, &arenaRing, nextNode) {
|
||||
Globals arenaGlobals = RING_ELT(Globals, globalRing, node);
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_DONE(args);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* locus.c: LOCUS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -89,7 +89,7 @@ static Bool GenDescCheck(GenDesc gen)
|
|||
CHECKL(gen->mortality <= 1.0);
|
||||
CHECKL(gen->proflow >= 0.0);
|
||||
CHECKL(gen->proflow <= 1.0);
|
||||
CHECKL(RingCheck(&gen->locusRing));
|
||||
CHECKD_NOSIG(Ring, &gen->locusRing);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ Bool ChainCheck(Chain chain)
|
|||
|
||||
CHECKS(Chain, chain);
|
||||
CHECKU(Arena, chain->arena);
|
||||
CHECKL(RingCheck(&chain->chainRing));
|
||||
CHECKD_NOSIG(Ring, &chain->chainRing);
|
||||
CHECKL(TraceSetCheck(chain->activeTraces));
|
||||
CHECKL(chain->genCount > 0);
|
||||
for (i = 0; i < chain->genCount; ++i) {
|
||||
|
|
@ -370,7 +370,7 @@ Res ChainCondemnAll(Chain chain, Trace trace)
|
|||
Ring segNode, nextSegNode;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER((pool->class->attr & AttrGC) != 0);
|
||||
AVER(PoolHasAttr(pool, AttrGC));
|
||||
RING_FOR(segNode, PoolSegRing(pool), nextSegNode) {
|
||||
Seg seg = SegOfPoolRing(segNode);
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ Bool PoolGenCheck(PoolGen gen)
|
|||
/* nothing to check about serial */
|
||||
CHECKU(Pool, gen->pool);
|
||||
CHECKU(Chain, gen->chain);
|
||||
CHECKL(RingCheck(&gen->genRing));
|
||||
CHECKD_NOSIG(Ring, &gen->genRing);
|
||||
CHECKL(gen->newSize <= gen->totalSize);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -501,14 +501,14 @@ void LocusFinish(Arena arena)
|
|||
Bool LocusCheck(Arena arena)
|
||||
{
|
||||
/* Can't check arena, because this is part of ArenaCheck. */
|
||||
CHECKL(GenDescCheck(&arena->topGen));
|
||||
CHECKD(GenDesc, &arena->topGen);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@ static void runArenaTest(size_t size,
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_DONE(args);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* message.c: MPS/CLIENT MESSAGES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -53,7 +53,7 @@ Bool MessageCheck(Message message)
|
|||
CHECKS(Message, message);
|
||||
CHECKU(Arena, message->arena);
|
||||
CHECKD(MessageClass, message->class);
|
||||
CHECKL(RingCheck(&message->queueRing));
|
||||
CHECKD_NOSIG(Ring, &message->queueRing);
|
||||
/* postedClock is uncheckable for clocked message types, */
|
||||
/* but must be 0 for unclocked message types: */
|
||||
CHECKL(MessageIsClocked(message) || (message->postedClock == 0));
|
||||
|
|
@ -186,7 +186,7 @@ void MessageEmpty(Arena arena)
|
|||
static Bool MessageTypeEnabled(Arena arena, MessageType type)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
AVER(MessageTypeCheck(type));
|
||||
AVERT(MessageType, type);
|
||||
|
||||
return BTGet(arena->enabledMessageTypes, type);
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ static Bool MessageTypeEnabled(Arena arena, MessageType type)
|
|||
void MessageTypeEnable(Arena arena, MessageType type)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
AVER(MessageTypeCheck(type));
|
||||
AVERT(MessageType, type);
|
||||
|
||||
BTSet(arena->enabledMessageTypes, type);
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ void MessageTypeDisable(Arena arena, MessageType type)
|
|||
Message message;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVER(MessageTypeCheck(type));
|
||||
AVERT(MessageType, type);
|
||||
|
||||
/* Flush existing messages of this type */
|
||||
while(MessageGet(&message, arena, type)) {
|
||||
|
|
@ -252,7 +252,7 @@ Bool MessageGet(Message *messageReturn, Arena arena, MessageType type)
|
|||
|
||||
AVER(messageReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(MessageTypeCheck(type));
|
||||
AVERT(MessageType, type);
|
||||
|
||||
RING_FOR(node, &arena->messageRing, next) {
|
||||
Message message = RING_ELT(Message, queueRing, node);
|
||||
|
|
@ -427,7 +427,7 @@ const char *MessageNoGCStartWhy(Message message)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002, 2008 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpm.c: GENERAL MPM SUPPORT
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: Miscellaneous support for the implementation of the MPM
|
||||
* and pool classes.
|
||||
|
|
@ -132,7 +132,7 @@ Bool AlignCheck(Align align)
|
|||
|
||||
Bool (WordIsAligned)(Word word, Align align)
|
||||
{
|
||||
AVER(AlignCheck(align));
|
||||
AVERT(Align, align);
|
||||
return WordIsAligned(word, align);
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ Bool (WordIsAligned)(Word word, Align align)
|
|||
|
||||
Word (WordAlignUp)(Word word, Align align)
|
||||
{
|
||||
AVER(AlignCheck(align));
|
||||
AVERT(Align, align);
|
||||
return WordAlignUp(word, align);
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ Word (WordRoundUp)(Word word, Size modulus)
|
|||
|
||||
Word (WordAlignDown)(Word word, Align alignment)
|
||||
{
|
||||
AVER(AlignCheck(alignment));
|
||||
AVERT(Align, alignment);
|
||||
return WordAlignDown(word, alignment);
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ Shift SizeLog2(Size size)
|
|||
|
||||
Addr (AddrAlignDown)(Addr addr, Align alignment)
|
||||
{
|
||||
AVER(AlignCheck(alignment));
|
||||
AVERT(Align, alignment);
|
||||
return AddrAlignDown(addr, alignment);
|
||||
}
|
||||
|
||||
|
|
@ -604,7 +604,7 @@ Bool StringEqual(const char *s1, const char *s2)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -178,11 +178,13 @@ extern Bool PoolClassCheck(PoolClass class);
|
|||
extern Bool PoolCheck(Pool pool);
|
||||
extern Res PoolDescribe(Pool pool, mps_lib_FILE *stream);
|
||||
|
||||
/* Must be thread-safe. See <design/interface-c/#thread-safety>. */
|
||||
#define PoolArena(pool) ((pool)->arena)
|
||||
#define PoolAlignment(pool) ((pool)->alignment)
|
||||
#define PoolSegRing(pool) (&(pool)->segRing)
|
||||
#define PoolArenaRing(pool) (&(pool)->arenaRing)
|
||||
#define PoolOfArenaRing(node) RING_ELT(Pool, arenaRing, node)
|
||||
#define PoolHasAttr(pool, Attr) (((pool)->class->attr & (Attr)) != 0)
|
||||
|
||||
extern Bool PoolFormat(Format *formatReturn, Pool pool);
|
||||
|
||||
|
|
@ -263,10 +265,11 @@ extern Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf);
|
|||
extern Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr);
|
||||
extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step,
|
||||
void *p, size_t s);
|
||||
extern void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern PoolDebugMixin PoolNoDebugMixin(Pool pool);
|
||||
extern BufferClass PoolNoBufferClass(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpmtypes.h: MEMORY POOL MANAGER TYPES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2002, 2006 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: <design/type/>
|
||||
|
|
@ -41,7 +41,7 @@ typedef unsigned Shift; /* <design/type/#shift> */
|
|||
typedef unsigned Serial; /* <design/type/#serial> */
|
||||
typedef Addr Ref; /* <design/type/#ref> */
|
||||
typedef void *Pointer; /* <design/type/#pointer> */
|
||||
typedef Word Clock; /* processor time */
|
||||
typedef Word Clock; /* <design/type/#clock> */
|
||||
typedef MPS_T_ULONGEST ULongest; /* <design/type/#ulongest> */
|
||||
|
||||
typedef mps_arg_s ArgStruct;
|
||||
|
|
@ -60,7 +60,6 @@ typedef unsigned TraceSet; /* <design/trace/> */
|
|||
typedef unsigned TraceState; /* <design/trace/> */
|
||||
typedef unsigned AccessSet; /* <design/type/#access-set> */
|
||||
typedef unsigned Attr; /* <design/type/#attr> */
|
||||
typedef unsigned FormatVariety;
|
||||
typedef int RootVar; /* <design/type/#rootvar> */
|
||||
|
||||
typedef Word *BT; /* <design/bt/> */
|
||||
|
|
@ -300,16 +299,6 @@ typedef struct TraceMessageStruct *TraceMessage; /* trace end */
|
|||
AttrGC | AttrINCR_RB | AttrINCR_WB | AttrMOVINGGC)
|
||||
|
||||
|
||||
/* Format varieties */
|
||||
enum {
|
||||
FormatVarietyA = 1,
|
||||
FormatVarietyB,
|
||||
FormatVarietyAutoHeader,
|
||||
FormatVarietyFixed,
|
||||
FormatVarietyLIMIT
|
||||
};
|
||||
|
||||
|
||||
/* Segment preferences */
|
||||
enum {
|
||||
SegPrefHigh = 1,
|
||||
|
|
@ -465,7 +454,7 @@ typedef double WriteFD;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002, 2006 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This code bridges between the MPS interface to C,
|
||||
|
|
@ -46,11 +46,6 @@
|
|||
#include "mpm.h"
|
||||
#include "mps.h"
|
||||
#include "sac.h"
|
||||
#include "chain.h"
|
||||
|
||||
/* TODO: Remove these includes when varargs support is removed. */
|
||||
#include "mpsacl.h"
|
||||
#include "mpsavm.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
|
@ -459,7 +454,7 @@ mps_res_t mps_fmt_create_k(mps_fmt_t *mps_fmt_o,
|
|||
|
||||
AVER(mps_fmt_o != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
res = FormatCreate(&format, arena, args);
|
||||
|
||||
|
|
@ -657,7 +652,7 @@ mps_res_t mps_pool_create_k(mps_pool_t *mps_pool_o, mps_arena_t arena,
|
|||
AVER(mps_pool_o != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(PoolClass, class);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
res = PoolCreate(&pool, arena, class, args);
|
||||
|
||||
|
|
@ -1935,7 +1930,7 @@ void mps_chain_destroy(mps_chain_t chain)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -516,7 +516,8 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
if (rnd() % patternFREQ == 0) {
|
||||
switch(rnd() % 4) {
|
||||
case 0: case 1:
|
||||
case 0: /* fall through */
|
||||
case 1:
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp), "alloc_pattern_begin");
|
||||
++rampCount;
|
||||
break;
|
||||
|
|
@ -528,7 +529,7 @@ static void *test(void *arg, size_t s)
|
|||
--rampCount;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
die(mps_ap_alloc_pattern_reset(ap), "alloc_pattern_reset");
|
||||
rampCount = 0;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -173,7 +173,6 @@ static void stress_with_arena_class(mps_arena_class_t aclass, Bool zoned)
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, zoned);
|
||||
MPS_ARGS_DONE(args);
|
||||
die(mps_arena_create_k(&arena, aclass, args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@
|
|||
* .purpose.dispatch: Dispatch functions that implement the generic
|
||||
* function dispatch mechanism for Pool Classes (PoolAlloc, PoolFix,
|
||||
* etc.).
|
||||
* .purpose.core: A selection of default, trivial, or useful methods
|
||||
* that Pool Classes can use as the implementations for some of their
|
||||
* methods (such as PoolTrivWhiten, PoolNoFix, etc.).
|
||||
*
|
||||
* SOURCES
|
||||
*
|
||||
|
|
@ -40,13 +37,14 @@ SRCID(pool, "$Id$");
|
|||
|
||||
Bool PoolClassCheck(PoolClass class)
|
||||
{
|
||||
CHECKL(ProtocolClassCheck(&class->protocol));
|
||||
CHECKD(ProtocolClass, &class->protocol);
|
||||
CHECKL(class->name != NULL); /* Should be <=6 char C identifier */
|
||||
CHECKL(class->size >= sizeof(PoolStruct));
|
||||
/* Offset of generic Pool within class-specific instance cannot be */
|
||||
/* greater than the size of the class-specific portion of the instance */
|
||||
CHECKL(class->offset <= (size_t)(class->size - sizeof(PoolStruct)));
|
||||
CHECKL(AttrCheck(class->attr));
|
||||
CHECKL(!(class->attr & AttrMOVINGGC) || (class->attr & AttrGC));
|
||||
CHECKL(FUNCHECK(class->varargs));
|
||||
CHECKL(FUNCHECK(class->init));
|
||||
CHECKL(FUNCHECK(class->finish));
|
||||
|
|
@ -89,16 +87,14 @@ Bool PoolCheck(Pool pool)
|
|||
CHECKL(pool->serial < ArenaGlobals(pool->arena)->poolSerial);
|
||||
CHECKD(PoolClass, pool->class);
|
||||
CHECKU(Arena, pool->arena);
|
||||
CHECKL(RingCheck(&pool->arenaRing));
|
||||
CHECKL(RingCheck(&pool->bufferRing));
|
||||
CHECKD_NOSIG(Ring, &pool->arenaRing);
|
||||
CHECKD_NOSIG(Ring, &pool->bufferRing);
|
||||
/* Cannot check pool->bufferSerial */
|
||||
CHECKL(RingCheck(&pool->segRing));
|
||||
CHECKD_NOSIG(Ring, &pool->segRing);
|
||||
CHECKL(AlignCheck(pool->alignment));
|
||||
/* normally pool->format iff pool->class->attr&AttrFMT, but not */
|
||||
/* during pool initialization */
|
||||
if (pool->format != NULL) {
|
||||
CHECKL((pool->class->attr & AttrFMT) != 0);
|
||||
}
|
||||
/* normally pool->format iff PoolHasAttr(pool, AttrFMT), but during
|
||||
* pool initialization pool->format may not yet be set. */
|
||||
CHECKL(pool->format == NULL || PoolHasAttr(pool, AttrFMT));
|
||||
CHECKL(pool->fillMutatorSize >= 0.0);
|
||||
CHECKL(pool->emptyMutatorSize >= 0.0);
|
||||
CHECKL(pool->fillInternalSize >= 0.0);
|
||||
|
|
@ -289,9 +285,9 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER((pool->class->attr & AttrALLOC) != 0);
|
||||
AVER(PoolHasAttr(pool, AttrALLOC));
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
res = (*pool->class->alloc)(pReturn, pool, size, withReservoirPermit);
|
||||
if (res != ResOK)
|
||||
|
|
@ -319,7 +315,7 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
void PoolFree(Pool pool, Addr old, Size size)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER((pool->class->attr & AttrFREE) != 0);
|
||||
AVER(PoolHasAttr(pool, AttrFREE));
|
||||
AVER(old != NULL);
|
||||
/* The pool methods should check that old is in pool. */
|
||||
AVER(size > 0);
|
||||
|
|
@ -384,6 +380,7 @@ Res PoolScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
AVER(totalReturn != NULL);
|
||||
AVERT(ScanState, ss);
|
||||
AVERT(Pool, pool);
|
||||
AVER(PoolHasAttr(pool, AttrSCAN));
|
||||
AVERT(Seg, seg);
|
||||
AVER(ss->arena == pool->arena);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolabs.c: ABSTRACT POOL CLASSES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* PURPOSE
|
||||
|
|
@ -65,12 +65,13 @@ void PoolClassMixInAllocFree(PoolClass class)
|
|||
void PoolClassMixInBuffer(PoolClass class)
|
||||
{
|
||||
/* Can't check class because it's not initialized yet */
|
||||
class->attr |= (AttrBUF | AttrBUF_RESERVE);
|
||||
class->attr |= AttrBUF;
|
||||
class->bufferFill = PoolTrivBufferFill;
|
||||
class->bufferEmpty = PoolTrivBufferEmpty;
|
||||
/* By default, buffered pools treat frame operations as NOOPs */
|
||||
class->framePush = PoolTrivFramePush;
|
||||
class->framePop = PoolTrivFramePop;
|
||||
class->framePopPending = PoolTrivFramePopPending;
|
||||
class->bufferClass = BufferClassGet;
|
||||
}
|
||||
|
||||
|
|
@ -84,8 +85,10 @@ void PoolClassMixInScan(PoolClass class)
|
|||
class->access = PoolSegAccess;
|
||||
class->blacken = PoolTrivBlacken;
|
||||
class->grey = PoolTrivGrey;
|
||||
/* Scan is part of the scanning protocol - but there is */
|
||||
/* no useful default method */
|
||||
/* scan is part of the scanning protocol, but there is no useful
|
||||
* default method.
|
||||
*/
|
||||
class->scan = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -95,6 +98,10 @@ void PoolClassMixInFormat(PoolClass class)
|
|||
{
|
||||
/* Can't check class because it's not initialized yet */
|
||||
class->attr |= AttrFMT;
|
||||
/* walk is part of the format protocol, but there is no useful
|
||||
* default method.
|
||||
*/
|
||||
class->walk = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -103,10 +110,14 @@ void PoolClassMixInFormat(PoolClass class)
|
|||
void PoolClassMixInCollect(PoolClass class)
|
||||
{
|
||||
/* Can't check class because it's not initialized yet */
|
||||
class->attr |= (AttrGC | AttrINCR_RB);
|
||||
class->attr |= AttrGC;
|
||||
class->whiten = PoolTrivWhiten;
|
||||
/* Fix & reclaim are part of the collection protocol - but there */
|
||||
/* are no useful default methods for them. */
|
||||
/* fix, fixEmergency and reclaim are part of the collection
|
||||
* protocol, but there are no useful default methods for them.
|
||||
*/
|
||||
class->fix = NULL;
|
||||
class->fixEmergency = NULL;
|
||||
class->reclaim = NULL;
|
||||
class->rampBegin = PoolTrivRampBegin;
|
||||
class->rampEnd = PoolTrivRampEnd;
|
||||
}
|
||||
|
|
@ -145,7 +156,7 @@ DEFINE_CLASS(AbstractPoolClass, class)
|
|||
class->framePopPending = PoolNoFramePopPending;
|
||||
class->addrObject = PoolNoAddrObject;
|
||||
class->walk = PoolNoWalk;
|
||||
class->freewalk = PoolNoFreeWalk;
|
||||
class->freewalk = PoolTrivFreeWalk;
|
||||
class->bufferClass = PoolNoBufferClass;
|
||||
class->describe = PoolTrivDescribe;
|
||||
class->debugMixin = PoolNoDebugMixin;
|
||||
|
|
@ -199,7 +210,7 @@ void PoolTrivFinish(Pool pool)
|
|||
Res PoolTrivInit(Pool pool, ArgList args)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
UNUSED(args);
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -210,7 +221,7 @@ Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
NOTREACHED;
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
|
@ -221,7 +232,7 @@ Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
return ResLIMIT;
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +262,7 @@ Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
NOTREACHED;
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
|
@ -268,7 +279,7 @@ Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
res = PoolAlloc(&p, pool, size, withReservoirPermit);
|
||||
if(res != ResOK) return res;
|
||||
|
|
@ -596,7 +607,7 @@ Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame)
|
|||
{
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buf);
|
||||
/* frame is of a abstract type & can't be checked */
|
||||
/* frame is of an abstract type & can't be checked */
|
||||
UNUSED(frame);
|
||||
NOTREACHED;
|
||||
return ResUNIMPL;
|
||||
|
|
@ -607,7 +618,7 @@ void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame)
|
|||
{
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buf);
|
||||
/* frame is of a abstract type & can't be checked */
|
||||
/* frame is of an abstract type & can't be checked */
|
||||
UNUSED(frame);
|
||||
NOTREACHED;
|
||||
}
|
||||
|
|
@ -626,12 +637,22 @@ Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame)
|
|||
{
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buf);
|
||||
/* frame is of a abstract type & can't be checked */
|
||||
/* frame is of an abstract type & can't be checked */
|
||||
UNUSED(frame);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buf);
|
||||
/* frame is of an abstract type & can't be checked */
|
||||
UNUSED(frame);
|
||||
NOOP;
|
||||
}
|
||||
|
||||
|
||||
Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
||||
{
|
||||
AVER(pReturn != NULL);
|
||||
|
|
@ -656,7 +677,7 @@ void PoolNoWalk(Pool pool, Seg seg,
|
|||
}
|
||||
|
||||
|
||||
void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(FUNCHECK(f));
|
||||
|
|
@ -677,7 +698,7 @@ BufferClass PoolNoBufferClass(void)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -341,6 +341,7 @@ DEFINE_SEG_CLASS(amcSegClass, class)
|
|||
class->size = sizeof(amcSegStruct);
|
||||
class->init = AMCSegInit;
|
||||
class->describe = AMCSegDescribe;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -484,7 +485,7 @@ static Bool amcGenCheck(amcGen gen)
|
|||
amc = amcGenAMC(gen);
|
||||
CHECKU(AMC, amc);
|
||||
CHECKD(Buffer, gen->forward);
|
||||
CHECKL(RingCheck(&gen->amcRing));
|
||||
CHECKD_NOSIG(Ring, &gen->amcRing);
|
||||
CHECKL((gen->pgen.totalSize == 0) == (gen->segs == 0));
|
||||
arena = amc->poolStruct.arena;
|
||||
CHECKL(gen->pgen.totalSize >= gen->segs * ArenaAlign(arena));
|
||||
|
|
@ -526,7 +527,7 @@ typedef struct amcBufStruct {
|
|||
static Bool amcBufCheck(amcBuf amcbuf)
|
||||
{
|
||||
CHECKS(amcBuf, amcbuf);
|
||||
CHECKL(SegBufCheck(&amcbuf->segbufStruct));
|
||||
CHECKD(SegBuf, &amcbuf->segbufStruct);
|
||||
if(amcbuf->gen != NULL)
|
||||
CHECKD(amcGen, amcbuf->gen);
|
||||
CHECKL(BoolCheck(amcbuf->forHashArrays));
|
||||
|
|
@ -632,6 +633,7 @@ DEFINE_BUFFER_CLASS(amcBufClass, class)
|
|||
class->size = sizeof(amcBufStruct);
|
||||
class->init = AMCBufInit;
|
||||
class->finish = AMCBufFinish;
|
||||
AVERT(BufferClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -776,7 +778,7 @@ static void AMCVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[1].key = MPS_KEY_CHAIN;
|
||||
args[1].val.chain = va_arg(varargs, Chain);
|
||||
args[2].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2087,7 +2089,7 @@ static void AMCTraceEnd(Pool pool, Trace trace)
|
|||
amc = Pool2AMC(pool);
|
||||
AVERT(AMC, amc);
|
||||
ti = trace->ti;
|
||||
AVER(TraceIdCheck(ti));
|
||||
AVERT(TraceId, ti);
|
||||
|
||||
STATISTIC_STAT ({
|
||||
Count pRetMin = 100;
|
||||
|
|
@ -2329,23 +2331,23 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
}
|
||||
|
||||
|
||||
/* AMCPoolClass -- the class definition */
|
||||
/* AMCZPoolClass -- the class definition */
|
||||
|
||||
DEFINE_POOL_CLASS(AMCPoolClass, this)
|
||||
DEFINE_POOL_CLASS(AMCZPoolClass, this)
|
||||
{
|
||||
INHERIT_CLASS(this, AbstractCollectPoolClass);
|
||||
INHERIT_CLASS(this, AbstractSegBufPoolClass);
|
||||
PoolClassMixInFormat(this);
|
||||
this->name = "AMC";
|
||||
PoolClassMixInCollect(this);
|
||||
this->name = "AMCZ";
|
||||
this->size = sizeof(AMCStruct);
|
||||
this->offset = offsetof(AMCStruct, poolStruct);
|
||||
this->attr |= AttrMOVINGGC;
|
||||
this->varargs = AMCVarargs;
|
||||
this->init = AMCInit;
|
||||
this->init = AMCZInit;
|
||||
this->finish = AMCFinish;
|
||||
this->bufferFill = AMCBufferFill;
|
||||
this->bufferEmpty = AMCBufferEmpty;
|
||||
this->whiten = AMCWhiten;
|
||||
this->scan = AMCScan;
|
||||
this->fix = AMCFix;
|
||||
this->fixEmergency = AMCFixEmergency;
|
||||
this->reclaim = AMCReclaim;
|
||||
|
|
@ -2356,19 +2358,20 @@ DEFINE_POOL_CLASS(AMCPoolClass, this)
|
|||
this->walk = AMCWalk;
|
||||
this->bufferClass = amcBufClassGet;
|
||||
this->describe = AMCDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
/* AMCZPoolClass -- the class definition */
|
||||
/* AMCPoolClass -- the class definition */
|
||||
|
||||
DEFINE_POOL_CLASS(AMCZPoolClass, this)
|
||||
DEFINE_POOL_CLASS(AMCPoolClass, this)
|
||||
{
|
||||
INHERIT_CLASS(this, AMCPoolClass);
|
||||
this->name = "AMCZ";
|
||||
this->attr &= ~(AttrSCAN | AttrINCR_RB);
|
||||
this->init = AMCZInit;
|
||||
this->grey = PoolNoGrey;
|
||||
this->scan = PoolNoScan;
|
||||
INHERIT_CLASS(this, AMCZPoolClass);
|
||||
PoolClassMixInScan(this);
|
||||
this->name = "AMC";
|
||||
this->init = AMCInit;
|
||||
this->scan = AMCScan;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2448,7 +2451,7 @@ static Bool AMCCheck(AMC amc)
|
|||
CHECKD(Pool, &amc->poolStruct);
|
||||
CHECKL(IsSubclassPoly(amc->poolStruct.class, EnsureAMCPoolClass()));
|
||||
CHECKL(RankSetCheck(amc->rankSet));
|
||||
CHECKL(RingCheck(&amc->genRing));
|
||||
CHECKD_NOSIG(Ring, &amc->genRing);
|
||||
CHECKL(BoolCheck(amc->gensBooted));
|
||||
if(amc->gensBooted) {
|
||||
CHECKD(amcGen, amc->nursery);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolams.c: AUTOMATIC MARK & SWEEP POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
|
|
@ -48,7 +48,7 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
{
|
||||
Seg seg = AMSSeg2Seg(amsseg);
|
||||
CHECKS(AMSSeg, amsseg);
|
||||
CHECKL(GCSegCheck(&amsseg->gcSegStruct));
|
||||
CHECKD(GCSeg, &amsseg->gcSegStruct);
|
||||
CHECKU(AMS, amsseg->ams);
|
||||
CHECKL(AMS2Pool(amsseg->ams) == SegPool(seg));
|
||||
CHECKD_NOSIG(Ring, &amsseg->segRing);
|
||||
|
|
@ -60,7 +60,7 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
CHECKL(BoolCheck(amsseg->allocTableInUse));
|
||||
if (!amsseg->allocTableInUse)
|
||||
CHECKL(amsseg->firstFree <= amsseg->grains);
|
||||
CHECKL(amsseg->allocTable != NULL);
|
||||
CHECKD_NOSIG(BT, amsseg->allocTable);
|
||||
|
||||
if (SegWhite(seg) != TraceSetEMPTY) {
|
||||
/* <design/poolams/#colour.single> */
|
||||
|
|
@ -71,8 +71,8 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
CHECKL(BoolCheck(amsseg->marksChanged));
|
||||
CHECKL(BoolCheck(amsseg->ambiguousFixes));
|
||||
CHECKL(BoolCheck(amsseg->colourTablesInUse));
|
||||
CHECKL(amsseg->nongreyTable != NULL);
|
||||
CHECKL(amsseg->nonwhiteTable != NULL);
|
||||
CHECKD_NOSIG(BT, amsseg->nongreyTable);
|
||||
CHECKD_NOSIG(BT, amsseg->nonwhiteTable);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(AMS, ams);
|
||||
arena = PoolArena(pool);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(AMSSegClass);
|
||||
|
|
@ -609,6 +609,7 @@ DEFINE_CLASS(AMSSegClass, class)
|
|||
class->merge = AMSSegMerge;
|
||||
class->split = AMSSegSplit;
|
||||
class->describe = AMSSegDescribe;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -637,7 +638,7 @@ static Res AMSSegSizePolicy(Size *sizeReturn,
|
|||
AVER(sizeReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
|
||||
|
|
@ -666,7 +667,7 @@ static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size,
|
|||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(RankSet, rankSet);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
ams = Pool2AMS(pool);
|
||||
AVERT(AMS,ams);
|
||||
|
|
@ -734,7 +735,7 @@ static void AMSVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[2].key = MPS_KEY_AMS_SUPPORT_AMBIGUOUS;
|
||||
args[2].val.b = va_arg(varargs, Bool);
|
||||
args[3].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
static void AMSDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
||||
|
|
@ -763,7 +764,7 @@ static Res AMSInit(Pool pool, ArgList args)
|
|||
ArgStruct arg;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
if (ArgPick(&arg, args, MPS_KEY_CHAIN))
|
||||
chain = arg.val.chain;
|
||||
|
|
@ -932,7 +933,7 @@ static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Check that we're not in the grey mutator phase (see */
|
||||
/* <design/poolams/#fill.colour>). */
|
||||
|
|
@ -996,7 +997,7 @@ static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
AVERT(Buffer,buffer);
|
||||
AVER(BufferIsReady(buffer));
|
||||
seg = BufferSeg(buffer);
|
||||
AVER(SegCheck(seg));
|
||||
AVERT(Seg, seg);
|
||||
AVER(init <= limit);
|
||||
AVER(AddrIsAligned(init, PoolAlignment(pool)));
|
||||
AVER(AddrIsAligned(limit, PoolAlignment(pool)));
|
||||
|
|
@ -1074,7 +1075,7 @@ static Res AMSCondemn(Pool pool, Trace trace, Seg seg)
|
|||
AVERT(AMS, ams);
|
||||
|
||||
AVERT(Trace, trace);
|
||||
AVER(SegCheck(seg));
|
||||
AVERT(Seg, seg);
|
||||
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
AVERT(AMSSeg, amsseg);
|
||||
|
|
@ -1260,7 +1261,7 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
|||
AVER(clos != NULL);
|
||||
closure = (amsScanClosure)clos;
|
||||
AVERT(ScanState, closure->ss);
|
||||
AVER(BoolCheck(closure->scanAllObjects));
|
||||
AVERT(Bool, closure->scanAllObjects);
|
||||
|
||||
format = AMS2Pool(amsseg->ams)->format;
|
||||
AVERT(Format, format);
|
||||
|
|
@ -1306,7 +1307,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
ams = Pool2AMS(pool);
|
||||
AVERT(AMS, ams);
|
||||
arena = PoolArena(pool);
|
||||
AVER(SegCheck(seg));
|
||||
AVERT(Seg, seg);
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
AVERT(AMSSeg, amsseg);
|
||||
|
||||
|
|
@ -1684,8 +1685,10 @@ DEFINE_CLASS(AMSPoolClass, this)
|
|||
this->fix = AMSFix;
|
||||
this->fixEmergency = AMSFix;
|
||||
this->reclaim = AMSReclaim;
|
||||
this->walk = PoolNoWalk; /* TODO: job003738 */
|
||||
this->freewalk = AMSFreeWalk;
|
||||
this->describe = AMSDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1713,6 +1716,7 @@ DEFINE_POOL_CLASS(AMSDebugPoolClass, this)
|
|||
this->size = sizeof(AMSDebugStruct);
|
||||
this->varargs = AMSDebugVarargs;
|
||||
this->debugMixin = AMSDebugMixin;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1721,7 +1725,7 @@ DEFINE_POOL_CLASS(AMSDebugPoolClass, this)
|
|||
Bool AMSCheck(AMS ams)
|
||||
{
|
||||
CHECKS(AMS, ams);
|
||||
CHECKL(PoolCheck(AMS2Pool(ams)));
|
||||
CHECKD(Pool, AMS2Pool(ams));
|
||||
CHECKL(IsSubclassPoly(AMS2Pool(ams)->class, AMSPoolClassGet()));
|
||||
CHECKL(PoolAlignment(AMS2Pool(ams)) == ((Size)1 << ams->grainShift));
|
||||
CHECKL(PoolAlignment(AMS2Pool(ams)) == AMS2Pool(ams)->format->alignment);
|
||||
|
|
@ -1729,7 +1733,7 @@ Bool AMSCheck(AMS ams)
|
|||
CHECKD(PoolGen, &ams->pgen);
|
||||
CHECKL(SizeIsAligned(ams->size, ArenaAlign(PoolArena(AMS2Pool(ams)))));
|
||||
CHECKL(FUNCHECK(ams->segSize));
|
||||
CHECKL(RingCheck(&ams->segRing));
|
||||
CHECKD_NOSIG(Ring, &ams->segRing);
|
||||
CHECKL(FUNCHECK(ams->allocRing));
|
||||
CHECKL(FUNCHECK(ams->segsDestroy));
|
||||
CHECKL(FUNCHECK(ams->segClass));
|
||||
|
|
@ -1740,7 +1744,7 @@ Bool AMSCheck(AMS ams)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
*
|
||||
* DESIGN
|
||||
|
|
@ -187,7 +187,7 @@ static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(Pool, pool);
|
||||
arena = PoolArena(pool);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
ArgRequire(&arg, args, awlKeySegRankSet);
|
||||
rankSet = arg.val.u;
|
||||
AVERT(RankSet, rankSet);
|
||||
|
|
@ -288,6 +288,7 @@ DEFINE_SEG_CLASS(AWLSegClass, class)
|
|||
class->size = sizeof(AWLSegStruct);
|
||||
class->init = AWLSegInit;
|
||||
class->finish = AWLSegFinish;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -450,10 +451,10 @@ static Res AWLSegCreate(AWLSeg *awlsegReturn,
|
|||
Arena arena;
|
||||
|
||||
AVER(awlsegReturn != NULL);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
awl = Pool2AWL(pool);
|
||||
AVERT(AWL, awl);
|
||||
|
|
@ -519,7 +520,7 @@ static void AWLVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[1].key = MPS_KEY_AWL_FIND_DEPENDENT;
|
||||
args[1].val.addr_method = va_arg(varargs, mps_awl_find_dependent_t);
|
||||
args[2].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -626,7 +627,7 @@ static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
awl = Pool2AWL(pool);
|
||||
AVERT(AWL, awl);
|
||||
|
|
@ -834,7 +835,7 @@ static void AWLBlacken(Pool pool, TraceSet traceSet, Seg seg)
|
|||
AWLSeg awlseg;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(TraceSetCheck(traceSet));
|
||||
AVERT(TraceSet, traceSet);
|
||||
AVERT(Seg, seg);
|
||||
|
||||
awl = Pool2AWL(pool);
|
||||
|
|
@ -1280,6 +1281,7 @@ DEFINE_POOL_CLASS(AWLPoolClass, this)
|
|||
this->fixEmergency = AWLFix;
|
||||
this->reclaim = AWLReclaim;
|
||||
this->walk = AWLWalk;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1307,7 +1309,7 @@ static Bool AWLCheck(AWL awl)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poollo.c: LEAF POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -73,6 +73,7 @@ DEFINE_SEG_CLASS(LOSegClass, class)
|
|||
class->size = sizeof(LOSegStruct);
|
||||
class->init = loSegInit;
|
||||
class->finish = loSegFinish;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ DEFINE_SEG_CLASS(LOSegClass, class)
|
|||
static Bool LOSegCheck(LOSeg loseg)
|
||||
{
|
||||
CHECKS(LOSeg, loseg);
|
||||
CHECKL(GCSegCheck(&loseg->gcSegStruct));
|
||||
CHECKD(GCSeg, &loseg->gcSegStruct);
|
||||
CHECKU(LO, loseg->lo);
|
||||
CHECKL(loseg->mark != NULL);
|
||||
CHECKL(loseg->alloc != NULL);
|
||||
|
|
@ -112,7 +113,7 @@ static Res loSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(Pool, pool);
|
||||
arena = PoolArena(pool);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
lo = PoolPoolLO(pool);
|
||||
AVERT(LO, lo);
|
||||
|
||||
|
|
@ -286,7 +287,7 @@ static Res loSegCreate(LOSeg *loSegReturn, Pool pool, Size size,
|
|||
AVER(loSegReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
lo = PoolPoolLO(pool);
|
||||
AVERT(LO, lo);
|
||||
|
||||
|
|
@ -460,7 +461,7 @@ static void LOVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[0].key = MPS_KEY_FORMAT;
|
||||
args[0].val.format = va_arg(varargs, Format);
|
||||
args[1].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -558,7 +559,7 @@ static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(BufferRankSet(buffer) == RankSetEMPTY);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Try to find a segment with enough space already. */
|
||||
RING_FOR(node, &pool->segRing, nextNode) {
|
||||
|
|
@ -774,25 +775,23 @@ static void LOReclaim(Pool pool, Trace trace, Seg seg)
|
|||
|
||||
DEFINE_POOL_CLASS(LOPoolClass, this)
|
||||
{
|
||||
INHERIT_CLASS(this, AbstractCollectPoolClass);
|
||||
INHERIT_CLASS(this, AbstractSegBufPoolClass);
|
||||
PoolClassMixInFormat(this);
|
||||
PoolClassMixInCollect(this);
|
||||
this->name = "LO";
|
||||
this->size = sizeof(LOStruct);
|
||||
this->offset = offsetof(LOStruct, poolStruct);
|
||||
this->attr &= ~(AttrSCAN | AttrINCR_RB);
|
||||
this->varargs = LOVarargs;
|
||||
this->init = LOInit;
|
||||
this->finish = LOFinish;
|
||||
this->bufferFill = LOBufferFill;
|
||||
this->bufferEmpty = LOBufferEmpty;
|
||||
this->whiten = LOWhiten;
|
||||
this->grey = PoolNoGrey;
|
||||
this->blacken = PoolNoBlacken;
|
||||
this->scan = PoolNoScan;
|
||||
this->fix = LOFix;
|
||||
this->fixEmergency = LOFix;
|
||||
this->reclaim = LOReclaim;
|
||||
this->walk = LOWalk;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -821,7 +820,7 @@ static Bool LOCheck(LO lo)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmfs.c: MANUAL FIXED SMALL UNIT POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is the implementation of the MFS pool class.
|
||||
*
|
||||
|
|
@ -86,7 +86,7 @@ static void MFSVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[1].key = MPS_KEY_MFS_UNIT_SIZE;
|
||||
args[1].val.size = va_arg(varargs, Size);
|
||||
args[2].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
ARG_DEFINE_KEY(mfs_unit_size, Size);
|
||||
|
|
@ -102,7 +102,7 @@ static Res MFSInit(Pool pool, ArgList args)
|
|||
ArgStruct arg;
|
||||
|
||||
AVER(pool != NULL);
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
|
||||
ArgRequire(&arg, args, MPS_KEY_MFS_UNIT_SIZE);
|
||||
unitSize = arg.val.size;
|
||||
|
|
@ -116,7 +116,7 @@ static Res MFSInit(Pool pool, ArgList args)
|
|||
extendSelf = arg.val.b;
|
||||
|
||||
AVER(extendBy >= unitSize);
|
||||
AVER(BoolCheck(extendSelf));
|
||||
AVERT(Bool, extendSelf);
|
||||
|
||||
mfs = PoolPoolMFS(pool);
|
||||
arena = PoolArena(pool);
|
||||
|
|
@ -250,7 +250,7 @@ static Res MFSAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
AVER(pReturn != NULL);
|
||||
AVER(size == mfs->unroundedUnitSize);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
f = mfs->freeList;
|
||||
|
||||
|
|
@ -347,6 +347,7 @@ DEFINE_POOL_CLASS(MFSPoolClass, this)
|
|||
this->alloc = MFSAlloc;
|
||||
this->free = MFSFree;
|
||||
this->describe = MFSDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -369,7 +370,7 @@ Bool MFSCheck(MFS mfs)
|
|||
CHECKS(MFS, mfs);
|
||||
CHECKD(Pool, &mfs->poolStruct);
|
||||
CHECKL(mfs->poolStruct.class == EnsureMFSPoolClass());
|
||||
CHECKL(mfs->unroundedUnitSize >= UNIT_MIN);
|
||||
CHECKL(mfs->unitSize >= UNIT_MIN);
|
||||
CHECKL(mfs->extendBy >= UNIT_MIN);
|
||||
CHECKL(BoolCheck(mfs->extendSelf));
|
||||
arena = PoolArena(&mfs->poolStruct);
|
||||
|
|
@ -377,7 +378,7 @@ Bool MFSCheck(MFS mfs)
|
|||
CHECKL(SizeAlignUp(mfs->unroundedUnitSize, mfs->poolStruct.alignment) ==
|
||||
mfs->unitSize);
|
||||
if(mfs->tractList != NULL) {
|
||||
CHECKL(TractCheck(mfs->tractList));
|
||||
CHECKD_NOSIG(Tract, mfs->tractList);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -385,7 +386,7 @@ Bool MFSCheck(MFS mfs)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmrg.c: MANUAL RANK GUARDIAN POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
|
|
@ -130,9 +130,9 @@ static Bool MRGCheck(MRG mrg)
|
|||
CHECKS(MRG, mrg);
|
||||
CHECKD(Pool, &mrg->poolStruct);
|
||||
CHECKL(MRG2Pool(mrg)->class == PoolClassMRG());
|
||||
CHECKL(RingCheck(&mrg->entryRing));
|
||||
CHECKL(RingCheck(&mrg->freeRing));
|
||||
CHECKL(RingCheck(&mrg->refRing));
|
||||
CHECKD_NOSIG(Ring, &mrg->entryRing);
|
||||
CHECKD_NOSIG(Ring, &mrg->freeRing);
|
||||
CHECKD_NOSIG(Ring, &mrg->refRing);
|
||||
CHECKL(mrg->extendBy == ArenaAlign(PoolArena(MRG2Pool(mrg))));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ static Bool MRGLinkSegCheck(MRGLinkSeg linkseg)
|
|||
Seg seg;
|
||||
|
||||
CHECKS(MRGLinkSeg, linkseg);
|
||||
CHECKL(SegCheck(&linkseg->segStruct));
|
||||
CHECKD(Seg, &linkseg->segStruct);
|
||||
seg = LinkSeg2Seg(linkseg);
|
||||
if (NULL != linkseg->refSeg) { /* see .link.nullref */
|
||||
CHECKL(SegPool(seg) == SegPool(RefSeg2Seg(linkseg->refSeg)));
|
||||
|
|
@ -198,10 +198,10 @@ static Bool MRGRefSegCheck(MRGRefSeg refseg)
|
|||
Seg seg;
|
||||
|
||||
CHECKS(MRGRefSeg, refseg);
|
||||
CHECKL(GCSegCheck(&refseg->gcSegStruct));
|
||||
CHECKD(GCSeg, &refseg->gcSegStruct);
|
||||
seg = RefSeg2Seg(refseg);
|
||||
CHECKL(SegPool(seg) == SegPool(LinkSeg2Seg(refseg->linkSeg)));
|
||||
CHECKL(RingCheck(&refseg->mrgRing));
|
||||
CHECKD_NOSIG(Ring, &refseg->mrgRing);
|
||||
CHECKD(MRGLinkSeg, refseg->linkSeg);
|
||||
CHECKL(refseg->linkSeg->refSeg == refseg);
|
||||
return TRUE;
|
||||
|
|
@ -224,7 +224,7 @@ static Res MRGLinkSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
mrg = Pool2MRG(pool);
|
||||
AVERT(MRG, mrg);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(MRGLinkSegClass);
|
||||
|
|
@ -267,7 +267,7 @@ static Res MRGRefSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
mrg = Pool2MRG(pool);
|
||||
AVERT(MRG, mrg);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
AVERT(MRGLinkSeg, linkseg);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
|
|
@ -302,6 +302,7 @@ DEFINE_SEG_CLASS(MRGLinkSegClass, class)
|
|||
class->name = "MRGLSEG";
|
||||
class->size = sizeof(MRGLinkSegStruct);
|
||||
class->init = MRGLinkSegInit;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -314,6 +315,7 @@ DEFINE_SEG_CLASS(MRGRefSegClass, class)
|
|||
class->name = "MRGRSEG";
|
||||
class->size = sizeof(MRGRefSegStruct);
|
||||
class->init = MRGRefSegInit;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -629,7 +631,7 @@ static Res MRGInit(Pool pool, ArgList args)
|
|||
MRG mrg;
|
||||
|
||||
AVER(pool != NULL); /* Can't check more; see pool contract @@@@ */
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
UNUSED(args);
|
||||
|
||||
mrg = Pool2MRG(pool);
|
||||
|
|
@ -855,13 +857,14 @@ DEFINE_POOL_CLASS(MRGPoolClass, this)
|
|||
this->name = "MRG";
|
||||
this->size = sizeof(MRGStruct);
|
||||
this->offset = offsetof(MRGStruct, poolStruct);
|
||||
this->attr |= (AttrSCAN | AttrFREE | AttrINCR_RB);
|
||||
this->attr |= AttrSCAN;
|
||||
this->init = MRGInit;
|
||||
this->finish = MRGFinish;
|
||||
this->grey = PoolTrivGrey;
|
||||
this->blacken = PoolTrivBlacken;
|
||||
this->scan = MRGScan;
|
||||
this->describe = MRGDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -873,7 +876,7 @@ PoolClass PoolClassMRG(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmv.c: MANUAL VARIABLE POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* **** RESTRICTION: This pool may not allocate from the arena control
|
||||
|
|
@ -138,11 +138,11 @@ static Bool MVSpanCheck(MVSpan span)
|
|||
|
||||
CHECKS(MVSpan, span);
|
||||
|
||||
CHECKL(RingCheck(&span->spans));
|
||||
CHECKD_NOSIG(Ring, &span->spans);
|
||||
CHECKU(MV, span->mv);
|
||||
CHECKD_NOSIG(Tract, span->tract);
|
||||
CHECKL(MVBlockCheck(&span->base));
|
||||
CHECKL(MVBlockCheck(&span->limit));
|
||||
CHECKD_NOSIG(MVBlock, &span->base);
|
||||
CHECKD_NOSIG(MVBlock, &span->limit);
|
||||
/* The block chain starts with the base sentinel. */
|
||||
CHECKL(span->blocks == &span->base);
|
||||
/* Since there is a limit sentinel, the chain can't end just after the */
|
||||
|
|
@ -193,7 +193,7 @@ static void MVVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[2].key = MPS_KEY_MAX_SIZE;
|
||||
args[2].val.size = va_arg(varargs, Size);
|
||||
args[3].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
static void MVDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
||||
|
|
@ -570,7 +570,7 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
span->mv = mv;
|
||||
/* Set the p field for each tract of the span */
|
||||
TRACT_FOR(tract, addr, arena, base, limit) {
|
||||
AVER(TractCheck(tract));
|
||||
AVERT(Tract, tract);
|
||||
AVER(TractP(tract) == NULL);
|
||||
AVER(TractPool(tract) == pool);
|
||||
TractSetP(tract, (void *)span);
|
||||
|
|
@ -792,6 +792,7 @@ DEFINE_POOL_CLASS(MVPoolClass, this)
|
|||
this->alloc = MVAlloc;
|
||||
this->free = MVFree;
|
||||
this->describe = MVDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -811,6 +812,7 @@ DEFINE_POOL_CLASS(MVDebugPoolClass, this)
|
|||
this->size = sizeof(MVDebugStruct);
|
||||
this->varargs = MVDebugVarargs;
|
||||
this->debugMixin = MVDebugMixin;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -901,7 +903,7 @@ Bool MVCheck(MV mv)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmv2.c: MANUAL VARIABLE-SIZED TEMPORAL POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: A manual-variable pool designed to take advantage of
|
||||
* placement according to predicted deathtime.
|
||||
|
|
@ -145,6 +145,7 @@ DEFINE_POOL_CLASS(MVTPoolClass, this)
|
|||
this->bufferFill = MVTBufferFill;
|
||||
this->bufferEmpty = MVTBufferEmpty;
|
||||
this->describe = MVTDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
/* Macros */
|
||||
|
|
@ -199,7 +200,7 @@ static void MVTVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[4].key = MPS_KEY_MVT_FRAG_LIMIT;
|
||||
args[4].val.d = (double)va_arg(varargs, Count) / 100.0;
|
||||
args[5].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -363,9 +364,7 @@ static Bool MVTCheck(MVT mvt)
|
|||
CHECKD(Pool, &mvt->poolStruct);
|
||||
CHECKL(mvt->poolStruct.class == MVTPoolClassGet());
|
||||
CHECKD(CBS, &mvt->cbsStruct);
|
||||
/* CHECKL(CBSCheck(MVTCBS(mvt))); */
|
||||
CHECKD(ABQ, &mvt->abqStruct);
|
||||
/* CHECKL(ABQCheck(MVTABQ(mvt))); */
|
||||
CHECKD(Freelist, &mvt->flStruct);
|
||||
CHECKL(mvt->reuseSize >= 2 * mvt->fillSize);
|
||||
CHECKL(mvt->fillSize >= mvt->maxSize);
|
||||
|
|
@ -379,8 +378,7 @@ static Bool MVTCheck(MVT mvt)
|
|||
if (mvt->splinter) {
|
||||
CHECKL(AddrOffset(mvt->splinterBase, mvt->splinterLimit) >=
|
||||
mvt->minSize);
|
||||
/* CHECKD(Seg, mvt->splinterSeg); */
|
||||
CHECKL(SegCheck(mvt->splinterSeg));
|
||||
CHECKD(Seg, mvt->splinterSeg);
|
||||
CHECKL(mvt->splinterBase >= SegBase(mvt->splinterSeg));
|
||||
CHECKL(mvt->splinterLimit <= SegLimit(mvt->splinterSeg));
|
||||
}
|
||||
|
|
@ -687,7 +685,7 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(BufferIsReset(buffer));
|
||||
AVER(minSize > 0);
|
||||
AVER(SizeIsAligned(minSize, pool->alignment));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Allocate oversize blocks exactly, directly from the arena.
|
||||
<design/poolmvt/#arch.ap.no-fit.oversize> */
|
||||
|
|
@ -1488,7 +1486,7 @@ CBS _mps_mvt_cbs(mps_pool_t mps_pool) {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmvff.c: First Fit Manual Variable Pool
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This is a pool class for manually managed objects of
|
||||
|
|
@ -228,7 +228,7 @@ static Res MVFFAddSeg(Seg *segReturn,
|
|||
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
pool = MVFF2Pool(mvff);
|
||||
arena = PoolArena(pool);
|
||||
|
|
@ -339,7 +339,7 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size,
|
|||
|
||||
AVER(aReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
size = SizeAlignUp(size, PoolAlignment(pool));
|
||||
|
||||
|
|
@ -510,7 +510,7 @@ static void MVFFVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[5].key = MPS_KEY_MVFF_FIRST_FIT;
|
||||
args[5].val.b = va_arg(varargs, Bool);
|
||||
args[6].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
static void MVFFDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
||||
|
|
@ -571,9 +571,9 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
AVER(avgSize > 0); /* .arg.check */
|
||||
AVER(avgSize <= extendBy); /* .arg.check */
|
||||
AVER(SizeIsAligned(align, MPS_PF_ALIGN));
|
||||
AVER(BoolCheck(slotHigh));
|
||||
AVER(BoolCheck(arenaHigh));
|
||||
AVER(BoolCheck(firstFit));
|
||||
AVERT(Bool, slotHigh);
|
||||
AVERT(Bool, arenaHigh);
|
||||
AVERT(Bool, firstFit);
|
||||
|
||||
mvff = Pool2MVFF(pool);
|
||||
|
||||
|
|
@ -720,6 +720,7 @@ DEFINE_POOL_CLASS(MVFFPoolClass, this)
|
|||
this->bufferFill = MVFFBufferFill;
|
||||
this->bufferEmpty = MVFFBufferEmpty;
|
||||
this->describe = MVFFDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -739,6 +740,7 @@ DEFINE_POOL_CLASS(MVFFDebugPoolClass, this)
|
|||
this->size = sizeof(MVFFDebugStruct);
|
||||
this->varargs = MVFFDebugVarargs;
|
||||
this->debugMixin = MVFFDebugMixin;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -828,7 +830,7 @@ CBS _mps_mvff_cbs(mps_pool_t mps_pool) {
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* pooln.c: NULL POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "pooln.h"
|
||||
|
|
@ -71,7 +71,7 @@ static Res NAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
AVER(pReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
return ResLIMIT; /* limit of nil blocks exceeded */
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ static Res NBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Buffer, buffer);
|
||||
AVER(BufferIsReset(buffer));
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
NOTREACHED; /* can't create buffers, so shouldn't fill them */
|
||||
return ResUNIMPL;
|
||||
|
|
@ -270,8 +270,7 @@ DEFINE_POOL_CLASS(NPoolClass, this)
|
|||
this->name = "N";
|
||||
this->size = sizeof(PoolNStruct);
|
||||
this->offset = offsetof(PoolNStruct, poolStruct);
|
||||
this->attr = AttrSCAN | AttrALLOC | AttrFREE | AttrBUF |
|
||||
AttrBUF_RESERVE | AttrGC;
|
||||
this->attr |= (AttrALLOC | AttrBUF | AttrFREE | AttrGC | AttrSCAN);
|
||||
this->init = NInit;
|
||||
this->finish = NFinish;
|
||||
this->alloc = NAlloc;
|
||||
|
|
@ -287,6 +286,7 @@ DEFINE_POOL_CLASS(NPoolClass, this)
|
|||
this->reclaim = NReclaim;
|
||||
this->traceEnd = NTraceEnd;
|
||||
this->describe = NDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -313,7 +313,7 @@ Bool PoolNCheck(PoolN poolN)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolsnc.c: STACK NO CHECKING POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -90,9 +90,9 @@ static Bool SNCBufCheck(SNCBuf sncbuf)
|
|||
|
||||
CHECKS(SNCBuf, sncbuf);
|
||||
segbuf = &sncbuf->segBufStruct;
|
||||
CHECKL(SegBufCheck(segbuf));
|
||||
CHECKD(SegBuf, segbuf);
|
||||
if (sncbuf->topseg != NULL) {
|
||||
CHECKL(SegCheck(sncbuf->topseg));
|
||||
CHECKD(Seg, sncbuf->topseg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -185,6 +185,7 @@ DEFINE_BUFFER_CLASS(SNCBufClass, class)
|
|||
class->size = sizeof(SNCBufStruct);
|
||||
class->init = SNCBufInit;
|
||||
class->finish = SNCBufFinish;
|
||||
AVERT(BufferClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -216,7 +217,7 @@ typedef struct SNCSegStruct {
|
|||
static Bool SNCSegCheck(SNCSeg sncseg)
|
||||
{
|
||||
CHECKS(SNCSeg, sncseg);
|
||||
CHECKL(GCSegCheck(&sncseg->gcSegStruct));
|
||||
CHECKD(GCSeg, &sncseg->gcSegStruct);
|
||||
if (NULL != sncseg->next) {
|
||||
CHECKS(SNCSeg, sncseg->next);
|
||||
}
|
||||
|
|
@ -237,7 +238,7 @@ static Res sncSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
sncseg = SegSNCSeg(seg);
|
||||
AVERT(Pool, pool);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(SNCSegClass);
|
||||
|
|
@ -261,6 +262,7 @@ DEFINE_SEG_CLASS(SNCSegClass, class)
|
|||
class->name = "SNCSEG";
|
||||
class->size = sizeof(SNCSegStruct);
|
||||
class->init = sncSegInit;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -365,7 +367,7 @@ static void SNCVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
args[0].key = MPS_KEY_FORMAT;
|
||||
args[0].val.format = va_arg(varargs, Format);
|
||||
args[1].key = MPS_KEY_ARGS_END;
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -431,7 +433,7 @@ static Res SNCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
AVER(BufferIsReset(buffer));
|
||||
|
||||
snc = Pool2SNC(pool);
|
||||
|
|
@ -682,6 +684,7 @@ DEFINE_POOL_CLASS(SNCPoolClass, this)
|
|||
this->framePopPending = SNCFramePopPending;
|
||||
this->walk = SNCWalk;
|
||||
this->bufferClass = SNCBufClassGet;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -699,7 +702,7 @@ static Bool SNCCheck(SNC snc)
|
|||
CHECKD(Pool, &snc->poolStruct);
|
||||
CHECKL(snc->poolStruct.class == SNCPoolClassGet());
|
||||
if (snc->freeSegs != NULL) {
|
||||
CHECKL(SegCheck(snc->freeSegs));
|
||||
CHECKD(Seg, snc->freeSegs);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -707,7 +710,7 @@ static Bool SNCCheck(SNC snc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci3li.c: PROTECTION MUTATOR CONTEXT INTEL 386 (LINUX)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
|
|
@ -57,9 +57,10 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
case 5: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBP]);
|
||||
case 6: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESI]);
|
||||
case 7: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDI]);
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* PURPOSE
|
||||
*
|
||||
|
|
@ -46,9 +46,10 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
|
|||
case 5: return (MRef)&wincont->Ebp;
|
||||
case 6: return (MRef)&wincont->Esi;
|
||||
case 7: return (MRef)&wincont->Edi;
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* suppress warning */
|
||||
}
|
||||
NOTREACHED;
|
||||
return NULL; /* suppress warning */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -80,7 +81,7 @@ void Prmci3StepOverIns(MutatorFaultContext context, Size inslen)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci3xc.c: PROTECTION MUTATOR CONTEXT INTEL 386 (MAC OS X)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
|
|
@ -55,9 +55,10 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
case 5: return (MRef)((char *)&mfc->threadState->__ebp);
|
||||
case 6: return (MRef)((char *)&mfc->threadState->__esi);
|
||||
case 7: return (MRef)((char *)&mfc->threadState->__edi);
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -104,7 +105,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (LINUX)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
|
|
@ -61,9 +61,10 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
case 13: return &gregs[REG_R13];
|
||||
case 14: return &gregs[REG_R14];
|
||||
case 15: return &gregs[REG_R15];
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -111,7 +112,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* PURPOSE
|
||||
*
|
||||
|
|
@ -52,9 +52,10 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
|
|||
case 13: return (MRef)&wincont->R13;
|
||||
case 14: return (MRef)&wincont->R14;
|
||||
case 15: return (MRef)&wincont->R15;
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* suppress warning */
|
||||
}
|
||||
NOTREACHED;
|
||||
return NULL; /* suppress warning */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -86,7 +87,7 @@ void Prmci6StepOverIns(MutatorFaultContext context, Size inslen)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci6xc.c: PROTECTION MUTATOR CONTEXT x64 (MAC OS X)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
|
|
@ -58,9 +58,10 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
case 13: return (MRef)((char *)&mfc->threadState->__r13);
|
||||
case 14: return (MRef)((char *)&mfc->threadState->__r14);
|
||||
case 15: return (MRef)((char *)&mfc->threadState->__r15);
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* pool.c: PROTOCOL IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -18,7 +18,7 @@ SRCID(protocol, "$Id$");
|
|||
Bool ProtocolClassCheck(ProtocolClass class)
|
||||
{
|
||||
CHECKS(ProtocolClass, class);
|
||||
CHECKS(ProtocolClass, class->superclass);
|
||||
CHECKU(ProtocolClass, class->superclass);
|
||||
CHECKL(FUNCHECK(class->coerceInst));
|
||||
CHECKL(FUNCHECK(class->coerceClass));
|
||||
return TRUE;
|
||||
|
|
@ -30,7 +30,7 @@ Bool ProtocolClassCheck(ProtocolClass class)
|
|||
Bool ProtocolInstCheck(ProtocolInst inst)
|
||||
{
|
||||
CHECKS(ProtocolInst, inst);
|
||||
CHECKL(ProtocolClassCheck(inst->class));
|
||||
CHECKD(ProtocolClass, inst->class);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +118,7 @@ DEFINE_CLASS(ProtocolClass, theClass)
|
|||
theClass->superclass = theClass;
|
||||
theClass->coerceInst = ProtocolCoerceInst;
|
||||
theClass->coerceClass = ProtocolCoerceClass;
|
||||
AVERT(ProtocolClass, theClass);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ DEFINE_CLASS(ProtocolClass, theClass)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* pthreadext.c: POSIX THREAD EXTENSIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: Provides extension to Pthreads.
|
||||
*
|
||||
|
|
@ -178,8 +178,8 @@ extern Bool PThreadextCheck(PThreadext pthreadext)
|
|||
|
||||
CHECKS(PThreadext, pthreadext);
|
||||
/* can't check ID */
|
||||
CHECKL(RingCheck(&pthreadext->threadRing));
|
||||
CHECKL(RingCheck(&pthreadext->idRing));
|
||||
CHECKD_NOSIG(Ring, &pthreadext->threadRing);
|
||||
CHECKD_NOSIG(Ring, &pthreadext->idRing);
|
||||
if (pthreadext->suspendedMFC == NULL) {
|
||||
/* not suspended */
|
||||
CHECKL(RingIsSingle(&pthreadext->threadRing));
|
||||
|
|
@ -366,7 +366,7 @@ unlock:
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -334,7 +334,6 @@ static void *go(void *p, size_t s)
|
|||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_addr_t base;
|
||||
mps_addr_t *addr;
|
||||
|
||||
testlib_unused(p);
|
||||
testlib_unused(s);
|
||||
|
|
@ -357,9 +356,7 @@ static void *go(void *p, size_t s)
|
|||
"RootCreateTable");
|
||||
|
||||
base = &activationStack;
|
||||
addr = base;
|
||||
die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0,
|
||||
addr, sizeof(QSCell)/sizeof(mps_addr_t)),
|
||||
die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0, base, 1),
|
||||
"RootCreateTable");
|
||||
|
||||
/* makes a random list */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* reserv.c: ARENA RESERVOIR
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* IMPROVEMENTS
|
||||
*
|
||||
|
|
@ -74,6 +74,7 @@ DEFINE_POOL_CLASS(ReservoirPoolClass, this)
|
|||
this->offset = offsetof(ReservoirStruct, poolStruct);
|
||||
this->init = ResPoolInit;
|
||||
this->finish = ResPoolFinish;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -94,7 +95,7 @@ Bool ReservoirCheck(Reservoir reservoir)
|
|||
/* could call ReservoirIsConsistent, but it's costly. */
|
||||
tract = reservoir->reserve;
|
||||
if (tract != NULL) {
|
||||
CHECKL(TractCheck(tract));
|
||||
CHECKD_NOSIG(Tract, tract);
|
||||
CHECKL(TractPool(tract) == ReservoirPool(reservoir));
|
||||
}
|
||||
CHECKL(SizeIsAligned(reservoir->reservoirLimit, ArenaAlign(arena)));
|
||||
|
|
@ -281,7 +282,7 @@ Bool ReservoirDeposit(Reservoir reservoir, Addr *baseIO, Size *sizeIO)
|
|||
|
||||
/* put as many pages as necessary into the reserve & free the rest */
|
||||
TRACT_FOR(tract, addr, arena, base, limit) {
|
||||
AVER(TractCheck(tract));
|
||||
AVERT(Tract, tract);
|
||||
if (reservoir->reservoirSize < reslimit) {
|
||||
/* Reassign the tract to the reservoir pool */
|
||||
TractFinish(tract);
|
||||
|
|
@ -416,7 +417,7 @@ void ReservoirFinish (Reservoir reservoir)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* root.c: ROOT IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is the implementation of the root datatype.
|
||||
*
|
||||
|
|
@ -98,7 +98,7 @@ Bool RootCheck(Root root)
|
|||
CHECKS(Root, root);
|
||||
CHECKU(Arena, root->arena);
|
||||
CHECKL(root->serial < ArenaGlobals(root->arena)->rootSerial);
|
||||
CHECKL(RingCheck(&root->arenaRing));
|
||||
CHECKD_NOSIG(Ring, &root->arenaRing);
|
||||
CHECKL(RankCheck(root->rank));
|
||||
CHECKL(TraceSetCheck(root->grey));
|
||||
/* Don't need to check var here, because of the switch below */
|
||||
|
|
@ -121,7 +121,7 @@ Bool RootCheck(Root root)
|
|||
|
||||
case RootREG:
|
||||
CHECKL(root->the.reg.scan != NULL);
|
||||
CHECKL(ThreadCheck(root->the.reg.thread));
|
||||
CHECKD_NOSIG(Thread, root->the.reg.thread); /* <design/check/#hidden-type> */
|
||||
break;
|
||||
|
||||
case RootFMT:
|
||||
|
|
@ -261,7 +261,7 @@ Res RootCreateTable(Root *rootReturn, Arena arena,
|
|||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
AVER(base != 0);
|
||||
AVER(base < limit);
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ Res RootCreateTableMasked(Root *rootReturn, Arena arena,
|
|||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
AVER(base != 0);
|
||||
AVER(base < limit);
|
||||
/* Can't check anything about mask. */
|
||||
|
|
@ -302,7 +302,7 @@ Res RootCreateReg(Root *rootReturn, Arena arena,
|
|||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
AVERT(Thread, thread);
|
||||
AVER(scan != NULL);
|
||||
|
||||
|
|
@ -322,7 +322,7 @@ Res RootCreateFmt(Root *rootReturn, Arena arena,
|
|||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
AVER(FUNCHECK(scan));
|
||||
AVER(base != 0);
|
||||
AVER(base < limit);
|
||||
|
|
@ -342,7 +342,7 @@ Res RootCreateFun(Root *rootReturn, Arena arena, Rank rank,
|
|||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
AVER(FUNCHECK(scan));
|
||||
|
||||
theUnion.fun.scan = scan;
|
||||
|
|
@ -671,7 +671,7 @@ Res RootsDescribe(Globals arenaGlobals, mps_lib_FILE *stream)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -48,13 +48,11 @@ Bool SparseArrayCheck(SparseArray sa)
|
|||
CHECKS(SparseArray, sa);
|
||||
CHECKL(sa->base != NULL);
|
||||
CHECKL(sa->elementSize >= 1);
|
||||
/* TODO: CHECKD(VM, sa->vm); once VMStruct becomes visible */
|
||||
CHECKL(VMCheck(sa->vm));
|
||||
CHECKD_NOSIG(VM, sa->vm); /* <design/check/#hidden-type> */
|
||||
CHECKL(sa->elementSize <= VMAlign(sa->vm));
|
||||
CHECKL(sa->length > 0);
|
||||
/* TODO: Make BTCheck extern and use everywhere. */
|
||||
/* CHECKL(BTCheck(sa->mapped)); */
|
||||
/* CHECKL(BTCheck(sa->pages)); */
|
||||
CHECKD_NOSIG(BT, sa->mapped);
|
||||
CHECKD_NOSIG(BT, sa->pages);
|
||||
CHECKL(sa->shift == SizeLog2(VMAlign(sa->vm)));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* sac.c: SEGREGATED ALLOCATION CACHES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
@ -249,7 +249,7 @@ Res SACFill(Addr *p_o, SAC sac, Size size, Bool hasReservoirPermit)
|
|||
AVER(p_o != NULL);
|
||||
AVERT(SAC, sac);
|
||||
AVER(size != 0);
|
||||
AVER(BoolCheck(hasReservoirPermit));
|
||||
AVERT(Bool, hasReservoirPermit);
|
||||
esac = ExternalSACOfSAC(sac);
|
||||
|
||||
sacFind(&i, &blockSize, sac, size);
|
||||
|
|
@ -384,7 +384,7 @@ void SACFlush(SAC sac)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -94,26 +94,26 @@ static mps_res_t stress(mps_class_t class,
|
|||
/* upper half, as when allocating them again we want smaller objects */
|
||||
/* see randomSize() */
|
||||
switch (k % 2) {
|
||||
case 0: {
|
||||
case 0:
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i)
|
||||
MPS_SAC_FREE(sac, (mps_addr_t)ps[i], ss[i]);
|
||||
} break;
|
||||
case 1: {
|
||||
break;
|
||||
default:
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i)
|
||||
mps_sac_free(sac, (mps_addr_t)ps[i], ss[i]);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
ss[i] = (*size)(i);
|
||||
switch (k % 2) {
|
||||
case 0: {
|
||||
case 0:
|
||||
res = make((mps_addr_t *)&ps[i], sac, ss[i]);
|
||||
} break;
|
||||
case 1: {
|
||||
break;
|
||||
default:
|
||||
res = mps_sac_alloc((mps_addr_t *)&ps[i], sac, ss[i], FALSE);
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (res != MPS_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +185,6 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_DONE(args);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* seg.c: SEGMENTS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: The design for this module is <design/seg/>.
|
||||
*
|
||||
|
|
@ -68,7 +68,7 @@ Res SegAlloc(Seg *segReturn, SegClass class, SegPref pref,
|
|||
AVERT(SegPref, pref);
|
||||
AVER(size > (Size)0);
|
||||
AVERT(Pool, pool);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
AVERT(Arena, arena);
|
||||
|
|
@ -152,7 +152,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVER(SizeIsAligned(size, align));
|
||||
class = seg->class;
|
||||
AVERT(SegClass, class);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
limit = AddrAdd(base, size);
|
||||
seg->limit = limit;
|
||||
|
|
@ -168,7 +168,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
seg->sig = SegSig; /* set sig now so tract checks will see it */
|
||||
|
||||
TRACT_FOR(tract, addr, arena, base, limit) {
|
||||
AVER(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
AVERT(Tract, tract);
|
||||
AVER(TractP(tract) == NULL);
|
||||
AVER(!TractHasSeg(tract));
|
||||
AVER(TractPool(tract) == pool);
|
||||
|
|
@ -196,7 +196,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
failInit:
|
||||
RingFinish(SegPoolRing(seg));
|
||||
TRACT_FOR(tract, addr, arena, base, limit) {
|
||||
AVER(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
AVERT(Tract, tract);
|
||||
TRACT_UNSET_SEG(tract);
|
||||
}
|
||||
seg->sig = SigInvalid;
|
||||
|
|
@ -233,7 +233,7 @@ static void SegFinish(Seg seg)
|
|||
limit = SegLimit(seg);
|
||||
|
||||
TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) {
|
||||
AVER(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
AVERT(Tract, tract);
|
||||
TractSetWhite(tract, TraceSetEMPTY);
|
||||
TRACT_UNSET_SEG(tract);
|
||||
}
|
||||
|
|
@ -263,7 +263,7 @@ static void SegFinish(Seg seg)
|
|||
void SegSetGrey(Seg seg, TraceSet grey)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(TraceSetCheck(grey));
|
||||
AVERT(TraceSet, grey);
|
||||
AVER(grey == TraceSetEMPTY || SegRankSet(seg) != RankSetEMPTY);
|
||||
|
||||
/* Don't dispatch to the class method if there's no actual change in
|
||||
|
|
@ -281,7 +281,7 @@ void SegSetGrey(Seg seg, TraceSet grey)
|
|||
void SegSetWhite(Seg seg, TraceSet white)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(TraceSetCheck(white));
|
||||
AVERT(TraceSet, white);
|
||||
seg->class->setWhite(seg, white);
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ void SegSetWhite(Seg seg, TraceSet white)
|
|||
void SegSetRankSet(Seg seg, RankSet rankSet)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
AVER(rankSet != RankSetEMPTY || SegSummary(seg) == RefSetEMPTY);
|
||||
seg->class->setRankSet(seg, rankSet);
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ void SegSetSummary(Seg seg, RefSet summary)
|
|||
void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
|
||||
#ifdef PROTECTION_NONE
|
||||
if (rankSet != RankSetEMPTY) {
|
||||
|
|
@ -582,7 +582,7 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi,
|
|||
mid = SegLimit(segLo);
|
||||
limit = SegLimit(segHi);
|
||||
AVER(SegBase(segHi) == SegLimit(segLo));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
arena = PoolArena(SegPool(segLo));
|
||||
|
||||
ShieldFlush(arena); /* see <design/seg/#split-merge.shield> */
|
||||
|
|
@ -634,7 +634,7 @@ Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at,
|
|||
AVER(AddrIsAligned(at, arena->alignment));
|
||||
AVER(at > base);
|
||||
AVER(at < limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
ShieldFlush(arena); /* see <design/seg/#split-merge.shield> */
|
||||
|
||||
|
|
@ -690,7 +690,7 @@ Bool SegCheck(Seg seg)
|
|||
/* can't assume nailed is subset of white - mightn't be during whiten */
|
||||
/* CHECKL(TraceSetSub(seg->nailed, seg->white)); */
|
||||
CHECKL(TraceSetCheck(seg->grey));
|
||||
CHECKL(TractCheck(seg->firstTract)); /* <design/check/#type.no-sig> */
|
||||
CHECKD_NOSIG(Tract, seg->firstTract);
|
||||
pool = SegPool(seg);
|
||||
CHECKU(Pool, pool);
|
||||
arena = PoolArena(pool);
|
||||
|
|
@ -704,7 +704,7 @@ Bool SegCheck(Seg seg)
|
|||
TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) {
|
||||
Seg trseg = NULL; /* suppress compiler warning */
|
||||
|
||||
CHECKL(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
CHECKD_NOSIG(Tract, tract);
|
||||
CHECKL(TRACT_SEG(&trseg, tract) && (trseg == seg));
|
||||
CHECKL(TractWhite(tract) == seg->white);
|
||||
CHECKL(TractPool(tract) == pool);
|
||||
|
|
@ -716,7 +716,7 @@ Bool SegCheck(Seg seg)
|
|||
/* the segment is initialized.) */
|
||||
/* CHECKL(RingNext(&seg->poolRing) != &seg->poolRing); */
|
||||
|
||||
CHECKL(RingCheck(&seg->poolRing));
|
||||
CHECKD_NOSIG(Ring, &seg->poolRing);
|
||||
|
||||
/* "pm", "sm", and "depth" not checked. See .check.shield. */
|
||||
CHECKL(RankSetCheck(seg->rankSet));
|
||||
|
|
@ -727,6 +727,8 @@ Bool SegCheck(Seg seg)
|
|||
CHECKL(seg->sm == AccessSetEMPTY);
|
||||
CHECKL(seg->pm == AccessSetEMPTY);
|
||||
} else {
|
||||
/* Segments with ranks may only belong to scannable pools. */
|
||||
CHECKL(PoolHasAttr(pool, AttrSCAN));
|
||||
/* <design/seg/#field.rankSet.single>: The Tracer only permits */
|
||||
/* one rank per segment [ref?] so this field is either empty or a */
|
||||
/* singleton. */
|
||||
|
|
@ -760,8 +762,8 @@ static Res segTrivInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVER(SegBase(seg) == base);
|
||||
AVER(SegSize(seg) == size);
|
||||
AVER(SegPool(seg) == pool);
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVER(ArgListCheck(args));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
AVERT(ArgList, args);
|
||||
UNUSED(args);
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -781,7 +783,7 @@ static void segTrivFinish(Seg seg)
|
|||
static void segNoSetGrey(Seg seg, TraceSet grey)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(TraceSetCheck(grey));
|
||||
AVERT(TraceSet, grey);
|
||||
AVER(seg->rankSet != RankSetEMPTY);
|
||||
NOTREACHED;
|
||||
}
|
||||
|
|
@ -792,7 +794,7 @@ static void segNoSetGrey(Seg seg, TraceSet grey)
|
|||
static void segNoSetWhite(Seg seg, TraceSet white)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(TraceSetCheck(white));
|
||||
AVERT(TraceSet, white);
|
||||
NOTREACHED;
|
||||
}
|
||||
|
||||
|
|
@ -802,7 +804,7 @@ static void segNoSetWhite(Seg seg, TraceSet white)
|
|||
static void segNoSetRankSet(Seg seg, RankSet rankSet)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
NOTREACHED;
|
||||
}
|
||||
|
||||
|
|
@ -822,7 +824,7 @@ static void segNoSetSummary(Seg seg, RefSet summary)
|
|||
static void segNoSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
UNUSED(summary);
|
||||
NOTREACHED;
|
||||
}
|
||||
|
|
@ -862,7 +864,7 @@ static Res segNoMerge(Seg seg, Seg segHi,
|
|||
AVER(SegLimit(seg) == mid);
|
||||
AVER(SegBase(segHi) == mid);
|
||||
AVER(SegLimit(segHi) == limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
NOTREACHED;
|
||||
return ResFAIL;
|
||||
}
|
||||
|
|
@ -898,7 +900,7 @@ static Res segTrivMerge(Seg seg, Seg segHi,
|
|||
AVER(SegLimit(seg) == mid);
|
||||
AVER(SegBase(segHi) == mid);
|
||||
AVER(SegLimit(segHi) == limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* .similar. */
|
||||
AVER(seg->rankSet == segHi->rankSet);
|
||||
|
|
@ -916,7 +918,7 @@ static Res segTrivMerge(Seg seg, Seg segHi,
|
|||
|
||||
seg->limit = limit;
|
||||
TRACT_FOR(tract, addr, arena, mid, limit) {
|
||||
AVER(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
AVERT(Tract, tract);
|
||||
AVER(TractHasSeg(tract));
|
||||
AVER(segHi == TractP(tract));
|
||||
AVER(TractPool(tract) == pool);
|
||||
|
|
@ -946,7 +948,7 @@ static Res segNoSplit(Seg seg, Seg segHi,
|
|||
AVER(mid < limit);
|
||||
AVER(SegBase(seg) == base);
|
||||
AVER(SegLimit(seg) == limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
NOTREACHED;
|
||||
return ResFAIL;
|
||||
|
||||
|
|
@ -977,7 +979,7 @@ static Res segTrivSplit(Seg seg, Seg segHi,
|
|||
AVER(mid < limit);
|
||||
AVER(SegBase(seg) == base);
|
||||
AVER(SegLimit(seg) == limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Segment may not be exposed, or in the shield cache */
|
||||
/* See <design/seg/#split-merge.shield> & <code/shield.c#def.depth> */
|
||||
|
|
@ -999,7 +1001,7 @@ static Res segTrivSplit(Seg seg, Seg segHi,
|
|||
RingInit(SegPoolRing(segHi));
|
||||
|
||||
TRACT_FOR(tract, addr, arena, mid, limit) {
|
||||
AVER(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
AVERT(Tract, tract);
|
||||
AVER(TractHasSeg(tract));
|
||||
AVER(seg == TractP(tract));
|
||||
AVER(TractPool(tract) == pool);
|
||||
|
|
@ -1090,7 +1092,7 @@ Bool GCSegCheck(GCSeg gcseg)
|
|||
Seg seg;
|
||||
CHECKS(GCSeg, gcseg);
|
||||
seg = &gcseg->segStruct;
|
||||
CHECKL(SegCheck(seg));
|
||||
CHECKD(Seg, seg);
|
||||
|
||||
if (gcseg->buffer != NULL) {
|
||||
CHECKU(Buffer, gcseg->buffer);
|
||||
|
|
@ -1100,7 +1102,7 @@ Bool GCSegCheck(GCSeg gcseg)
|
|||
}
|
||||
|
||||
/* The segment should be on a grey ring if and only if it is grey. */
|
||||
CHECKL(RingCheck(&gcseg->greyRing));
|
||||
CHECKD_NOSIG(Ring, &gcseg->greyRing);
|
||||
CHECKL((seg->grey == TraceSetEMPTY) ==
|
||||
RingIsSingle(&gcseg->greyRing));
|
||||
|
||||
|
|
@ -1132,7 +1134,7 @@ static Res gcSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVER(SizeIsAligned(size, align));
|
||||
gcseg = SegGCSeg(seg);
|
||||
AVER(&gcseg->segStruct == seg);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(GCSegClass);
|
||||
|
|
@ -1309,7 +1311,7 @@ static void gcSegSetWhite(Seg seg, TraceSet white)
|
|||
TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) {
|
||||
Seg trseg = NULL; /* suppress compiler warning */
|
||||
|
||||
AVER_CRITICAL(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
AVERT_CRITICAL(Tract, tract);
|
||||
AVER_CRITICAL(TRACT_SEG(&trseg, tract) && (trseg == seg));
|
||||
TractSetWhite(tract, white);
|
||||
}
|
||||
|
|
@ -1497,7 +1499,7 @@ static Res gcSegMerge(Seg seg, Seg segHi,
|
|||
AVER(SegLimit(seg) == mid);
|
||||
AVER(SegBase(segHi) == mid);
|
||||
AVER(SegLimit(segHi) == limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
buf = gcsegHi->buffer; /* any buffer on segHi must be reassigned */
|
||||
AVER(buf == NULL || gcseg->buffer == NULL); /* See .buffer */
|
||||
|
|
@ -1563,7 +1565,7 @@ static Res gcSegSplit(Seg seg, Seg segHi,
|
|||
AVER(mid < limit);
|
||||
AVER(SegBase(seg) == base);
|
||||
AVER(SegLimit(seg) == limit);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
grey = SegGrey(seg);
|
||||
buf = gcseg->buffer; /* Look for buffer to reassign to segHi */
|
||||
|
|
@ -1646,7 +1648,7 @@ static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream)
|
|||
|
||||
Bool SegClassCheck(SegClass class)
|
||||
{
|
||||
CHECKL(ProtocolClassCheck(&class->protocol));
|
||||
CHECKD(ProtocolClass, &class->protocol);
|
||||
CHECKL(class->name != NULL); /* Should be <= 6 char C identifier */
|
||||
CHECKL(class->size >= sizeof(SegStruct));
|
||||
CHECKL(FUNCHECK(class->init));
|
||||
|
|
@ -1683,6 +1685,7 @@ DEFINE_CLASS(SegClass, class)
|
|||
class->split = segTrivSplit;
|
||||
class->describe = segTrivDescribe;
|
||||
class->sig = SegClassSig;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1707,6 +1710,7 @@ DEFINE_CLASS(GCSegClass, class)
|
|||
class->merge = gcSegMerge;
|
||||
class->split = gcSegSplit;
|
||||
class->describe = gcSegDescribe;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1726,7 +1730,7 @@ void SegClassMixInNoSplitMerge(SegClass class)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ typedef struct AMSTStruct *AMST;
|
|||
static Bool AMSTCheck(AMST amst)
|
||||
{
|
||||
CHECKS(AMST, amst);
|
||||
CHECKL(AMSCheck(AMST2AMS(amst)));
|
||||
CHECKD_NOSIG(AMS, AMST2AMS(amst)); /* <design/check/#hidden-type> */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ typedef struct AMSTSegStruct {
|
|||
static Bool AMSTSegCheck(AMSTSeg amstseg)
|
||||
{
|
||||
CHECKS(AMSTSeg, amstseg);
|
||||
CHECKL(AMSSegCheck(&amstseg->amsSegStruct));
|
||||
CHECKD_NOSIG(AMSSeg, &amstseg->amsSegStruct); /* <design/check/#hidden-type> */
|
||||
/* don't bother to do other checks - this is a stress test */
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ static Res amstSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
amst = Pool2AMST(pool);
|
||||
AVERT(AMST, amst);
|
||||
/* no useful checks for base and size */
|
||||
AVER(BoolCheck(reservoirPermit));
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(AMSTSegClass);
|
||||
|
|
@ -294,6 +294,7 @@ DEFINE_SEG_CLASS(AMSTSegClass, class)
|
|||
class->finish = amstSegFinish;
|
||||
class->split = amstSegSplit;
|
||||
class->merge = amstSegMerge;
|
||||
AVERT(SegClass, class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -310,7 +311,7 @@ static Res AMSTSegSizePolicy(Size *sizeReturn,
|
|||
AVER(sizeReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER(RankSetCheck(rankSet));
|
||||
AVERT(RankSet, rankSet);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
|
||||
|
|
@ -674,6 +675,7 @@ DEFINE_POOL_CLASS(AMSTPoolClass, this)
|
|||
this->init = AMSTInit;
|
||||
this->finish = AMSTFinish;
|
||||
this->bufferFill = AMSTBufferFill;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ Bool SplayTreeCheck(SplayTree splay)
|
|||
CHECKL(FUNCHECK(splay->compare));
|
||||
CHECKL(FUNCHECK(splay->nodeKey));
|
||||
CHECKL(FUNCHECK(splay->updateNode));
|
||||
/* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */
|
||||
CHECKL(TreeCheck(splay->root));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* than.c: ANSI THREADS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is a single-threaded implementation of the threads manager.
|
||||
* Has stubs for thread suspension.
|
||||
|
|
@ -30,7 +30,7 @@ Bool ThreadCheck(Thread thread)
|
|||
CHECKS(Thread, thread);
|
||||
CHECKU(Arena, thread->arena);
|
||||
CHECKL(thread->serial < thread->arena->threadSerial);
|
||||
CHECKL(RingCheck(&thread->arenaRing));
|
||||
CHECKD_NOSIG(Ring, &thread->arenaRing);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* thix.c: Threads Manager for Posix threads
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is a pthreads implementation of the threads manager.
|
||||
* This implements <code/th.h>.
|
||||
|
|
@ -61,7 +61,7 @@ Bool ThreadCheck(Thread thread)
|
|||
CHECKS(Thread, thread);
|
||||
CHECKU(Arena, thread->arena);
|
||||
CHECKL(thread->serial < thread->arena->threadSerial);
|
||||
CHECKL(RingCheck(&thread->arenaRing));
|
||||
CHECKD_NOSIG(Ring, &thread->arenaRing);
|
||||
CHECKD(PThreadext, &thread->thrextStruct);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -292,7 +292,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* thw3i3.c: WIN32 THREAD MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* Implements thread registration, suspension, and stack
|
||||
* scanning. See <design/thread-manager/>.
|
||||
|
|
@ -60,7 +60,7 @@ Bool ThreadCheck(Thread thread)
|
|||
CHECKS(Thread, thread);
|
||||
CHECKU(Arena, thread->arena);
|
||||
CHECKL(thread->serial < thread->arena->threadSerial);
|
||||
CHECKL(RingCheck(&thread->arenaRing));
|
||||
CHECKD_NOSIG(Ring, &thread->arenaRing);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* thxc.c: OS X MACH THREADS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: See <design/thread-manager/>.
|
||||
*
|
||||
|
|
@ -45,7 +45,7 @@ Bool ThreadCheck(Thread thread)
|
|||
CHECKS(Thread, thread);
|
||||
CHECKU(Arena, thread->arena);
|
||||
CHECKL(thread->serial < thread->arena->threadSerial);
|
||||
CHECKL(RingCheck(&thread->arenaRing));
|
||||
CHECKD_NOSIG(Ring, &thread->arenaRing);
|
||||
CHECKL(MACH_PORT_VALID(thread->port));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -267,7 +267,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -64,9 +64,9 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
|||
TraceId ti;
|
||||
Trace trace;
|
||||
|
||||
AVER(TraceSetCheck(ts));
|
||||
AVERT(TraceSet, ts);
|
||||
AVERT(Arena, arena);
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(Rank, rank);
|
||||
/* white is arbitrary and can't be checked */
|
||||
|
||||
/* NOTE: We can only currently support scanning for a set of traces with
|
||||
|
|
@ -363,7 +363,7 @@ Res TraceAddWhite(Trace trace, Seg seg)
|
|||
if(TraceSetIsMember(SegWhite(seg), trace)) {
|
||||
trace->white = ZoneSetUnion(trace->white, ZoneSetOfSeg(trace->arena, seg));
|
||||
/* if the pool is a moving GC, then condemned objects may move */
|
||||
if(pool->class->attr & AttrMOVINGGC) {
|
||||
if(PoolHasAttr(pool, AttrMOVINGGC)) {
|
||||
trace->mayMove = ZoneSetUnion(trace->mayMove,
|
||||
ZoneSetOfSeg(trace->arena, seg));
|
||||
}
|
||||
|
|
@ -410,8 +410,9 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet)
|
|||
/* the requested zone set. Otherwise, we would bloat the */
|
||||
/* foundation to no gain. Note that this doesn't exclude */
|
||||
/* any segments from which the condemned set was derived, */
|
||||
if((SegPool(seg)->class->attr & AttrGC) != 0
|
||||
&& ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg))) {
|
||||
if(PoolHasAttr(SegPool(seg), AttrGC)
|
||||
&& ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg)))
|
||||
{
|
||||
res = TraceAddWhite(trace, seg);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
|
@ -503,9 +504,9 @@ static Res rootFlip(Root root, void *p)
|
|||
|
||||
AVERT(Root, root);
|
||||
AVER(p != NULL);
|
||||
AVER(TraceSetCheck(rf->ts));
|
||||
AVERT(TraceSet, rf->ts);
|
||||
AVERT(Arena, rf->arena);
|
||||
AVER(RankCheck(rf->rank));
|
||||
AVERT(Rank, rf->rank);
|
||||
|
||||
AVER(RootRank(root) <= RankEXACT); /* see .root.rank */
|
||||
|
||||
|
|
@ -827,7 +828,7 @@ static void traceReclaim(Trace trace)
|
|||
AVER_CRITICAL(!TraceSetIsMember(SegGrey(seg), trace));
|
||||
|
||||
if(TraceSetIsMember(SegWhite(seg), trace)) {
|
||||
AVER_CRITICAL((pool->class->attr & AttrGC) != 0);
|
||||
AVER_CRITICAL(PoolHasAttr(pool, AttrGC));
|
||||
STATISTIC(++trace->reclaimCount);
|
||||
PoolReclaim(pool, trace, seg);
|
||||
|
||||
|
|
@ -988,7 +989,7 @@ static Bool traceFindGrey(Seg *segReturn, Rank *rankReturn,
|
|||
Ring node, nextNode;
|
||||
|
||||
AVER(segReturn != NULL);
|
||||
AVER(TraceIdCheck(ti));
|
||||
AVERT(TraceId, ti);
|
||||
|
||||
trace = ArenaTrace(arena, ti);
|
||||
|
||||
|
|
@ -1376,10 +1377,10 @@ void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
|
|||
{
|
||||
Res res;
|
||||
|
||||
AVER(TraceSetCheck(ts));
|
||||
AVER(RankCheck(rank));
|
||||
AVERT(TraceSet, ts);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(Arena, arena);
|
||||
AVER(SegCheck(seg));
|
||||
AVERT(Seg, seg);
|
||||
AVER(refIO != NULL);
|
||||
|
||||
res = traceScanSingleRefRes(ts, rank, arena, seg, refIO);
|
||||
|
|
@ -1617,9 +1618,6 @@ Res TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
/* This is indicated by the rankSet begin non-empty. Such */
|
||||
/* segments may only belong to scannable pools. */
|
||||
if(SegRankSet(seg) != RankSetEMPTY) {
|
||||
/* Segments with ranks may only belong to scannable pools. */
|
||||
AVER((SegPool(seg)->class->attr & AttrSCAN) != 0);
|
||||
|
||||
/* Turn the segment grey if there might be a reference in it */
|
||||
/* to the white set. This is done by seeing if the summary */
|
||||
/* of references in the segment intersects with the */
|
||||
|
|
@ -1634,8 +1632,9 @@ Res TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
}
|
||||
}
|
||||
|
||||
if((SegPool(seg)->class->attr & AttrGC)
|
||||
&& !TraceSetIsMember(SegWhite(seg), trace)) {
|
||||
if(PoolHasAttr(SegPool(seg), AttrGC)
|
||||
&& !TraceSetIsMember(SegWhite(seg), trace))
|
||||
{
|
||||
trace->notCondemned += size;
|
||||
}
|
||||
}
|
||||
|
|
@ -1730,7 +1729,6 @@ void TraceQuantum(Trace trace)
|
|||
|
||||
if(traceFindGrey(&seg, &rank, arena, trace->ti)) {
|
||||
Res res;
|
||||
AVER((SegPool(seg)->class->attr & AttrSCAN) != 0);
|
||||
res = traceScanSeg(TraceSetSingle(trace), rank, arena, seg);
|
||||
/* Allocation failures should be handled by emergency mode, and we
|
||||
don't expect any other error in a normal GC trace. */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* tract.c: PAGE TABLES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .ullagepages: Pages whose page index is < allocBase are recorded as
|
||||
* free but never allocated as alloc starts searching after the tables.
|
||||
|
|
@ -113,7 +113,7 @@ Bool ChunkCheck(Chunk chunk)
|
|||
CHECKS(Chunk, chunk);
|
||||
CHECKU(Arena, chunk->arena);
|
||||
CHECKL(chunk->serial < chunk->arena->chunkSerial);
|
||||
CHECKL(RingCheck(&chunk->chunkRing));
|
||||
CHECKD_NOSIG(Ring, &chunk->chunkRing);
|
||||
CHECKL(ChunkPagesToSize(chunk, 1) == ChunkPageSize(chunk));
|
||||
CHECKL(ShiftCheck(ChunkPageShift(chunk)));
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ Bool ChunkCheck(Chunk chunk)
|
|||
CHECKL(chunk->allocBase <= chunk->pages);
|
||||
CHECKL(chunk->allocBase >= chunk->pageTablePages);
|
||||
|
||||
CHECKL(chunk->allocTable != NULL);
|
||||
CHECKD_NOSIG(BT, chunk->allocTable);
|
||||
/* check that allocTable is in the chunk overhead */
|
||||
CHECKL((Addr)chunk->allocTable >= chunk->base);
|
||||
CHECKL(AddrAdd((Addr)chunk->allocTable, BTSize(chunk->pages))
|
||||
|
|
@ -671,7 +671,7 @@ void PageFree(Chunk chunk, Index pi)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* walk.c: OBJECT WALKER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
@ -77,7 +77,7 @@ static void ArenaFormattedObjectsWalk(Arena arena, FormattedObjectsStepMethod f,
|
|||
do {
|
||||
Pool pool;
|
||||
pool = SegPool(seg);
|
||||
if (pool->class->attr & AttrFMT) {
|
||||
if (PoolHasAttr(pool, AttrFMT)) {
|
||||
ShieldExpose(arena, seg);
|
||||
PoolWalk(pool, seg, f, p, s);
|
||||
ShieldCover(arena, seg);
|
||||
|
|
@ -171,7 +171,7 @@ static Bool rootsStepClosureCheck(rootsStepClosure rsc)
|
|||
CHECKL(FUNCHECK(rsc->f));
|
||||
/* p and s fields are arbitrary closures which cannot be checked */
|
||||
if (rsc->root != NULL) {
|
||||
CHECKL(RootCheck(rsc->root));
|
||||
CHECKD_NOSIG(Root, rsc->root); /* <design/check/#.hidden-type> */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -243,7 +243,7 @@ static Res RootsWalkFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
|
||||
/* If the segment isn't GCable then the ref is not to the heap and */
|
||||
/* shouldn't be passed to the client. */
|
||||
AVER((SegPool(seg)->class->attr & AttrGC) != 0);
|
||||
AVER(PoolHasAttr(SegPool(seg), AttrGC));
|
||||
|
||||
/* Call the client closure - .assume.rootaddr */
|
||||
rsc->f((mps_addr_t*)refIO, (mps_root_t)rsc->root, rsc->p, rsc->s);
|
||||
|
|
@ -307,7 +307,7 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
|
|||
/* NOTE: I'm not sure why this is. RB 2012-07-24 */
|
||||
if (SegFirst(&seg, arena)) {
|
||||
do {
|
||||
if ((SegPool(seg)->class->attr & AttrGC) != 0) {
|
||||
if (PoolHasAttr(SegPool(seg), AttrGC)) {
|
||||
res = TraceAddWhite(trace, seg);
|
||||
AVER(res == ResOK);
|
||||
}
|
||||
|
|
@ -363,7 +363,7 @@ void mps_arena_roots_walk(mps_arena_t mps_arena, mps_roots_stepper_t f,
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpscams.h"
|
||||
#include "mpscawl.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
|
|
@ -126,11 +128,16 @@ static void stepper(mps_addr_t object, mps_fmt_t format,
|
|||
return;
|
||||
}
|
||||
|
||||
static mps_addr_t test_awl_find_dependent(mps_addr_t addr)
|
||||
{
|
||||
testlib_unused(addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
static void *test(mps_arena_t arena, mps_class_t pool_class)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_chain_t chain;
|
||||
mps_fmt_t format;
|
||||
mps_pool_t pool;
|
||||
|
|
@ -139,14 +146,15 @@ static void *test(void *arg, size_t s)
|
|||
unsigned long objs;
|
||||
struct stepper_data sdStruct, *sd;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
|
||||
die(dylan_fmt(&format, arena), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
|
||||
die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain),
|
||||
"pool_create(amc)");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent);
|
||||
die(mps_pool_create_k(&pool, arena, pool_class, args), "pool_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create");
|
||||
|
||||
|
|
@ -199,7 +207,6 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
void *r;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
|
|
@ -207,7 +214,11 @@ int main(int argc, char *argv[])
|
|||
testArenaSIZE),
|
||||
"arena_create");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
|
||||
test(arena, mps_class_amc());
|
||||
test(arena, mps_class_awl());
|
||||
/* TODO: test(arena, mps_class_ams()); -- see job003738 */
|
||||
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
|
|||
|
|
@ -95,17 +95,30 @@ type structure pointer, possibly invoking ``<type>Check`` (depending
|
|||
on level; see `.level`_). It should be called with the child type
|
||||
and pointer.
|
||||
|
||||
_`.full-type`: ``CHECKS()``, ``CHECKD()``, ``CHECKU()``, all operate
|
||||
only on fully fledged types. This means the type has to provide a
|
||||
function ``Bool TypeCheck(Type type)`` where ``Type`` is substituted
|
||||
for the name of the type (for example, ``PoolCheck()``), and the
|
||||
expression ``obj->sig`` must be a valid value of type ``Sig`` whenever
|
||||
``obj`` is a valid value of type ``Type``.
|
||||
_`.full-type`: Use ``CHECKS()``, ``CHECKD()`` or ``CHECKU()`` on all
|
||||
types that satisfy these three requirements:
|
||||
|
||||
_`.type.no-sig`: This tag is to be referenced in implementations
|
||||
whenever the form ``CHECKL(ThingCheck(thing))`` is used instead of
|
||||
``CHECK{U,D}(Thing, thing)`` because ``Thing`` is not a fully fledged
|
||||
type (`.full-type`_).
|
||||
_`.full-type.pointer`: The type is a pointer type.
|
||||
|
||||
_`.full-type.check`: The type provides a function ``Bool TypeCheck(Type
|
||||
type)`` where ``Type`` is substituted for the name of the type (for
|
||||
example, ``PoolCheck()``).
|
||||
|
||||
_`.full-type.sig`: The expression ``obj->sig`` is a valid value of
|
||||
type ``Sig`` whenever ``obj`` is a valid value of type ``Type``.
|
||||
|
||||
_`.partial-type`: Where the type satisfies `.full-type.pointer`_ and
|
||||
`.full-type.check`_ but not `.full-type.sig`_ because the type lacks a
|
||||
signature in order to save space (this applies to small structures
|
||||
that are embedded many times in other structures, for example
|
||||
``Ring``), use ``CHECKD_NOSIG()``.
|
||||
|
||||
_`.hidden-type`: Where the type satisfies `.full-type.pointer`_ and
|
||||
`.full-type.check`_ but not `.full-type.sig`_ because the structure
|
||||
has a signature but the structure definition is not visible at point
|
||||
of checking (for example ``Root``), use ``CHECKD_NOSIG()`` and
|
||||
reference this tag. The structure could be considered for addition to
|
||||
``mpmst.h``.
|
||||
|
||||
|
||||
Document History
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ C interface design
|
|||
:Tag: design.mps.interface.c
|
||||
:Author: Richard Brooksby
|
||||
:Date: 1996-07-29
|
||||
:Status: incomplete document
|
||||
:Status: complete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See `Copyright and License`_.
|
||||
:Index terms: pair: C interface; design
|
||||
|
|
@ -29,7 +29,9 @@ Goals
|
|||
|
||||
_`.goal.c`: The file impl.h.mps is the C external interface to the
|
||||
MPS. It is the default interface between client code written in C and
|
||||
the MPS. _`.goal.cpp`: impl.h.mps is not specifically designed to be
|
||||
the MPS.
|
||||
|
||||
_`.goal.cpp`: impl.h.mps is not specifically designed to be
|
||||
an interface to C++, but should be usable from C++.
|
||||
|
||||
|
||||
|
|
@ -38,36 +40,32 @@ Requirements
|
|||
|
||||
_`.req`: The interface must provide an interface from client code
|
||||
written in C to the functionality of the MPS required by the product
|
||||
(see req.product), Dylan (req.dylan), and the Core RIP (req.epcore).
|
||||
(see req.product), and Open Dylan (req.dylan).
|
||||
|
||||
``mps.h`` may not include internal MPS header files (such as
|
||||
``pool.h``).
|
||||
_`.req.separation`: The external interface may not include internal
|
||||
MPS header files (such as ``pool.h``).
|
||||
|
||||
It is essential that the interface cope well with change, in order to
|
||||
avoid restricting possible future MPS developments. This means that
|
||||
the interface must be "open ended" in its definitions. This accounts
|
||||
for some of the apparently tortuous methods of doing things
|
||||
(``mps_fmt_A_t``, for example). The requirement is that the MPS should
|
||||
_`.req.flexibility`: It is essential that the interface cope well with
|
||||
change, in order to avoid restricting possible future MPS
|
||||
developments. This means that the interface must be "open ended" in
|
||||
its definitions. This accounts for some of the apparently tortuous
|
||||
methods of doing things (such as the keyword argument mechanism; see
|
||||
design.mps.keyword-arguments_). The requirement is that the MPS should
|
||||
be able to add new functionality, or alter the implementation of
|
||||
existing functionality, without affecting existing client code. A
|
||||
stronger requirement is that the MPS should be able to change without
|
||||
*recompiling* client code. This is not always possible.
|
||||
|
||||
.. note::
|
||||
.. _design.mps.keyword-arguments: keyword-arguments
|
||||
|
||||
`.naming.global` was presumably done in response to unwritten
|
||||
requirements regarding the use of the name spaces in C, perhaps
|
||||
these:
|
||||
_`.req.name.iso`: The interface shall not conflict in terms of
|
||||
naming with any interfaces specified by ISO C and all reasonable
|
||||
future versions.
|
||||
|
||||
- _`.req.name.iso`: The interface shall not conflict in terms of
|
||||
naming with any interfaces specified by ISO C and all reasonable
|
||||
future versions.
|
||||
|
||||
- _`.req.name.general`: The interface shall use a documented and
|
||||
reasonably small portion of the namespace so that clients can
|
||||
interoperate easily.
|
||||
|
||||
David Jones, 1998-10-01.
|
||||
_`.req.name.general`: The interface shall use a documented and
|
||||
reasonably small portion of the namespace so that clients can use the
|
||||
MPS C interface in combination with other interfaces without name
|
||||
conflicts.
|
||||
|
||||
|
||||
Architecture
|
||||
|
|
@ -82,13 +80,18 @@ layer" which does the job of converting types and checking parameters
|
|||
before calling through to the MPS proper, using internal MPS methods.
|
||||
|
||||
|
||||
General conventions
|
||||
-------------------
|
||||
Naming conventions
|
||||
------------------
|
||||
|
||||
_`.naming`: The external interface names should adhere to the
|
||||
documented interface conventions; these are found in
|
||||
doc.mps.ref-man.if-conv(0).naming. They are paraphrased/recreated
|
||||
here.
|
||||
documented interface conventions; these are found in the “`Interface
|
||||
conventions`_” chapter of the Reference Manual. They are
|
||||
paraphrased/recreated here.
|
||||
|
||||
.. _Interface conventions: ../topic/interface.html
|
||||
|
||||
_`.naming.file`: All files in the external interface have names
|
||||
starting with ``mps``.
|
||||
|
||||
_`.naming.unixy`: The external interface does not follow the same
|
||||
naming conventions as the internal code. The interface is designed to
|
||||
|
|
@ -97,13 +100,13 @@ resemble a more conventional C, Unix, or Posix naming convention.
|
|||
_`.naming.case`: Identifiers are in lower case, except
|
||||
non-function-like macros, which are in upper case.
|
||||
|
||||
_`.naming.global`: All publicised identifiers are
|
||||
prefixed ``mps_`` or ``MPS_``.
|
||||
_`.naming.global`: All documented identifiers begin ``mps_`` or
|
||||
``MPS_``.
|
||||
|
||||
_`.naming.all`: All identifiers defined by the MPS
|
||||
should begin ``mps_`` or ``MPS_`` or ``_mps_``.
|
||||
_`.naming.all`: All identifiers defined by the MPS begin ``mps_`` or
|
||||
``MPS_`` or ``_mps_``.
|
||||
|
||||
_`.naming.type`: Types are suffixed ``_t``.
|
||||
_`.naming.type`: Types are suffixed ``_t``, except for structure and union types.
|
||||
|
||||
_`.naming.struct`: Structure types and tags are suffixed ``_s``.
|
||||
|
||||
|
|
@ -117,15 +120,14 @@ structure and union members, macros, macro parameters, labels.
|
|||
_`.naming.scope.labels`: labels (for ``goto`` statements) should be
|
||||
rare, only in special block macros and probably not even then.
|
||||
|
||||
.. note::
|
||||
|
||||
This principle is not adhered to in the source code, which uses
|
||||
``goto`` for handling error cases. Gareth Rees, 2013-05-27.
|
||||
|
||||
_`.naming.scope.other`: The naming convention would also extend to
|
||||
enumeration types and parameters in functions prototypes but both of
|
||||
those are prohibited from having names in an interface file.
|
||||
|
||||
|
||||
Type conventions
|
||||
----------------
|
||||
|
||||
_`.type.gen`: The interface defines memory addresses as ``void *`` and
|
||||
sizes as ``size_t`` for compatibility with standard C (in particular,
|
||||
with ``malloc()``). These types must be binary compatible with the
|
||||
|
|
@ -139,13 +141,13 @@ which are never defined. These types are cast to the corresponding
|
|||
internal types in ``mpsi.c``.
|
||||
|
||||
_`.type.trans`: Some transparent structures are defined. The client is
|
||||
expected to read these, or poke about in them, under restrictions
|
||||
which should be documented. The most important is probably the
|
||||
allocation point (``mps_ap_s``) which is part of allocation buffers.
|
||||
The transparent structures must be binary compatible with
|
||||
corresponding internal structures. For example, the fields of
|
||||
``mps_ap_s`` must correspond with ``APStruct`` internally. This is
|
||||
checked by ``mpsi.c`` in ``mps_check()``.
|
||||
expected to read these, or poke about in them, under documented
|
||||
restrictions. The most important is the allocation point structure
|
||||
(``mps_ap_s``) which is part of allocation buffers. The transparent
|
||||
structures must be binary compatible with corresponding internal
|
||||
structures. For example, the fields of ``mps_ap_s`` must correspond
|
||||
with ``APStruct`` internally. This is checked by ``mpsi.c`` in
|
||||
``mps_check()``.
|
||||
|
||||
_`.type.pseudo`: Some pseudo-opaque structures are defined. These only
|
||||
exist so that code can be inlined using macros. The client code
|
||||
|
|
@ -153,9 +155,9 @@ shouldn't mess with them. The most important case of this is the scan
|
|||
state (``mps_ss_s``) which is accessed by the in-line scanning macros,
|
||||
``MPS_SCAN_*`` and ``MPS_FIX*``.
|
||||
|
||||
_`.type.enum`: There should be no enumeration types in the interface.
|
||||
Note that enum specifiers (to declare integer constants) are fine as
|
||||
long as no type is declared. See guide.impl.c.misc.enum.type.
|
||||
_`.type.enum`: There are no enumeration types in the interface. Note
|
||||
that enum specifiers (to declare integer constants) are fine as long
|
||||
as no type is declared. See guide.impl.c.misc.enum.type.
|
||||
|
||||
_`.type.fun`: Whenever function types or derived function types (such
|
||||
as pointer to function) are declared a prototype should be used and
|
||||
|
|
@ -184,39 +186,32 @@ See guide.impl.c.misc.prototype.parameters.
|
|||
Checking
|
||||
--------
|
||||
|
||||
_`.check.space`: When the arena needs to be recovered from a parameter
|
||||
it is check using ``AVERT(Foo, foo)`` before any attempt to call
|
||||
``FooArena(foo)``. The macro ``AVERT()`` in impl.h.assert performs
|
||||
simple thread-safe checking of ``foo``, so it can be called outside of
|
||||
``ArenaEnter()`` and ``ArenaLeave()``.
|
||||
_`.check.avert`: Before any use of a function paramater ``FOO *foo``
|
||||
it is checked using ``AVERT(Foo, foo)``. The macro ``AVERT()`` in
|
||||
impl.h.check performs simple thread-safe checking of ``foo``, so it
|
||||
can be called outside of ``ArenaEnter()`` and ``ArenaLeave()``.
|
||||
|
||||
_`.check.types`: We use definitions of types in both our external
|
||||
interface and our internal code, and we want to make sure that they
|
||||
are compatible. (The external interface changes less often and hides
|
||||
more information.) At first, we were just checking their sizes, which
|
||||
wasn't very good, but I've come up with some macros which check the
|
||||
assignment compatibility of the types too. This is a sufficiently
|
||||
useful trick that I thought I'd send it round. It may be useful in
|
||||
other places where types and structures need to be checked for
|
||||
compatibility at compile time.
|
||||
|
||||
These macros don't generate warnings on the compilers I've tried.
|
||||
more information.) This checking uses the following macros.
|
||||
|
||||
``COMPATLVALUE(lvalue1, lvalue2)``
|
||||
|
||||
This macro checks the assignment compatibility of two lvalues. It uses
|
||||
``sizeof()`` to ensure that the assignments have no effect. ::
|
||||
_`.check.types.compat.lvalue`: This macro checks the assignment
|
||||
compatibility of two lvalues. It uses ``sizeof()`` to ensure that the
|
||||
assignments have no effect. ::
|
||||
|
||||
#define COMPATLVALUE(lv1, lv2) \
|
||||
((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE)
|
||||
|
||||
``COMPATTYPE(type1, type2)``
|
||||
|
||||
This macro checks that two types are assignment-compatible and equal
|
||||
in size. The hack here is that it generates an lvalue for each type by
|
||||
casting zero to a pointer to the type. The use of ``sizeof()`` avoids
|
||||
the undefined behaviour that would otherwise result from dereferencing
|
||||
a null pointer. ::
|
||||
_`.check.types.compat.type`: This macro checks that two types are
|
||||
assignment-compatible and equal in size. The hack here is that it
|
||||
generates an lvalue for each type by casting zero to a pointer to the
|
||||
type. The use of ``sizeof()`` avoids the undefined behaviour that
|
||||
would otherwise result from dereferencing a null pointer. ::
|
||||
|
||||
#define COMPATTYPE(t1, t2) \
|
||||
(sizeof(t1) == sizeof(t2) && \
|
||||
|
|
@ -224,8 +219,8 @@ a null pointer. ::
|
|||
|
||||
``COMPATFIELDAPPROX(structure1, field1, structure2, field2)``
|
||||
|
||||
This macro checks that the offset and size of two fields in two
|
||||
structure types are the same. ::
|
||||
_`.check.types.compat.field.approx`: This macro checks that the offset
|
||||
and size of two fields in two structure types are the same. ::
|
||||
|
||||
#define COMPATFIELDAPPROX(s1, f1, s2, f2) \
|
||||
(sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \
|
||||
|
|
@ -233,8 +228,8 @@ structure types are the same. ::
|
|||
|
||||
``COMPATFIELD(structure1, field1, structure2, field2)``
|
||||
|
||||
This macro checks the offset, size, and assignment-compatibility of
|
||||
two fields in two structure types. ::
|
||||
_`.check.types.compat.field`: This macro checks the offset, size, and
|
||||
assignment-compatibility of two fields in two structure types. ::
|
||||
|
||||
#define COMPATFIELD(s1, f1, s2, f2) \
|
||||
(COMPATFIELDAPPROX(s1, f1, s2, f2) && \
|
||||
|
|
@ -247,21 +242,34 @@ Binary compatibility issues
|
|||
As in, "Enumeration types are not allowed" (see
|
||||
mail.richard.1995-09-08.09-28).
|
||||
|
||||
There are two main aspects to run-time compatibility: binary interface
|
||||
and protocol. The binary interface is all the information needed to
|
||||
correctly use the library, and includes external symbol linkage,
|
||||
_`.compat`: There are two main aspects to run-time compatibility:
|
||||
binary interface and protocol.
|
||||
|
||||
_`.compat.binary`: The binary interface is all the information needed
|
||||
to correctly use the library, and includes external symbol linkage,
|
||||
calling conventions, type representation compatibility, structure
|
||||
layouts, etc. The protocol is how the library is actually used by the
|
||||
client code -- whether this is called before that -- and determines
|
||||
the semantic correctness of the client with respect to the library.
|
||||
layouts, etc.
|
||||
|
||||
The binary interface is determined completely by the header file and
|
||||
the target. The header file specifies the external names and the
|
||||
types, and the target platform specifies calling conventions and type
|
||||
representation. There is therefore a many-to-one mapping between the
|
||||
header file version and the binary interface.
|
||||
_`.compat.binary.unneeded`: Binary compatibility is not required by
|
||||
the open source MPS: we expect (and indeed, recommend) that a client
|
||||
program is compiled against the MPS sources. Nonetheless we try to
|
||||
maintain binary compatibility in case the capability is required in
|
||||
future.
|
||||
|
||||
The protocol is determined by the implementation of the library.
|
||||
_`.compat.binary.dependencies`: The binary interface is determined
|
||||
completely by the header file and the target. The header file
|
||||
specifies the external names and the types, and the target platform
|
||||
specifies calling conventions and type representation. There is
|
||||
therefore a many-to-one mapping between the header file version and
|
||||
the binary interface.
|
||||
|
||||
_`.compat.protocol`: The protocol is how the library is actually used
|
||||
by the client code -- whether this is called before that -- and
|
||||
determines the semantic correctness of the client with respect to the
|
||||
library.
|
||||
|
||||
_`.compat.protocol.dependencies`: The protocol is determined by the
|
||||
implementation of the library.
|
||||
|
||||
|
||||
Constraints
|
||||
|
|
@ -291,34 +299,59 @@ interface constrains ``Word`` to being the same size as C's generic
|
|||
pointer type, ``void *``.
|
||||
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
_`.impl`: The external interface consists of the following header
|
||||
files:
|
||||
|
||||
_`.impl.mps`: ``mps.h`` is the main external interface, containing of
|
||||
type and function declarations needed by all clients of the MPS.
|
||||
|
||||
_`.impl.mpstd`: ``mpstd.h`` is the MPS target detection header. It
|
||||
decodes preprocessor symbols which are predefined by build
|
||||
environments in order to determine the target platform (see
|
||||
design.mps.config_), and then defines uniform symbols, such as
|
||||
``MPS_ARCH_I3``, for use externally and internally by the MPS.
|
||||
``mpstd.h`` is not included by any of the other external headers, as
|
||||
it relies on exact set of preprocessor constants defined by compilers.
|
||||
|
||||
.. _design.mps.config: config
|
||||
|
||||
_`.impl.mpsio`: ``mpsio.h`` is the interface to the MPS I/O subsystem,
|
||||
part of the plinth. See design.mps.io_.
|
||||
|
||||
.. _design.mps.io: io
|
||||
|
||||
_`.impl.mpslib`: ``mpslib.h`` is the interface to the MPS Library
|
||||
Interface, part of the plinth. See design.mps.lib_.
|
||||
|
||||
.. _design.mps.lib: lib
|
||||
|
||||
_`.impl.mpsa`: Interfaces to arena classes are in files with names
|
||||
starting ``mpsa``: for example, the interface to the Virtual Memory
|
||||
arena class is in ``mpsavm.h``.
|
||||
|
||||
_`.impl.mpsc`: Interfaces to pool classes are in files with names
|
||||
starting ``mpsc``: for example, the interface to the MVFF pool class
|
||||
is in ``mpscmvff.h``.
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
The file ``mpstd.h`` is the MPS target detection header. It decodes
|
||||
preprocessor symbols which are predefined by build environments in
|
||||
order to determine the target platform, and then defines uniform
|
||||
symbols, such as ``MPS_ARCH_I3``, for use internally by the MPS.
|
||||
_`.fmt.extend`: ``mps_fmt_A_t`` is so called because new pool classes
|
||||
might require new format methods, but these methods cannot be added to
|
||||
the format structure without breaking binary compatibility. Therefore
|
||||
these new pool classes would use new format structures named
|
||||
``mps_fmt_B_t`` and so on.
|
||||
|
||||
There is a design document for the mps interface,
|
||||
design.mps.interface, but it was written before we had the idea of
|
||||
having a C interface layer. It is quite relevant, though, and could be
|
||||
updated. We should use it during the review.
|
||||
|
||||
All exported identifiers and file names should begin with ``mps_`` or
|
||||
``MPS_`` so that they don't clash with other systems.
|
||||
|
||||
We should probably have a specialized set of rules and a special
|
||||
checklist for this interface.
|
||||
|
||||
_`.fmt.extend`: This paragraph should be an explanation of why
|
||||
``mps_fmt_A_t`` is so called. The underlying reason is future
|
||||
extensibility.
|
||||
|
||||
_`.thread-safety`: Most calls through this interface lock the space
|
||||
_`.thread-safety`: Most calls through this interface lock the arena
|
||||
and therefore make the MPM single-threaded. In order to do this they
|
||||
must recover the space from their parameters. Methods such as
|
||||
``ThreadSpace()`` must therefore be callable when the space is *not*
|
||||
locked. These methods are tagged with the tag of this note.
|
||||
must recover the arena from their parameters. Methods such as
|
||||
``FormatArena()`` and ``ThreadArena()`` must therefore be callable
|
||||
when the arena is *not* locked. These methods are tagged with the tag
|
||||
of this note.
|
||||
|
||||
_`.lock-free`: Certain functions inside the MPM are thread-safe and do
|
||||
not need to be serialized by using locks. They are marked with the tag
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ but ``arg.h`` provides a macro for this::
|
|||
We define keys as static structures (rather than, say, an enum) because:
|
||||
|
||||
- The set of keys can be extended indefinitely.
|
||||
- The set of keys can be extended by indepdently linked modules.
|
||||
- The set of keys can be extended by independently linked modules.
|
||||
- The structure contents allow strong checking of argument lists.
|
||||
|
||||
In the MPS Interface, we declare keys like this::
|
||||
In the MPS C Interface, we declare keys like this::
|
||||
|
||||
extern const struct mps_key_s _mps_key_extend_by;
|
||||
#define MPS_KEY_EXTEND_BY (&_mps_key_extend_by)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ General MPS types
|
|||
:Tag: design.mps.type
|
||||
:Author: Richard Brooksby
|
||||
:Date: 1996-10-23
|
||||
:Status: incomplete document
|
||||
:Status: complete document
|
||||
:Revision: $Id$
|
||||
:Copyright: See `Copyright and License`_.
|
||||
:Index terms: pair: general types; design
|
||||
|
|
@ -32,6 +32,87 @@ say ``Byte`` in your code if it's what you mean.
|
|||
Concrete types
|
||||
--------------
|
||||
|
||||
``typedef unsigned AccessSet``
|
||||
|
||||
_`.access-set`: An ``AccessSet`` is a bitset of ``Access`` modes,
|
||||
which are ``AccessREAD`` and ``AccessWRITE``. ``AccessSetEMPTY`` is
|
||||
the empty ``AccessSet``.
|
||||
|
||||
|
||||
``typedef struct AddrStruct *Addr``
|
||||
|
||||
_`.addr`: ``Addr`` is the type used for "managed addresses", that is,
|
||||
addresses of objects managed by the MPS.
|
||||
|
||||
_`.addr.def`: ``Addr`` is defined as ``struct AddrStruct *``, but
|
||||
``AddrStruct`` is never defined. This means that ``Addr`` is always an
|
||||
incomplete type, which prevents accidental dereferencing, arithmetic,
|
||||
or assignment to other pointer types.
|
||||
|
||||
_`.addr.use`: ``Addr`` should be used whenever the code needs to deal
|
||||
with addresses. It should not be used for the addresses of memory
|
||||
manager data structures themselves, so that the memory manager remains
|
||||
amenable to working in a separate address space. Be careful not to
|
||||
confuse ``Addr`` with ``void *``.
|
||||
|
||||
_`.addr.ops`: Limited arithmetic is allowed on addresses using
|
||||
``AddrAdd()`` and ``AddrOffset()`` (impl.c.mpm). Addresses may also be
|
||||
compared using the relational operators ``==``, ``!=``, ``<``, ``<=``,
|
||||
``>``, and ``>=``.
|
||||
|
||||
_`.addr.ops.mem`: We need efficient operators similar to ``memset()``,
|
||||
``memcpy()``, and ``memcmp()`` on ``Addr``; these are called ``AddrSet()``,
|
||||
``AddrCopy()``, and ``AddrComp()``. When ``Addr`` is compatible with
|
||||
``void *``, these are implemented through the functions
|
||||
``mps_lib_memset()``, ``mps_lib_memcpy()``, and ``mps_lib_memcmp()``
|
||||
functions in the plinth (impl.h.mpm).
|
||||
|
||||
_`.addr.conv.c`: ``Addr`` is converted to ``mps_addr_t`` in the MPS C
|
||||
Interface. ``mps_addr_t`` is defined to be the same as ``void *``, so
|
||||
using the MPS C Interface confines the memory manager to the same
|
||||
address space as the client data.
|
||||
|
||||
|
||||
``typedef Word Align``
|
||||
|
||||
_`.align`: ``Align`` is an unsigned integral type which is used to
|
||||
represent the alignment of managed addresses. All alignments are
|
||||
positive powers of two. ``Align`` is large enough to hold the maximum
|
||||
possible alignment.
|
||||
|
||||
_`.align.use`: ``Align`` should be used whenever the code needs to
|
||||
deal with the alignment of a managed address.
|
||||
|
||||
_`.align.conv.c`: ``Align`` is converted to ``mps_align_t`` in the MPS
|
||||
C Interface.
|
||||
|
||||
|
||||
``typedef unsigned Attr``
|
||||
|
||||
_`.attr`: Pool attributes. A bitset of pool or pool class
|
||||
attributes, which are:
|
||||
|
||||
=================== ===================================================
|
||||
Attribute Description
|
||||
=================== ===================================================
|
||||
``AttrALLOC`` Supports the ``PoolAlloc`` interface.
|
||||
``AttrBUF`` Supports the buffer interface.
|
||||
``AttrFMT`` Contains formatted objects.
|
||||
Used to decide which pools to walk.
|
||||
``AttrFREE`` Supports the ``PoolFree`` interface.
|
||||
``AttrGC`` Is garbage collecting, that is, parts may be
|
||||
reclaimed. Used to decide which segments are
|
||||
condemned.
|
||||
``AttrMOVINGGC`` Is moving, that is, objects may move in memory.
|
||||
Used to update the set of zones that might have
|
||||
moved and so implement location dependency.
|
||||
``AttrSCAN`` Contains references and must be scanned.
|
||||
=================== ===================================================
|
||||
|
||||
There is an attribute field in the pool class (``PoolClassStruct``)
|
||||
which declares the attributes of that class.
|
||||
|
||||
|
||||
``typedef int Bool``
|
||||
|
||||
_`.bool`: The ``Bool`` type is mostly defined so that the intention of
|
||||
|
|
@ -71,63 +152,135 @@ for ``BoolCheck`` on the PC Aaron. "With" ran in 97.7% of the time
|
|||
(averaged over 3 runs).
|
||||
|
||||
|
||||
``typedef int Res``
|
||||
``typedef unsigned BufferMode``
|
||||
|
||||
_`.res`: ``Res`` is the type of result codes. A result code indicates
|
||||
the success or failure of an operation, along with the reason for
|
||||
failure. Like Unix error codes, the meaning of the code depends on the
|
||||
call that returned it. These codes are just broad categories with
|
||||
mnemonic names for various sorts of problems.
|
||||
_`.buffermode`: ``BufferMode`` is a bitset of buffer attributes. See
|
||||
design.mps.buffer_. It is a sum of the following:
|
||||
|
||||
=================== =======================================================
|
||||
Result code Description
|
||||
=================== =======================================================
|
||||
``ResOK`` The operation succeeded. Return parameters may only be
|
||||
updated if OK is returned, otherwise they must be left
|
||||
untouched.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResFAIL`` Something went wrong which doesn't fall into any of the
|
||||
other categories. The exact meaning depends on the
|
||||
call. See documentation.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResRESOURCE`` A needed resource could not be obtained. Which resource
|
||||
depends on the call. See also ``ResMEMORY``, which is a
|
||||
special case of this.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResMEMORY`` Needed memory (committed memory, not address space)
|
||||
could not be obtained.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResLIMIT`` An internal limitation was reached. For example, the
|
||||
maximum number of somethings was reached. We should
|
||||
avoid returning this by not including static
|
||||
limitations in our code, as far as possible. (See
|
||||
rule.impl.constrain and
|
||||
rule.impl.limits.)
|
||||
------------------- -------------------------------------------------------
|
||||
``ResUNIMPL`` The operation, or some vital part of it, is
|
||||
unimplemented. This might be returned by functions
|
||||
which are no longer supported, or by operations which
|
||||
are included for future expansion, but not yet
|
||||
supported.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResIO`` An I/O error occurred. Exactly what depends on the
|
||||
function.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResCOMMIT_LIMIT`` The arena's commit limit would have been exceeded
|
||||
as a result of allocation.
|
||||
------------------- -------------------------------------------------------
|
||||
``ResPARAM`` An invalid parameter was passed. Normally reserved for
|
||||
parameters passed from the client.
|
||||
=================== =======================================================
|
||||
.. _design.mps.buffer: buffer
|
||||
|
||||
_`.res.use`: ``Res`` should be returned from any function which might
|
||||
fail. Any other results of the function should be passed back in
|
||||
"return" parameters (pointers to locations to fill in with the
|
||||
results).
|
||||
======================== ==============================================
|
||||
Mode Description
|
||||
======================== ==============================================
|
||||
``BufferModeATTACHED`` Buffer is attached to a region of memory.
|
||||
``BufferModeFLIPPED`` Buffer has been flipped.
|
||||
``BufferModeLOGGED`` Buffer emits the events ``BufferReserve`` and
|
||||
``BufferCommit``.
|
||||
``BufferModeTRANSITION`` Buffer is in the process of being detached.
|
||||
======================== ==============================================
|
||||
|
||||
.. note:: This is documented elsewhere, I think -- richard
|
||||
|
||||
_`.res.use.spec`: The most specific code should be returned.
|
||||
``typedef unsigned char Byte``
|
||||
|
||||
_`.byte`: ``Byte`` is an unsigned integral type corresponding to the
|
||||
unit in which most sizes are measured, and also the units of
|
||||
``sizeof``.
|
||||
|
||||
_`.byte.use`: ``Byte`` should be used in preference to ``char`` or
|
||||
``unsigned char`` wherever it is necessary to deal with bytes
|
||||
directly.
|
||||
|
||||
_`.byte.source`: ``Byte`` is a just pedagogic version of ``unsigned
|
||||
char``, since ``char`` is the unit of ``sizeof``.
|
||||
|
||||
|
||||
``typedef Word Clock``
|
||||
|
||||
_`.clock`: ``Clock`` is an unsigned integral type representing clock
|
||||
time since some epoch.
|
||||
|
||||
_`.clock.use`: A ``Clock`` value is returned by the plinth function
|
||||
``mps_clock``. It is used to make collection scheduling decisions and
|
||||
to calibrate the time stamps on events in the telemetry stream.
|
||||
|
||||
_`.clock.units`: The plinth function ``mps_clocks_per_sec`` defines
|
||||
the units of a ``Clock`` value.
|
||||
|
||||
_`.clock.conv.c`: ``Clock`` is converted to ``mps_clock_t`` in the MPS
|
||||
C Interface.
|
||||
|
||||
|
||||
``typedef unsigned Compare``
|
||||
|
||||
_`.compare`: ``Compare`` is the type of tri-state comparison
|
||||
values.
|
||||
|
||||
================== ====================================================
|
||||
Value Description
|
||||
================== ====================================================
|
||||
``CompareLESS`` A value compares less than another value.
|
||||
``CompareEQUAL`` Two values compare the same.
|
||||
``CompareGREATER`` A value compares greater than another value.
|
||||
================== ====================================================
|
||||
|
||||
|
||||
``typedef Word Count``
|
||||
|
||||
_`.count`: ``Count`` is an unsigned integral type which is large
|
||||
enough to hold the size of any collection of objects in the MPS.
|
||||
|
||||
_`.count.use`: ``Count`` should be used for a number of objects
|
||||
(control or managed) where the maximum number of objects cannot be
|
||||
statically determined. If the maximum number can be statically
|
||||
determined then the smallest unsigned integer with a large enough
|
||||
range may be used instead (although ``Count`` may be preferable for
|
||||
clarity).
|
||||
|
||||
_`.count.use.other`: ``Count`` may also be used to count things that
|
||||
aren't represented by objects (for example, levels), but only where it
|
||||
can be determined that the maximum count is less than the number of
|
||||
objects.
|
||||
|
||||
|
||||
``typedef Size Epoch``
|
||||
|
||||
_`.epoch`: An ``Epoch`` is a count of the number of flips that have
|
||||
occurred. It is used in the implementation of location dependencies.
|
||||
|
||||
``Epoch`` is converted to ``mps_word_t`` in the MPS C Interface, as a
|
||||
field of ``mps_ld_s``.
|
||||
|
||||
|
||||
``typedef unsigned FindDelete``
|
||||
|
||||
_`.finddelete`: ``FindDelete`` represents an instruction to one of the
|
||||
*find* methods of a ``Land`` as to what it should do if it finds a
|
||||
suitable block. See design.mps.land_. It takes one of the following
|
||||
values:
|
||||
|
||||
.. _design.mps.land: land
|
||||
|
||||
==================== ==================================================
|
||||
Value Description
|
||||
==================== ==================================================
|
||||
``FindDeleteNONE`` Don't delete after finding.
|
||||
``FindDeleteLOW`` Delete from low end of block.
|
||||
``FindDeleteHIGH`` Delete from high end of block.
|
||||
``FindDeleteENTIRE`` Delete entire block.
|
||||
==================== ==================================================
|
||||
|
||||
|
||||
``typedef unsigned FrameState``
|
||||
|
||||
_`.framestate`: ``FrameState`` represents the current state in a
|
||||
buffer frame's lifecycle. See design.mps.alloc-frame_. It takes one of
|
||||
the following values:
|
||||
|
||||
.. _design.mps.alloc-frame: alloc-frame
|
||||
|
||||
========================== ============================================
|
||||
State Description
|
||||
========================== ============================================
|
||||
``BufferFrameVALID`` Indicates that ``PushFrame()`` can be a
|
||||
lightweight operation and need not be
|
||||
synchronized.
|
||||
``BufferFramePOP_PENDING`` Indicates that there has been a
|
||||
``PopFrame()`` operation that the pool
|
||||
must respond to.
|
||||
``BufferFrameDISABLED`` Indicates that the pool has disabled
|
||||
support for lightweight operations for
|
||||
this buffer.
|
||||
========================== ============================================
|
||||
|
||||
|
||||
``typedef void (*Fun)(void)``
|
||||
|
|
@ -142,6 +295,328 @@ through to a third function ``h``, where ``h`` knows the real type of
|
|||
``f`` but ``g`` doesn't.
|
||||
|
||||
|
||||
``typedef Word Index``
|
||||
|
||||
_`.index`: ``Index`` is an unsigned integral type which is large
|
||||
enough to hold any array index.
|
||||
|
||||
_`.index.use`: ``Index`` should be used where the maximum size of the
|
||||
array cannot be statically determined. If the maximum size can be
|
||||
determined then the smallest unsigned integer with a large enough
|
||||
range may be used instead.
|
||||
|
||||
|
||||
``typedef unsigned MessageType``
|
||||
|
||||
_`.messagetype`: ``MessageType`` is the type of a message. See
|
||||
design.mps.message_. It takes one of the following values:
|
||||
|
||||
.. _design.mps.message: message
|
||||
|
||||
=========================== ===========================================
|
||||
Message type Description
|
||||
=========================== ===========================================
|
||||
``MessageTypeFINALIZATION`` A block is finalizable.
|
||||
``MessageTypeGC`` A garbage collection finished.
|
||||
``MessageTypeGCSTART`` A garbage collection started.
|
||||
=========================== ===========================================
|
||||
|
||||
|
||||
``typedef unsigned Rank``
|
||||
|
||||
_`.rank`: ``Rank`` is an enumeration which represents the rank of a
|
||||
reference. The ranks are:
|
||||
|
||||
============= ===== ==================================================
|
||||
Rank Index Description
|
||||
============= ===== ==================================================
|
||||
``RankAMBIG`` 0 The reference is ambiguous. That is, it must be
|
||||
assumed to be a reference, but not updated in
|
||||
case it isn't.
|
||||
``RankEXACT`` 1 The reference is exact, and refers to an object.
|
||||
``RankFINAL`` 2 The reference is exact and final, so special
|
||||
action is required if only final or weak
|
||||
references remain to the object.
|
||||
``RankWEAK`` 3 The reference is exact and weak, so should
|
||||
be deleted if only weak references remain to the
|
||||
object.
|
||||
============= ===== ==================================================
|
||||
|
||||
``Rank`` is stored with segments and roots, and passed around.
|
||||
|
||||
``Rank`` is converted to ``mps_rank_t`` in the MPS C Interface.
|
||||
|
||||
The ordering of the ranks is important. It is the order in which the
|
||||
references must be scanned in order to respect the properties of
|
||||
references of the ranks. Therefore they are declared explicitly with
|
||||
their integer values.
|
||||
|
||||
.. note:: Could ``Rank`` be a ``short``?
|
||||
|
||||
.. note::
|
||||
|
||||
This documentation should be expanded and moved to its own
|
||||
document, then referenced from the implementation more thoroughly.
|
||||
|
||||
|
||||
``typedef unsigned RankSet``
|
||||
|
||||
_`.rankset`: ``RankSet`` is a set of ranks, represented as a bitset.
|
||||
|
||||
|
||||
``typedef Addr Ref``
|
||||
|
||||
_`.ref`: ``Ref`` is a reference to a managed object (as opposed to any
|
||||
old managed address). ``Ref`` should be used where a reference is
|
||||
intended.
|
||||
|
||||
.. note:: This isn't too clear -- richard
|
||||
|
||||
|
||||
``typedef Word RefSet``
|
||||
|
||||
_`.refset`: ``RefSet`` is a conservative approximation to a set of
|
||||
references. See design.mps.refset_.
|
||||
|
||||
.. _design.mps.refset: refset
|
||||
|
||||
|
||||
``typedef int Res``
|
||||
|
||||
_`.res`: ``Res`` is the type of result codes. A result code indicates
|
||||
the success or failure of an operation, along with the reason for
|
||||
failure. Like Unix error codes, the meaning of the code depends on the
|
||||
call that returned it. These codes are just broad categories with
|
||||
mnemonic names for various sorts of problems.
|
||||
|
||||
=================== ===================================================
|
||||
Result code Description
|
||||
=================== ===================================================
|
||||
``ResOK`` The operation succeeded. Return parameters may only
|
||||
be updated if OK is returned, otherwise they must
|
||||
be left untouched.
|
||||
``ResCOMMIT_LIMIT`` The arena's commit limit would have been exceeded
|
||||
as a result of allocation.
|
||||
``ResFAIL`` Something went wrong which doesn't fall into any of
|
||||
the other categories. The exact meaning depends
|
||||
on the call. See documentation.
|
||||
``ResIO`` An I/O error occurred. Exactly what depends on the
|
||||
function.
|
||||
``ResLIMIT`` An internal limitation was reached. For example,
|
||||
the maximum number of somethings was reached. We
|
||||
should avoid returning this by not including
|
||||
static limitations in our code, as far as
|
||||
possible. (See rule.impl.constrain and
|
||||
rule.impl.limits.)
|
||||
``ResMEMORY`` Needed memory (committed memory, not address space)
|
||||
could not be obtained.
|
||||
``ResPARAM`` An invalid parameter was passed. Normally reserved
|
||||
for parameters passed from the client.
|
||||
``ResRESOURCE`` A needed resource could not be obtained. Which
|
||||
resource depends on the call. See also
|
||||
``ResMEMORY``, which is a special case of this.
|
||||
``ResUNIMPL`` The operation, or some vital part of it, is
|
||||
unimplemented. This might be returned by
|
||||
functions which are no longer supported, or by
|
||||
operations which are included for future
|
||||
expansion, but not yet supported.
|
||||
=================== ===================================================
|
||||
|
||||
_`.res.use`: ``Res`` should be returned from any function which might
|
||||
fail. Any other results of the function should be passed back in
|
||||
"return" parameters (pointers to locations to fill in with the
|
||||
results).
|
||||
|
||||
.. note:: This is documented elsewhere, I think -- richard
|
||||
|
||||
_`.res.use.spec`: The most specific code should be returned.
|
||||
|
||||
|
||||
``typedef unsigned RootMode``
|
||||
|
||||
_`.rootmode`: ``RootMode`` is an unsigned integral type which is used
|
||||
to represent an attribute of a root:
|
||||
|
||||
============================= =========================================
|
||||
Root mode Description
|
||||
============================= =========================================
|
||||
``RootModeCONSTANT`` Client program will not change the root
|
||||
after it is registered.
|
||||
``RootModePROTECTABLE`` Root is protectable: the MPS may place
|
||||
a barrier on any page containing any
|
||||
part of the root.
|
||||
``RootModePROTECTABLE_INNER`` Root is protectable: the MPS may place
|
||||
a barrier on any page completely covered
|
||||
by part of the root.
|
||||
============================= =========================================
|
||||
|
||||
_`.rootmode.const.unused`: ``RootModeCONSTANT`` has no effect. This
|
||||
mode was introduced in the hope of being able to maintain a
|
||||
:term:`remembered set` for the root without needing a :term:`write
|
||||
barrier`, but it can't work as described, since you can't reliably
|
||||
create a valid registered constant root that contains any references.
|
||||
(If you add the references before registering the root, they may have
|
||||
become invalid; but you can't add them afterwards because the root is
|
||||
supposed to be constant.)
|
||||
|
||||
_`.rootmode.conv.c`: ``RootMode`` is converted to ``mps_rm_t`` in the MPS C
|
||||
Interface.
|
||||
|
||||
|
||||
``typedef int RootVar``
|
||||
|
||||
_`.rootvar`: The type ``RootVar`` is the type of the
|
||||
discriminator for the union within ``RootStruct``.
|
||||
|
||||
|
||||
``typedef int SegPrefKind``
|
||||
|
||||
_`.segprefkind`: The type ``SegPrefKind`` expresses a preference about
|
||||
where the arena should place a segment. It takes one of the following
|
||||
values:
|
||||
|
||||
================== ====================================================
|
||||
Kind Description
|
||||
================== ====================================================
|
||||
``SegPrefHigh`` Place the segment high in the address space.
|
||||
``SegPrefLow`` Place the segment low in the address space.
|
||||
``SegPrefZoneSet`` Place the segment in specified zones.
|
||||
================== ====================================================
|
||||
|
||||
|
||||
``typedef unsigned Serial``
|
||||
|
||||
_`.serial`: A ``Serial`` is a number which is assigned to a structure
|
||||
when it is initialized. The serial number is taken from a field in the
|
||||
parent structure, which is incremented. Thus, every instance of a
|
||||
structure has a unique "name" which is a path of structures from the
|
||||
global root. For example::
|
||||
|
||||
space[3].pool[5].buffer[2]
|
||||
|
||||
Why? Consistency checking, debugging, and logging. Not well thought
|
||||
out.
|
||||
|
||||
|
||||
``typedef unsigned Shift``
|
||||
|
||||
_`.shift`: ``Shift`` is an unsigned integral type which can hold the
|
||||
amount by which a ``Word`` can be shifted. It is therefore large
|
||||
enough to hold the word width (in bits).
|
||||
|
||||
_`.shift.use`: ``Shift`` should be used whenever a shift value (the
|
||||
right-hand operand of the ``<<`` or ``>>`` operators) is intended, to
|
||||
make the code clear. It should also be used for structure fields which
|
||||
have this use.
|
||||
|
||||
|
||||
``typedef unsigned long Sig``
|
||||
|
||||
_`.sig`: ``Sig`` is the type of signatures, which are written into
|
||||
structures when they are created, and invalidated when they are
|
||||
destroyed. They provide a limited form of run-time type checking and
|
||||
dynamic scope checking. See design.mps.sig_.
|
||||
|
||||
.. _design.mps.sig: sig
|
||||
|
||||
|
||||
``typedef Word Size``
|
||||
|
||||
_`.size`: ``Size`` is an unsigned integral type large enough to
|
||||
hold the size of any object which the MPS might manage.
|
||||
|
||||
_`.size.byte`: ``Size`` should hold a size calculated in bytes.
|
||||
|
||||
.. warning::
|
||||
|
||||
This is violated by ``GenParams.capacity`` (which is measured in
|
||||
kilobytes).
|
||||
|
||||
_`.size.use`: ``Size`` should be used whenever the code needs to deal
|
||||
with the size of managed memory or client objects. It should not be
|
||||
used for the sizes of the memory manager's own data structures, so
|
||||
that the memory manager is amenable to working in a separate address
|
||||
space. Be careful not to confuse it with ``size_t``.
|
||||
|
||||
_`.size.ops`: ``SizeIsAligned()``, ``SizeAlignUp()``,
|
||||
``SizeAlignDown()`` and ``SizeRoundUp()``.
|
||||
|
||||
_`.size.conv.c`: ``Size`` is converted to ``size_t`` in the MPS C
|
||||
Interface. This constrains the memory manager to the same address
|
||||
space as the client data.
|
||||
|
||||
|
||||
``typedef unsigned TraceId``
|
||||
|
||||
_`.traceid`: A ``TraceId`` is an unsigned integer which is less than
|
||||
``TRACE_MAX``. Each running trace has a different ``TraceId`` which is
|
||||
used to index into tables and bitfields used to remember the state of
|
||||
that trace.
|
||||
|
||||
|
||||
``typedef unsigned TraceSet``
|
||||
|
||||
_`.traceset`: A ``TraceSet`` is a bitset of ``TraceId``,
|
||||
represented in the obvious way::
|
||||
|
||||
member(ti, ts) ⇔ ((1<<ti) & ts) != 0
|
||||
|
||||
``TraceSet`` is used to represent colour in the Tracer. See
|
||||
design.mps.trace_.
|
||||
|
||||
.. _design.mps.trace: trace
|
||||
|
||||
``typedef unsigned TraceStartWhy``
|
||||
|
||||
_`.tracestartwhy`: ``TraceStartWhy`` represents the reason that a
|
||||
trace was started. It takes one of the following values:
|
||||
|
||||
======================================= ===============================
|
||||
Reason Description
|
||||
======================================= ===============================
|
||||
``TraceStartWhyCHAIN_GEN0CAP`` Generation zero of a chain
|
||||
reached capacity.
|
||||
``TraceStartWhyDYNAMICCRITERION`` Need to start full collection
|
||||
now, or there won't be enough
|
||||
memory to complete it.
|
||||
``TraceStartWhyOPPORTUNISM`` Client had idle time available.
|
||||
``TraceStartWhyCLIENTFULL_INCREMENTAL`` Client requested incremental
|
||||
collection.
|
||||
``TraceStartWhyCLIENTFULL_BLOCK`` Client requested full
|
||||
collection.
|
||||
``TraceStartWhyWALK`` Walking references.
|
||||
``TraceStartWhyEXTENSION`` Request by MPS extension.
|
||||
======================================= ===============================
|
||||
|
||||
|
||||
``typedef unsigned TraceState``
|
||||
|
||||
_`.tracestate`: ``TraceState`` represents the current state in a
|
||||
trace's lifecycle. See design.mps.trace_. It takes one of the
|
||||
following values:
|
||||
|
||||
================== ====================================================
|
||||
State Description
|
||||
================== ====================================================
|
||||
``TraceINIT`` Nothing happened yet.
|
||||
``TraceUNFLIPPED`` Segments condemned (made white); initial grey set
|
||||
created; scanning rate calculated.
|
||||
``TraceFLIPPED`` Buffers flipped; roots scanned; location
|
||||
dependencies made stale; grey segments protected.
|
||||
``TraceRECLAIM`` There are no outstanding grey segments.
|
||||
``TraceFINISHED`` All segments reclaimed.
|
||||
================== ====================================================
|
||||
|
||||
|
||||
``typedef MPS_T_ULONGEST ULongest``
|
||||
|
||||
_`.ulongest`: ``ULongest`` is the longest unsigned integer on the
|
||||
platform. (We used to use ``unsigned long`` but this assumption is
|
||||
violated by 64-bit Windows.) This type should be used for calculations
|
||||
where any integer might be passed. Notably, it is used in ``WriteF()``
|
||||
to print any integer.
|
||||
|
||||
|
||||
``typedef MPS_T_WORD Word``
|
||||
|
||||
_`.word`: ``Word`` is an unsigned integral type which matches the size
|
||||
|
|
@ -162,348 +637,10 @@ _`.word.ops`: ``WordIsAligned()``, ``WordAlignUp()``,
|
|||
``WordAlignDown()`` and ``WordRoundUp()``.
|
||||
|
||||
|
||||
``typedef unsigned char Byte``
|
||||
``typedef Word ZoneSet``
|
||||
|
||||
_`.byte`: ``Byte`` is an unsigned integral type corresponding to the
|
||||
unit in which most sizes are measured, and also the units of
|
||||
``sizeof``.
|
||||
|
||||
_`.byte.use`: ``Byte`` should be used in preference to ``char`` or
|
||||
``unsigned char`` wherever it is necessary to deal with bytes
|
||||
directly.
|
||||
|
||||
_`.byte.source`: ``Byte`` is a just pedagogic version of ``unsigned
|
||||
char``, since ``char`` is the unit of ``sizeof``.
|
||||
|
||||
|
||||
``typedef Word Index``
|
||||
|
||||
_`.index`: ``Index`` is an unsigned integral type which is large
|
||||
enough to hold any array index.
|
||||
|
||||
_`.index.use`: ``Index`` should be used where the maximum size of the
|
||||
array cannot be statically determined. If the maximum size can be
|
||||
determined then the smallest unsigned integer with a large enough
|
||||
range may be used instead.
|
||||
|
||||
|
||||
``typedef Word Count``
|
||||
|
||||
_`.count`: ``Count`` is an unsigned integral type which is large
|
||||
enough to hold the size of any collection of objects in the MPS.
|
||||
|
||||
_`.count.use`: ``Count`` should be used for a number of objects
|
||||
(control or managed) where the maximum number of objects cannot be
|
||||
statically determined. If the maximum number can be statically
|
||||
determined then the smallest unsigned integer with a large enough
|
||||
range may be used instead (although ``Count`` may be preferable for
|
||||
clarity).
|
||||
|
||||
.. note::
|
||||
|
||||
Should ``Count`` be used to count things that aren't represented
|
||||
by objects (for example, a level)? I would say yes. gavinm
|
||||
1998-07-21
|
||||
|
||||
.. note::
|
||||
|
||||
Only where it can be determined that the maximum count is less
|
||||
than the number of objects. pekka 1998-07-21
|
||||
|
||||
|
||||
``typedef Word Accumulation``
|
||||
|
||||
_`.accumulation`: ``Accumulation`` is an arithmetic type which is
|
||||
large enough to hold accumulated totals of objects of bytes (for
|
||||
example, total number of objects allocated, total number of bytes
|
||||
allocated).
|
||||
|
||||
_`.accumulation.type`: Currently it is ``double``, but the reason for
|
||||
the interface is so that we can more easily change it if we want to
|
||||
(if we decide we need more accuracy for example).
|
||||
|
||||
_`.accumulation.use`: Currently the only way to use an
|
||||
``Accumulation`` is to reset it (by calling ``AccumulatorReset``) and
|
||||
accumulate amounts into it (by calling ``Accumulate``). There is no
|
||||
way to read it at the moment, but that's okay, because no one seems to
|
||||
want to.
|
||||
|
||||
_`.accumulation.future`: Probably we should have methods which return
|
||||
the accumulation into an ``unsigned long``, and also a ``double``;
|
||||
these functions should return ``Bool`` to indicate whether the
|
||||
accumulation can fit in the requested type. Possibly we could have
|
||||
functions which returned scaled accumulations. For example,
|
||||
``AccumulatorScale(a, d)`` would divide the ``Accumulation a`` by
|
||||
``double d`` and return the ``double`` result if it fitted into a
|
||||
``double``.
|
||||
|
||||
|
||||
``typedef struct AddrStruct *Addr``
|
||||
|
||||
_`.addr`: ``Addr`` is the type used for "managed addresses", that is,
|
||||
addresses of objects managed by the MPS.
|
||||
|
||||
_`.addr.def`: ``Addr`` is defined as ``struct AddrStruct *``, but
|
||||
``AddrStruct`` is never defined. This means that ``Addr`` is always an
|
||||
incomplete type, which prevents accidental dereferencing, arithmetic,
|
||||
or assignment to other pointer types.
|
||||
|
||||
_`.addr.use`: ``Addr`` should be used whenever the code needs to deal
|
||||
with addresses. It should not be used for the addresses of memory
|
||||
manager data structures themselves, so that the memory manager remains
|
||||
amenable to working in a separate address space. Be careful not to
|
||||
confuse ``Addr`` with ``void *``.
|
||||
|
||||
_`.addr.ops`: Limited arithmetic is allowed on addresses using
|
||||
``AddrAdd()`` and ``AddrOffset()`` (impl.c.mpm). Addresses may also be
|
||||
compared using the relational operators ``==``, ``!=``, ``<``, ``<=``,
|
||||
``>``, and ``>=``.
|
||||
|
||||
_`.addr.ops.mem`: We need efficient operators similar to ``memset()``,
|
||||
``memcpy()``, and ``memcmp()`` on ``Addr``; these are called ``AddrSet()``,
|
||||
``AddrCopy()``, and ``AddrComp()``. When ``Addr`` is compatible with
|
||||
``void *``, these are implemented through the functions
|
||||
``mps_lib_memset()``, ``mps_lib_memcpy()``, and ``mps_lib_memcmp()``
|
||||
functions in the plinth (impl.h.mpm).
|
||||
|
||||
.. note::
|
||||
|
||||
No other implementation exists at present. pekka 1998-09-07
|
||||
|
||||
_`.addr.conv.c`: ``Addr`` is converted to ``mps_addr_t`` in the MPS C
|
||||
Interface. ``mps_addr_t`` is defined to be the same as ``void *``, so
|
||||
using the MPS C Interface confines the memory manager to the same
|
||||
address space as the client data.
|
||||
|
||||
|
||||
``typedef Word Size``
|
||||
|
||||
_`.size`: ``Size`` is an unsigned integral type large enough to
|
||||
hold the size of any object which the MPS might manage.
|
||||
|
||||
_`.size.byte`: ``Size`` should hold a size calculated in bytes.
|
||||
|
||||
.. warning:: This may not be true for all existing code.
|
||||
|
||||
_`.size.use`: ``Size`` should be used whenever the code needs to deal
|
||||
with the size of managed memory or client objects. It should not be
|
||||
used for the sizes of the memory manager's own data structures, so
|
||||
that the memory manager is amenable to working in a separate address
|
||||
space. Be careful not to confuse it with ``size_t``.
|
||||
|
||||
_`.size.ops`: ``SizeIsAligned()``, ``SizeAlignUp()``,
|
||||
``SizeAlignDown()`` and ``SizeRoundUp()``.
|
||||
|
||||
_`.size.conv.c`: ``Size`` is converted to ``size_t`` in the MPS C
|
||||
Interface. This constrains the memory manager to the same address
|
||||
space as the client data.
|
||||
|
||||
|
||||
``typedef Word Align``
|
||||
|
||||
_`.align`: ``Align`` is an unsigned integral type which is used to
|
||||
represent the alignment of managed addresses. All alignments are
|
||||
positive powers of two. ``Align`` is large enough to hold the maximum
|
||||
possible alignment.
|
||||
|
||||
_`.align.use`: ``Align`` should be used whenever the code needs to
|
||||
deal with the alignment of a managed address.
|
||||
|
||||
_`.align.conv.c`: ``Align`` is converted to ``mps_align_t`` in the MPS
|
||||
C Interface.
|
||||
|
||||
|
||||
``typedef unsigned Shift``
|
||||
|
||||
_`.shift`: ``Shift`` is an unsigned integral type which can hold the
|
||||
amount by which a ``Word`` can be shifted. It is therefore large
|
||||
enough to hold the word width (in bits).
|
||||
|
||||
_`.shift.use`: ``Shift`` should be used whenever a shift value (the
|
||||
right-hand operand of the ``<<`` or ``>>`` operators) is intended, to
|
||||
make the code clear. It should also be used for structure fields which
|
||||
have this use.
|
||||
|
||||
_`.shift.conv.c`: ``Shift`` is converted to ``mps_shift_t`` in the MPS
|
||||
C Interface.
|
||||
|
||||
|
||||
``typedef Addr Ref``
|
||||
|
||||
_`.ref`: ``Ref`` is a reference to a managed object (as opposed to any
|
||||
old managed address). ``Ref`` should be used where a reference is
|
||||
intended.
|
||||
|
||||
.. note:: This isn't too clear -- richard
|
||||
|
||||
|
||||
``typedef Word RefSet``
|
||||
|
||||
_`.refset`: ``RefSet`` is a conservative approximation to a set of
|
||||
references. See design.mps.refset.
|
||||
|
||||
|
||||
``typedef unsigned Rank``
|
||||
|
||||
_`.rank`: ``Rank`` is an enumeration which represents the rank of a
|
||||
reference. The ranks are:
|
||||
|
||||
============= ===== =====================================================
|
||||
Rank Index Description
|
||||
============= ===== =====================================================
|
||||
``RankAMBIG`` 0 The reference is ambiguous. That is, it must be
|
||||
assumed to be a reference, but not updated in case it
|
||||
isn't.
|
||||
------------- ----- -----------------------------------------------------
|
||||
``RankEXACT`` 1 The reference is exact, and refers to an object.
|
||||
------------- ----- -----------------------------------------------------
|
||||
``RankFINAL`` 2 The reference is exact and final, so special action
|
||||
is required if only final or weak references remain
|
||||
to the object.
|
||||
------------- ----- -----------------------------------------------------
|
||||
``RankWEAK`` 3 The reference is exact and weak, so should be deleted
|
||||
if only weak references remain to the object.
|
||||
============= ===== =====================================================
|
||||
|
||||
``Rank`` is stored with segments and roots, and passed around.
|
||||
|
||||
``Rank`` is converted to ``mps_rank_t`` in the MPS C Interface.
|
||||
|
||||
The ordering of the ranks is important. It is the order in which the
|
||||
references must be scanned in order to respect the properties of
|
||||
references of the ranks. Therefore they are declared explicitly with
|
||||
their integer values.
|
||||
|
||||
.. note:: Could ``Rank`` be a ``short``?
|
||||
|
||||
.. note::
|
||||
|
||||
This documentation should be expanded and moved to its own
|
||||
document, then referenced from the implementation more thoroughly.
|
||||
|
||||
|
||||
``typedef Size Epoch``
|
||||
|
||||
_`.epoch`: An ``Epoch`` is a count of the number of flips that have
|
||||
occurred. It is used in the implementation of location dependencies.
|
||||
|
||||
``Epoch`` is converted to ``mps_word_t`` in the MPS C Interface, as a
|
||||
field of ``mps_ld_s``.
|
||||
|
||||
|
||||
``typedef unsigned TraceId``
|
||||
|
||||
_`.traceid`: A ``TraceId`` is an unsigned integer which is less than
|
||||
``TRACE_MAX``. Each running trace has a different ``TraceId`` which is
|
||||
used to index into tables and bitfields used to remember the state of
|
||||
that trace.
|
||||
|
||||
|
||||
``typedef unsigned TraceSet``
|
||||
|
||||
_`.traceset`: A ``TraceSet`` is a bitset of ``TraceId``,
|
||||
represented in the obvious way::
|
||||
|
||||
member(ti, ts) ⇔ ((1<<ti) & ts) != 0
|
||||
|
||||
``TraceSet`` is used to represent colour in the Tracer.
|
||||
|
||||
.. note:: Expand on this.
|
||||
|
||||
|
||||
``typedef unsigned AccessSet``
|
||||
|
||||
_`.access-set`: An ``AccessSet`` is a bitset of ``Access``
|
||||
modes, which are ``AccessREAD`` and ``AccessWRITE``. ``AccessNONE`` is
|
||||
the empty ``AccessSet``.
|
||||
|
||||
|
||||
``typedef unsigned Attr``
|
||||
|
||||
_`.attr`: Pool attributes. A bitset of pool or pool class
|
||||
attributes, which are:
|
||||
|
||||
=================== ===========================================================
|
||||
Attribute Description
|
||||
=================== ===========================================================
|
||||
``AttrFMT`` Contains formatted objects.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrSCAN`` Contains references and must be scanned.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrPM_NO_READ`` May not be read protected.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrPM_NO_WRITE`` May not be write protected.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrALLOC`` Supports the ``PoolAlloc`` interface.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrFREE`` Supports the ``PoolFree`` interface.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrBUF`` Supports the allocation buffer interface.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrBUF_RESERVE`` Supports the reserve/commit protocol on allocation buffers.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrBUF_ALLOC`` Supports the alloc protocol on allocation buffers.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrGC`` Is garbage collecting, that is, parts may be reclaimed.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrINCR_RB`` Is incremental, requiring a read barrier.
|
||||
------------------- -----------------------------------------------------------
|
||||
``AttrINCR_WB`` Is incremental, requiring a write barrier.
|
||||
=================== ===========================================================
|
||||
|
||||
There is an attribute field in the pool class (``PoolClassStruct``)
|
||||
which declares the attributes of that class. These attributes are only
|
||||
used for consistency checking at the moment.
|
||||
|
||||
.. note::
|
||||
|
||||
It's no longer true that they are only used for consistency
|
||||
checking -- drj 1998-05-07
|
||||
|
||||
|
||||
``typedef int RootVar``
|
||||
|
||||
_`.rootvar`: The type ``RootVar`` is the type of the
|
||||
discriminator for the union within ``RootStruct``.
|
||||
|
||||
|
||||
``typedef unsigned Serial``
|
||||
|
||||
_`.serial`: A ``Serial`` is a number which is assigned to a structure
|
||||
when it is initialized. The serial number is taken from a field in the
|
||||
parent structure, which is incremented. Thus, every instance of a
|
||||
structure has a unique "name" which is a path of structures from the
|
||||
global root. For example::
|
||||
|
||||
space[3].pool[5].buffer[2]
|
||||
|
||||
Why? Consistency checking, debugging, and logging. Not well thought
|
||||
out.
|
||||
|
||||
|
||||
``typedef unsigned Compare``
|
||||
|
||||
_`.compare`: ``Compare`` is the type of tri-state comparison
|
||||
values.
|
||||
|
||||
================== ===========================================
|
||||
Value Description
|
||||
================== ===========================================
|
||||
``CompareLESS`` A value compares less than another value.
|
||||
------------------ -------------------------------------------
|
||||
``CompareEQUAL`` Two values compare the same.
|
||||
------------------ -------------------------------------------
|
||||
``CompareGREATER`` A value compares greater than another value.
|
||||
================== ===========================================
|
||||
|
||||
|
||||
``typedef MPS_T_ULONGEST ULongest``
|
||||
|
||||
_`.ulongest`: ``ULongest`` is the longest unsigned integer on the
|
||||
platform. (We used to use ``unsigned long`` but this assumption is
|
||||
violated by 64-bit Windows.) This type should be used for calculations
|
||||
where any integer might be passed. Notably, it is used in ``WriteF()``
|
||||
to print any integer.
|
||||
_`.zoneset`: ``ZoneSet`` is a conservative approximation to a set of
|
||||
zone. See design.mps.refset_.
|
||||
|
||||
|
||||
Abstract types
|
||||
|
|
@ -513,7 +650,12 @@ _`.adts`: The following types are abstract data types, implemented as
|
|||
pointers to structures. For example, ``Ring`` is a pointer to a
|
||||
``RingStruct``. They are described elsewhere.
|
||||
|
||||
``AP``, ``Arena``, ``Buffer``, ``Format``, ``LD``, ``Lock``, ``PoolClass``, ``Pool``, ``Ring``, ``Root``, ``ScanState``, ``Seg``, ``Space``, ``Thread``, ``Trace``, ``VM``.
|
||||
``AllocFrame``, ``AllocPattern``, ``AP``, ``Arena``, ``BootBlock``,
|
||||
``Buffer``, ``Chain``, ``Chunk``, ``Format``, ``Globals``, ``Land``,
|
||||
``LD``, ``Lock``, ``MutatorFaultContext``, ``PoolClass``, ``Page``,
|
||||
``Pool``, ``PoolDebugMixin``, ``Range``, ``Reservoir``, ``Ring``,
|
||||
``Root``, ``ScanState``, ``Seg``, ``SegBuf``, ``SegPref``,
|
||||
``StackContext``, ``Thread``, ``Trace``, ``VM``.
|
||||
|
||||
``typedef void *Pointer``
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ Design
|
|||
freelist
|
||||
guide.hex.trans
|
||||
guide.impl.c.format
|
||||
interface-c
|
||||
keyword-arguments
|
||||
nailboard
|
||||
range
|
||||
ring
|
||||
sig
|
||||
type
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ Old design
|
|||
diag
|
||||
finalize
|
||||
fix
|
||||
interface-c
|
||||
io
|
||||
lib
|
||||
lock
|
||||
|
|
@ -62,7 +61,6 @@ Old design
|
|||
thread-manager
|
||||
thread-safety
|
||||
trace
|
||||
type
|
||||
version-library
|
||||
version
|
||||
vm
|
||||
|
|
|
|||
|
|
@ -905,6 +905,10 @@ changes size::
|
|||
3. The order of operations at the end is important: the old root
|
||||
must be de-registered before its memory is freed.
|
||||
|
||||
4. When calling :c:func:`mps_root_create_table`, take care to
|
||||
avoid undefined behaviour due to :term:`type punning`. See the
|
||||
:ref:`warning <topic-root-type-pun>`.
|
||||
|
||||
.. topics::
|
||||
|
||||
:ref:`topic-root`.
|
||||
|
|
|
|||
|
|
@ -168,3 +168,86 @@ Other changes
|
|||
exception while the MPS is holding the arena lock. See job003640_.
|
||||
|
||||
.. _job003640: https://www.ravenbrook.com/project/mps/issue/job003640/
|
||||
|
||||
|
||||
.. _release-notes-1.111:
|
||||
|
||||
Release 1.111.0
|
||||
---------------
|
||||
|
||||
New features
|
||||
............
|
||||
|
||||
#. Reporting features have been removed from the :ref:`mpseventcnv
|
||||
<telemetry-mpseventcnv>` utility. Instead, the telemetry system
|
||||
comes with two new utility programs to assist with reporting and
|
||||
analysis: :ref:`mpseventtxt <telemetry-mpseventtxt>` converts an
|
||||
event stream into human-readable form, and :ref:`mpseventsql
|
||||
<telemetry-mpseventsql>` loads an event stream into a SQLite
|
||||
database for further analysis. See :ref:`topic-telemetry`.
|
||||
|
||||
#. The new pool class MFS provide manually managed allocation of
|
||||
fixed-size objects. See :ref:`pool-mfs`.
|
||||
|
||||
#. The new pool class MVT provide manually managed allocation of
|
||||
variable-size objects using a *temporal fit* allocation policy
|
||||
(that is, objects that are allocated togther are expected to be
|
||||
freed together). See :ref:`pool-mvt`.
|
||||
|
||||
|
||||
Interface changes
|
||||
.................
|
||||
|
||||
#. It is no longer necessary for client programs to use
|
||||
:c:func:`mps_tramp` to ensure that exceptions due to barrier hits
|
||||
are caught. This function is now deprecated.
|
||||
|
||||
#. You can set the environment variable
|
||||
:envvar:`MPS_TELEMETRY_CONTROL` to ``all`` to make the telemetry
|
||||
system output all events. See :ref:`topic-telemetry`.
|
||||
|
||||
#. New functions :c:func:`mps_telemetry_get`,
|
||||
:c:func:`mps_telemetry_set` and :c:func:`mps_telemetry_reset`
|
||||
provide a more convenient interface to telemetry control than
|
||||
:c:func:`mps_telemetry_control`, which is now deprecated. See
|
||||
:ref:`topic-telemetry`.
|
||||
|
||||
#. The pool classes :ref:`pool-mv` and :ref:`pool-snc` are now
|
||||
deprecated.
|
||||
|
||||
#. Allocation frames are now deprecated. See :ref:`topic-frame`.
|
||||
|
||||
#. Additionally, the functions :c:func:`mps_arena_expose`,
|
||||
:c:func:`mps_arena_unsafe_expose_remember_protection`,
|
||||
:c:func:`mps_arena_unsafe_restore_protection`,
|
||||
:c:func:`mps_arena_roots_walk`, and :c:func:`mps_fix` are now
|
||||
deprecated.
|
||||
|
||||
|
||||
Other changes
|
||||
.............
|
||||
|
||||
#. :c:func:`mps_arena_step` no longer unclamps the arena as a side
|
||||
effect. If the arena is clamped or parked before calling
|
||||
:c:func:`mps_arena_step`, it is clamped afterwards. See job003320_.
|
||||
|
||||
.. _job003320: https://www.ravenbrook.com/project/mps/issue/job003320/
|
||||
|
||||
#. The ambiguous stack scanner, :c:func:`mps_stack_scan_ambig`, no
|
||||
longer asserts on Linux when there are multiple threads. See
|
||||
job003412_.
|
||||
|
||||
.. _job003412: https://www.ravenbrook.com/project/mps/issue/job003412/
|
||||
|
||||
#. It is no longer possible for the "ramp" allocation pattern,
|
||||
:c:func:`mps_alloc_pattern_ramp()`, to get stuck. Now
|
||||
:c:func:`mps_ap_alloc_pattern_end` reliably clears this pattern.
|
||||
See job003454_.
|
||||
|
||||
.. _job003454: https://www.ravenbrook.com/project/mps/issue/job003454/
|
||||
|
||||
#. The build system now correctly detects the FreeBSD operating system
|
||||
running on the x86-64 architecture, for FreeBSD version 9.1 or
|
||||
later. See job003473_.
|
||||
|
||||
.. _job003473: https://www.ravenbrook.com/project/mps/issue/job003473/
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ Cautions
|
|||
prompt release of scarce resources. For example, Scheme provides
|
||||
the ``(with-input-from-file)`` procedure which specifies that the
|
||||
created port has :term:`dynamic extent` (and so can be closed as
|
||||
soon as the procedure exits).
|
||||
soon as the procedure exits, even if it is still reachable).
|
||||
|
||||
#. The MPS does not finalize objects in the context of
|
||||
:c:func:`mps_arena_destroy` or :c:func:`mps_pool_destroy`.
|
||||
|
|
@ -185,8 +185,8 @@ Cautions
|
|||
described under :c:func:`mps_pool_destroy`, but the objects do
|
||||
not get finalized.
|
||||
|
||||
The only reliable way to ensure that all finalizable object
|
||||
gets finalized is to maintain a table of :term:`weak
|
||||
The only reliable way to ensure that all finalizable objects
|
||||
are finalized is to maintain a table of :term:`weak
|
||||
references (1)` to all such objects. The weak references don't
|
||||
prevent the objects from being finalized, but you can iterate
|
||||
over the list at an appropriate point and finalize any
|
||||
|
|
|
|||
|
|
@ -205,11 +205,11 @@ Instead, we recommend this approach::
|
|||
struct foo *fp;
|
||||
res = mps_alloc(&p, pool, sizeof(struct foo));
|
||||
if(res) /* handle error case */;
|
||||
fp = (struct foo *)p;
|
||||
fp = p;
|
||||
|
||||
This is portable because conversion from ``void *`` to any other
|
||||
:term:`object pointer` type is defined by :ref:`ISO/IEC 9899:1990
|
||||
<ISO90>` §6.3.2.3.1.
|
||||
This has defined behaviour because conversion from ``void *`` to any
|
||||
other :term:`object pointer` type is defined by :ref:`ISO/IEC
|
||||
9899:1990 <ISO90>` §6.3.2.3.1.
|
||||
|
||||
|
||||
.. index::
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ allowing the MPS to detect whether they have changed.
|
|||
|
||||
The :term:`root mode` for :term:`protectable roots`. This tells
|
||||
the MPS that it may place a :term:`barrier (1)` on any
|
||||
:term:`page` which any part of the :term:`root` covers. No
|
||||
:term:`page` containing any part of the :term:`root`. No
|
||||
:term:`format method` or :term:`scan method` (except for the one
|
||||
for this root) may write data in this root. They may read it.
|
||||
|
||||
|
|
@ -514,6 +514,28 @@ Root interface
|
|||
The registered root description persists until it is destroyed by
|
||||
calling :c:func:`mps_root_destroy`.
|
||||
|
||||
.. _topic-root-type-pun:
|
||||
|
||||
.. warning::
|
||||
|
||||
The ``base`` argument has type ``mps_addr_t *`` (a typedef for
|
||||
``void **``) but the table of references most likely has some
|
||||
other pointer type, ``my_object *`` say. It is tempting to
|
||||
write::
|
||||
|
||||
mps_root_create_table(..., (mps_addr_t *)my_table, ...)
|
||||
|
||||
but this is :term:`type punning`, and its behaviour is not
|
||||
defined in ANSI/ISO Standard C. (GCC and Clang have a warning
|
||||
flag ``-Wstrict-aliasing`` which detects some errors of this
|
||||
form.)
|
||||
|
||||
To ensure well-defined behaviour, the pointer must be
|
||||
converted via ``void *`` (or via :c:type:`mps_addr_t`, which
|
||||
is a typedef for ``void *``), like this::
|
||||
|
||||
mps_addr_t base = my_table;
|
||||
mps_root_create_table(..., base, ...)
|
||||
|
||||
.. c:function:: mps_res_t mps_root_create_table_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_word_t mask)
|
||||
|
||||
|
|
@ -558,13 +580,17 @@ Root interface
|
|||
|
||||
mps_res_t res;
|
||||
mps_root_t root;
|
||||
mps_addr_t base = symtab;
|
||||
res = mps_root_create_table_masked(&root, arena,
|
||||
mps_rank_exact(),
|
||||
(mps_rm_t)0,
|
||||
symtab, symtab_size * 2,
|
||||
base, symtab_size * 2,
|
||||
(mps_word_t)TAG_MASK);
|
||||
if (res != MPS_RES_OK) errror("can't create symtab root");
|
||||
|
||||
.. warning::
|
||||
|
||||
See the warning for :c:func:`mps_root_create_table` above.
|
||||
|
||||
.. c:function:: void mps_root_destroy(mps_root_t root)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ region to be scanned. They must carry out the following steps:
|
|||
a pointer to a location containing the reference.
|
||||
|
||||
#. If :c:func:`MPS_FIX2` returns a :term:`result code` other than
|
||||
:c:func:`MPS_RES_OK`, return this result code from the scanning
|
||||
:c:macro:`MPS_RES_OK`, return this result code from the scanning
|
||||
function as soon as practicable.
|
||||
|
||||
#. If :c:func:`MPS_FIX2` returns :c:macro:`MPS_RES_OK`, it may have
|
||||
|
|
|
|||
|
|
@ -169,6 +169,6 @@ int main(void)
|
|||
stackpointer=&m; /* hack to get stack pointer */
|
||||
|
||||
easy_tramp(test);
|
||||
report("result", "unknown");
|
||||
pass();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ static void test(void)
|
|||
|
||||
for (j = 1; j < 100; j++) {
|
||||
comment("%i of 100", j);
|
||||
p = allocdumb(ap, sizeof(mps_ld_s));
|
||||
p = allocdumb(ap, sizeof(mycell));
|
||||
ld = (mps_ld_t) getdata(p);
|
||||
|
||||
b = a;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ function/1.c
|
|||
% function/3.c -- interactive test, can't run unattended
|
||||
% function/4.c -- interactive test, can't run unattended
|
||||
function/5.c
|
||||
% function/6.c -- job003494
|
||||
function/6.c
|
||||
function/7.c
|
||||
% function/8.c -- tries to exhaust memory by mps_arena_create
|
||||
function/9.c
|
||||
|
|
@ -48,12 +48,12 @@ function/42.c
|
|||
function/43.c
|
||||
function/44.c
|
||||
function/45.c
|
||||
% function/46.c -- report("result", "unknown"); @@@@
|
||||
function/46.c
|
||||
function/47.c
|
||||
function/48.c
|
||||
function/49.c
|
||||
function/50.c
|
||||
% function/51.c -- would pass if we allowed iter = 4 @@@@
|
||||
% function/51.c -- job003739
|
||||
function/52.c
|
||||
function/53.c
|
||||
function/55.c
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue