Catch-up merge from masters.

Copied from Perforce
 Change: 188921
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2016-01-19 16:22:39 +00:00
parent bdc1a92a18
commit a2f78d0df6
154 changed files with 3259 additions and 2100 deletions

View file

@ -73,7 +73,7 @@ install: @INSTALL_TARGET@
test-make-build:
$(MAKE) $(TARGET_OPTS) testci
$(MAKE) -C code -f anan$(MPS_BUILD_NAME).gmk VARIETY=cool clean testansi
$(MAKE) -C code -f anan$(MPS_BUILD_NAME).gmk VARIETY=cool CFLAGS="-DCONFIG_POLL_NONE" clean testpoll
$(MAKE) -C code -f anan$(MPS_BUILD_NAME).gmk VARIETY=cool CFLAGS="-DCONFIG_POLL_NONE" clean testpollnone
test-xcode-build:
$(XCODEBUILD) -config Debug -target testci

View file

@ -10,7 +10,9 @@ lii3gc
lii6gc
lii6ll
w3i3mv
w3i3pc
w3i6mv
w3i6pc
xci3gc
xci6ll
# Visual Studio junk

View file

@ -45,14 +45,14 @@ static mps_ap_t ap;
static mps_addr_t exactRoots[exactRootsCOUNT];
static mps_addr_t ambigRoots[ambigRootsCOUNT];
static size_t scale; /* Overall scale factor. */
static unsigned long nCollsStart;
static unsigned long nCollsDone;
/* report -- report statistics from any messages */
static void report(mps_arena_t arena)
{
static int nCollsStart = 0;
static int nCollsDone = 0;
mps_message_type_t type;
while(mps_message_queue_type(&type, arena)) {
@ -62,7 +62,7 @@ static void report(mps_arena_t arena)
if (type == mps_message_type_gc_start()) {
nCollsStart += 1;
printf("\n{\n Collection %d started. Because:\n", nCollsStart);
printf("\n{\n Collection %lu started. Because:\n", nCollsStart);
printf(" %s\n", mps_message_gc_start_why(arena, message));
printf(" clock: %"PRIuLONGEST"\n", (ulongest_t)mps_message_clock(arena, message));
@ -74,7 +74,7 @@ static void report(mps_arena_t arena)
condemned = mps_message_gc_condemned_size(arena, message);
not_condemned = mps_message_gc_not_condemned_size(arena, message);
printf("\n Collection %d finished:\n", nCollsDone);
printf("\n Collection %lu finished:\n", nCollsDone);
printf(" live %"PRIuLONGEST"\n", (ulongest_t)live);
printf(" condemned %"PRIuLONGEST"\n", (ulongest_t)condemned);
printf(" not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned);
@ -94,10 +94,12 @@ static void report(mps_arena_t arena)
static mps_addr_t make(size_t rootsCount)
{
static unsigned long calls = 0;
size_t length = rnd() % (scale * avLEN);
size_t size = (length+2) * sizeof(mps_word_t);
mps_addr_t p;
mps_res_t res;
++ calls;
do {
MPS_RESERVE_BLOCK(res, p, ap, size);
@ -167,6 +169,8 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
/* create an ap, and leave it busy */
die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy");
nCollsStart = 0;
nCollsDone = 0;
collections = 0;
rampSwitch = rampSIZE;
die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)");
@ -174,20 +178,18 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
ramping = 1;
objs = 0;
while (collections < collectionsCOUNT) {
mps_word_t c;
size_t r;
c = mps_collections(arena);
if (collections != c) {
report(arena);
if (collections != nCollsStart) {
if (!described) {
die(ArenaDescribe(arena, mps_lib_get_stdout(), 0), "ArenaDescribe");
described = TRUE;
}
collections = c;
report(arena);
collections = nCollsStart;
printf("%lu objects (mps_collections says: %"PRIuLONGEST")\n", objs,
(ulongest_t)c);
printf("%lu objects (nCollsStart=%"PRIuLONGEST")\n", objs,
(ulongest_t)collections);
/* test mps_arena_has_addr */
{

View file

@ -59,33 +59,9 @@ static mps_gen_param_s testChain[genCOUNT] = {
static mps_addr_t exactRoots[exactRootsCOUNT];
static mps_addr_t ambigRoots[ambigRootsCOUNT];
/* report - report statistics from any terminated GCs */
static void report(mps_arena_t arena)
{
mps_message_t message;
static int nCollections = 0;
while (mps_message_get(&message, arena, mps_message_type_gc())) {
size_t live, condemned, not_condemned;
live = mps_message_gc_live_size(arena, message);
condemned = mps_message_gc_condemned_size(arena, message);
not_condemned = mps_message_gc_not_condemned_size(arena, message);
printf("\nCollection %d finished:\n", ++nCollections);
printf("live %"PRIuLONGEST"\n", (ulongest_t)live);
printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned);
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned);
mps_message_discard(arena, message);
}
}
static mps_word_t collections;
static mps_arena_t arena;
static mps_fmt_t format;
static mps_chain_t chain;
static mps_root_t exactRoot, ambigRoot;
static unsigned long objs = 0;
@ -123,32 +99,6 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
}
/* init -- initialize roots and chain */
static void init(void)
{
size_t i;
die(dylan_fmt(&format, arena), "fmt_create");
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
for(i = 0; i < exactRootsCOUNT; ++i)
exactRoots[i] = objNULL;
for(i = 0; i < ambigRootsCOUNT; ++i)
ambigRoots[i] = rnd_addr();
die(mps_root_create_table_masked(&exactRoot, arena,
mps_rank_exact(), (mps_rm_t)0,
&exactRoots[0], exactRootsCOUNT,
(mps_word_t)1),
"root_create_table(exact)");
die(mps_root_create_table(&ambigRoot, arena,
mps_rank_ambig(), (mps_rm_t)0,
&ambigRoots[0], ambigRootsCOUNT),
"root_create_table(ambig)");
}
/* churn -- create an object and install into roots */
static void churn(mps_ap_t ap, size_t roots_count)
@ -207,10 +157,11 @@ static void *kid_thread(void *arg)
/* test -- the body of the test */
static void test_pool(mps_pool_t pool, size_t roots_count, int mode)
static void test_pool(const char *name, mps_pool_t pool, size_t roots_count,
int mode)
{
size_t i;
mps_word_t collections, rampSwitch;
mps_word_t rampSwitch;
mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp();
int ramping;
mps_ap_t ap, busy_ap;
@ -219,8 +170,12 @@ static void test_pool(mps_pool_t pool, size_t roots_count, int mode)
closure_s cl;
int walked = FALSE, ramped = FALSE;
printf("\n------ mode: %s pool: %s-------\n",
mode == ModeWALK ? "WALK" : "COMMIT", name);
cl.pool = pool;
cl.roots_count = roots_count;
collections = 0;
for (i = 0; i < NELEMS(kids); ++i)
testthr_create(&kids[i], kid_thread, &cl);
@ -231,72 +186,85 @@ static void test_pool(mps_pool_t pool, size_t roots_count, int mode)
/* create an ap, and leave it busy */
die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy");
collections = 0;
rampSwitch = rampSIZE;
die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)");
die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)");
ramping = 1;
while (collections < collectionsCOUNT) {
mps_word_t c;
size_t r;
mps_message_type_t type;
c = mps_collections(arena);
if (mps_message_queue_type(&type, arena)) {
mps_message_t msg;
mps_bool_t b = mps_message_get(&msg, arena, type);
Insist(b); /* we just checked there was one */
if (collections != c) {
collections = c;
printf("\nCollection %lu started, %lu objects, committed=%lu.\n",
(unsigned long)c, objs, (unsigned long)mps_arena_committed(arena));
report(arena);
if (type == mps_message_type_gc()) {
size_t live = mps_message_gc_live_size(arena, msg);
size_t condemned = mps_message_gc_condemned_size(arena, msg);
size_t not_condemned = mps_message_gc_not_condemned_size(arena, msg);
for (i = 0; i < exactRootsCOUNT; ++i)
cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]),
"all roots check");
printf("\nCollection %lu finished:\n", collections++);
printf("live %"PRIuLONGEST"\n", (ulongest_t)live);
printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned);
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned);
if (mode == ModeWALK && collections >= collectionsCOUNT / 2 && !walked) {
unsigned long object_count = 0;
mps_arena_park(arena);
mps_arena_formatted_objects_walk(arena, test_stepper, &object_count, 0);
mps_arena_release(arena);
printf("stepped on %lu objects.\n", object_count);
walked = TRUE;
}
if (collections >= rampSwitch && !ramped) {
int begin_ramp = !ramping
|| /* Every other time, switch back immediately. */ (collections & 1);
} else if (type == mps_message_type_gc_start()) {
printf("\nCollection %lu started, %lu objects, committed=%lu.\n",
(unsigned long)collections, objs,
(unsigned long)mps_arena_committed(arena));
rampSwitch += rampSIZE;
if (ramping) {
die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)");
die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)");
ramping = 0;
/* kill half of the roots */
for(i = 0; i < exactRootsCOUNT; i += 2) {
if (exactRoots[i] != objNULL) {
cdie(dylan_check(exactRoots[i]), "ramp kill check");
exactRoots[i] = objNULL;
for (i = 0; i < exactRootsCOUNT; ++i)
cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]),
"all roots check");
if (mode == ModeWALK && collections >= collectionsCOUNT / 2 && !walked)
{
unsigned long count = 0;
mps_arena_park(arena);
mps_arena_formatted_objects_walk(arena, test_stepper, &count, 0);
mps_arena_release(arena);
printf("stepped on %lu objects.\n", count);
walked = TRUE;
}
if (collections >= rampSwitch && !ramped) {
/* Every other time, switch back immediately. */
int begin_ramp = !ramping || (collections & 1);
rampSwitch += rampSIZE;
if (ramping) {
die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)");
die(mps_ap_alloc_pattern_end(busy_ap, ramp),
"pattern end (busy_ap)");
ramping = 0;
/* kill half of the roots */
for(i = 0; i < exactRootsCOUNT; i += 2) {
if (exactRoots[i] != objNULL) {
cdie(dylan_check(exactRoots[i]), "ramp kill check");
exactRoots[i] = objNULL;
}
}
}
if (begin_ramp) {
die(mps_ap_alloc_pattern_begin(ap, ramp),
"pattern rebegin (ap)");
die(mps_ap_alloc_pattern_begin(busy_ap, ramp),
"pattern rebegin (busy_ap)");
ramping = 1;
}
}
if (begin_ramp) {
die(mps_ap_alloc_pattern_begin(ap, ramp),
"pattern rebegin (ap)");
die(mps_ap_alloc_pattern_begin(busy_ap, ramp),
"pattern rebegin (busy_ap)");
ramping = 1;
}
ramped = TRUE;
}
ramped = TRUE;
mps_message_discard(arena, msg);
}
churn(ap, roots_count);
r = (size_t)rnd();
if (r % initTestFREQ == 0)
*(int*)busy_init = -1; /* check that the buffer is still there */
{
size_t r = (size_t)rnd();
if (r % initTestFREQ == 0)
*(int*)busy_init = -1; /* check that the buffer is still there */
}
if (objs % 1024 == 0) {
report(arena);
putchar('.');
fflush(stdout);
}
@ -312,6 +280,9 @@ static void test_pool(mps_pool_t pool, size_t roots_count, int mode)
static void test_arena(int mode)
{
size_t i;
mps_fmt_t format;
mps_chain_t chain;
mps_thr_t thread;
mps_root_t reg_root;
mps_pool_t amc_pool, amcz_pool;
@ -325,7 +296,25 @@ static void test_arena(int mode)
if (mode == ModeCOMMIT)
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
mps_message_type_enable(arena, mps_message_type_gc());
init();
mps_message_type_enable(arena, mps_message_type_gc_start());
die(dylan_fmt(&format, arena), "fmt_create");
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
for(i = 0; i < exactRootsCOUNT; ++i)
exactRoots[i] = objNULL;
for(i = 0; i < ambigRootsCOUNT; ++i)
ambigRoots[i] = rnd_addr();
die(mps_root_create_table_masked(&exactRoot, arena,
mps_rank_exact(), (mps_rm_t)0,
&exactRoots[0], exactRootsCOUNT,
(mps_word_t)1),
"root_create_table(exact)");
die(mps_root_create_table(&ambigRoot, arena,
mps_rank_ambig(), (mps_rm_t)0,
&ambigRoots[0], ambigRootsCOUNT),
"root_create_table(ambig)");
die(mps_thread_reg(&thread, arena), "thread_reg");
die(mps_root_create_reg(&reg_root, arena, mps_rank_ambig(), 0, thread,
mps_stack_scan_ambig, marker, 0), "root_create");
@ -335,8 +324,8 @@ static void test_arena(int mode)
die(mps_pool_create(&amcz_pool, arena, mps_class_amcz(), format, chain),
"pool_create(amcz)");
test_pool(amc_pool, exactRootsCOUNT, mode);
test_pool(amcz_pool, 0, mode);
test_pool("AMC", amc_pool, exactRootsCOUNT, mode);
test_pool("AMCZ", amcz_pool, 0, mode);
mps_arena_park(arena);
mps_pool_destroy(amc_pool);
@ -347,7 +336,6 @@ static void test_arena(int mode)
mps_root_destroy(ambigRoot);
mps_chain_destroy(chain);
mps_fmt_destroy(format);
report(arena);
mps_arena_destroy(arena);
}
@ -367,18 +355,18 @@ int main(int argc, char *argv[])
* 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.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*
* 3. Redistributions in any form must be accompanied by information on how
* to obtain complete source code for this software and any accompanying
* software that uses this software. The source code must either be
@ -389,7 +377,7 @@ int main(int argc, char *argv[])
* include source code for modules or files that typically accompany the
* major components of the operating system on which the executable file
* runs.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR

View file

@ -16,9 +16,8 @@ MPMPF = \
[than] \
[vman]
!INCLUDE commpre.nmk
!INCLUDE mv.nmk
!INCLUDE commpost.nmk
!INCLUDE comm.nmk
# C. COPYRIGHT AND LICENSE

View file

@ -41,6 +41,7 @@ Bool ArenaGrainSizeCheck(Size size)
static void ArenaTrivCompact(Arena arena, Trace trace);
static void arenaFreePage(Arena arena, Addr base, Pool pool);
static void arenaFreeLandFinish(Arena arena);
/* ArenaTrivDescribe -- produce trivial description of an arena */
@ -85,7 +86,6 @@ DEFINE_CLASS(AbstractArenaClass, class)
class->varargs = ArgTrivVarargs;
class->init = NULL;
class->finish = NULL;
class->reserved = NULL;
class->purgeSpare = ArenaNoPurgeSpare;
class->extend = ArenaNoExtend;
class->grow = ArenaNoGrow;
@ -113,7 +113,6 @@ Bool ArenaClassCheck(ArenaClass class)
CHECKL(FUNCHECK(class->varargs));
CHECKL(FUNCHECK(class->init));
CHECKL(FUNCHECK(class->finish));
CHECKL(FUNCHECK(class->reserved));
CHECKL(FUNCHECK(class->purgeSpare));
CHECKL(FUNCHECK(class->extend));
CHECKL(FUNCHECK(class->grow));
@ -142,9 +141,12 @@ Bool ArenaCheck(Arena arena)
CHECKD(Reservoir, &arena->reservoirStruct);
}
/* Can't check that limit>=size because we may call ArenaCheck */
/* while the size is being adjusted. */
/* .reserved.check: Would like to check that arena->committed <=
* arena->reserved, but that isn't always true in the VM arena.
* Memory is committed early on when VMChunkCreate calls vmArenaMap
* (to provide a place for the chunk struct) but is not recorded as
* reserved until ChunkInit calls ArenaChunkInsert.
*/
CHECKL(arena->committed <= arena->commitLimit);
CHECKL(arena->spareCommitted <= arena->committed);
@ -206,6 +208,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
arena->class = class;
arena->reserved = (Size)0;
arena->committed = (Size)0;
/* commitLimit may be overridden by init (but probably not */
/* as there's not much point) */
@ -236,10 +239,11 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
arena->sig = ArenaSig;
AVERT(Arena, arena);
/* Initialise a pool to hold the arena's CBS blocks. This pool can't be
allowed to extend itself using ArenaAlloc because it is used during
ArenaAlloc, so MFSExtendSelf is set to FALSE. Failures to extend are
handled where the Land is used. */
/* Initialise a pool to hold the CBS blocks for the arena's free
* land. This pool can't be allowed to extend itself using
* ArenaAlloc because it is used to implement ArenaAlloc, so
* MFSExtendSelf is set to FALSE. Failures to extend are handled
* where the free land is used: see arenaFreeLandInsertExtend. */
MPS_ARGS_BEGIN(piArgs) {
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSZonedBlockStruct));
@ -251,18 +255,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
if (res != ResOK)
goto failMFSInit;
/* Initialise the freeLand. */
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
res = LandInit(ArenaFreeLand(arena), CBSZonedLandClassGet(), arena,
ArenaGrainSize(arena), arena, liArgs);
} MPS_ARGS_END(liArgs);
AVER(res == ResOK); /* no allocation, no failure expected */
if (res != ResOK)
goto failLandInit;
/* Note that although freeLand is initialised, it doesn't have any memory
for its blocks, so hasFreeLand remains FALSE until later. */
/* initialize the reservoir, <design/reservoir/> */
res = ReservoirInit(&arena->reservoirStruct, arena);
if (res != ResOK)
@ -272,8 +264,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
return ResOK;
failReservoirInit:
LandFinish(ArenaFreeLand(arena));
failLandInit:
PoolFinish(ArenaCBSBlockPool(arena));
failMFSInit:
GlobalsFinish(ArenaGlobals(arena));
@ -299,6 +289,43 @@ ARG_DEFINE_KEY(ARENA_SIZE, Size);
ARG_DEFINE_KEY(ARENA_GRAIN_SIZE, Size);
ARG_DEFINE_KEY(ARENA_ZONED, Bool);
static Res arenaFreeLandInit(Arena arena)
{
Res res;
AVERT(Arena, arena);
AVER(!arena->hasFreeLand);
AVER(arena->primary != NULL);
/* Initialise the free land. */
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
res = LandInit(ArenaFreeLand(arena), CBSZonedLandClassGet(), arena,
ArenaGrainSize(arena), arena, liArgs);
} MPS_ARGS_END(liArgs);
AVER(res == ResOK); /* no allocation, no failure expected */
if (res != ResOK)
goto failLandInit;
/* With the primary chunk initialised we can add page memory to the
* free land that describes the free address space in the primary
* chunk. */
res = ArenaFreeLandInsert(arena,
PageIndexBase(arena->primary,
arena->primary->allocBase),
arena->primary->limit);
if (res != ResOK)
goto failFreeLandInsert;
arena->hasFreeLand = TRUE;
return ResOK;
failFreeLandInsert:
LandFinish(ArenaFreeLand(arena));
failLandInit:
return res;
}
Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
{
Arena arena;
@ -324,15 +351,9 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
goto failStripeSize;
}
/* With the primary chunk initialised we can add page memory to the freeLand
that describes the free address space in the primary chunk. */
res = ArenaFreeLandInsert(arena,
PageIndexBase(arena->primary,
arena->primary->allocBase),
arena->primary->limit);
res = arenaFreeLandInit(arena);
if (res != ResOK)
goto failPrimaryLand;
arena->hasFreeLand = TRUE;
goto failFreeLandInit;
res = ControlInit(arena);
if (res != ResOK)
@ -349,7 +370,8 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
failGlobalsCompleteCreate:
ControlFinish(arena);
failControlInit:
failPrimaryLand:
arenaFreeLandFinish(arena);
failFreeLandInit:
failStripeSize:
(*class->finish)(arena);
failInit:
@ -390,6 +412,20 @@ static void arenaMFSPageFreeVisitor(Pool pool, Addr base, Size size,
arenaFreePage(PoolArena(pool), base, pool);
}
static void arenaFreeLandFinish(Arena arena)
{
AVERT(Arena, arena);
AVER(arena->hasFreeLand);
/* The CBS block pool can't free its own memory via ArenaFree because
* that would use the free land. */
MFSFinishTracts(ArenaCBSBlockPool(arena), arenaMFSPageFreeVisitor,
UNUSED_POINTER, UNUSED_SIZE);
arena->hasFreeLand = FALSE;
LandFinish(ArenaFreeLand(arena));
}
void ArenaDestroy(Arena arena)
{
AVERT(Arena, arena);
@ -399,19 +435,11 @@ void ArenaDestroy(Arena arena)
/* Empty the reservoir - see <code/reserv.c#reservoir.finish> */
ReservoirSetLimit(ArenaReservoir(arena), 0);
arena->poolReady = FALSE;
ControlFinish(arena);
/* We must tear down the freeLand before the chunks, because pages
containing CBS blocks might be allocated in those chunks. */
AVER(arena->hasFreeLand);
arena->hasFreeLand = FALSE;
LandFinish(ArenaFreeLand(arena));
/* The CBS block pool can't free its own memory via ArenaFree because
that would use the freeLand. */
MFSFinishTracts(ArenaCBSBlockPool(arena), arenaMFSPageFreeVisitor,
UNUSED_POINTER, UNUSED_SIZE);
/* We must tear down the free land before the chunks, because pages
* containing CBS blocks might be allocated in those chunks. */
arenaFreeLandFinish(arena);
/* Call class-specific finishing. This will call ArenaFinish. */
(*arena->class->finish)(arena);
@ -427,6 +455,7 @@ Res ControlInit(Arena arena)
Res res;
AVERT(Arena, arena);
AVER(!arena->poolReady);
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, CONTROL_EXTEND_BY);
res = PoolInit(MVPool(&arena->controlPoolStruct), arena,
@ -444,6 +473,7 @@ Res ControlInit(Arena arena)
void ControlFinish(Arena arena)
{
AVERT(Arena, arena);
AVER(arena->poolReady);
arena->poolReady = FALSE;
PoolFinish(MVPool(&arena->controlPoolStruct));
}
@ -454,7 +484,6 @@ void ControlFinish(Arena arena)
Res ArenaDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
{
Res res;
Size reserved;
if (!TESTT(Arena, arena))
return ResFAIL;
@ -476,20 +505,9 @@ Res ArenaDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
return res;
}
/* Note: this Describe clause calls a function */
reserved = ArenaReserved(arena);
res = WriteF(stream, depth + 2,
"reserved $W <-- "
"total size of address-space reserved\n",
(WriteFW)reserved,
NULL);
if (res != ResOK)
return res;
res = WriteF(stream, depth + 2,
"committed $W <-- "
"total bytes currently stored (in RAM or swap)\n",
(WriteFW)arena->committed,
"reserved $W\n", (WriteFW)arena->reserved,
"committed $W\n", (WriteFW)arena->committed,
"commitLimit $W\n", (WriteFW)arena->commitLimit,
"spareCommitted $W\n", (WriteFW)arena->spareCommitted,
"spareCommitLimit $W\n", (WriteFW)arena->spareCommitLimit,
@ -669,7 +687,10 @@ Res ControlDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
}
/* ArenaChunkInsert -- insert chunk into arena's chunk tree and ring */
/* ArenaChunkInsert -- insert chunk into arena's chunk tree and ring,
* update the total reserved address space, and set the primary chunk
* if not already set.
*/
void ArenaChunkInsert(Arena arena, Chunk chunk) {
Bool inserted;
@ -687,6 +708,8 @@ void ArenaChunkInsert(Arena arena, Chunk chunk) {
arena->chunkTree = updatedTree;
RingAppend(&arena->chunkRing, &chunk->arenaRing);
arena->reserved += ChunkReserved(chunk);
/* As part of the bootstrap, the first created chunk becomes the primary
chunk. This step allows ArenaFreeLandInsert to allocate pages. */
if (arena->primary == NULL)
@ -694,6 +717,31 @@ void ArenaChunkInsert(Arena arena, Chunk chunk) {
}
/* ArenaChunkRemoved -- chunk was removed from the arena and is being
* finished, so update the total reserved address space, and unset the
* primary chunk if necessary.
*/
void ArenaChunkRemoved(Arena arena, Chunk chunk)
{
Size size;
AVERT(Arena, arena);
AVERT(Chunk, chunk);
size = ChunkReserved(chunk);
AVER(arena->reserved >= size);
arena->reserved -= size;
if (chunk == arena->primary) {
/* The primary chunk must be the last chunk to be removed. */
AVER(RingIsSingle(&arena->chunkRing));
AVER(arena->reserved == 0);
arena->primary = NULL;
}
}
/* arenaAllocPage -- allocate one page from the arena
*
* This is a primitive allocator used to allocate pages for the arena
@ -781,7 +829,7 @@ static Res arenaExtendCBSBlockPool(Range pageRangeReturn, Arena arena)
return res;
MFSExtend(ArenaCBSBlockPool(arena), pageBase, ArenaGrainSize(arena));
RangeInit(pageRangeReturn, pageBase, AddrAdd(pageBase, ArenaGrainSize(arena)));
RangeInitSize(pageRangeReturn, pageBase, ArenaGrainSize(arena));
return ResOK;
}
@ -801,15 +849,19 @@ static void arenaExcludePage(Arena arena, Range pageRange)
}
/* arenaLandInsert -- add range to arena's land, maybe extending block pool
/* arenaFreeLandInsertExtend -- add range to arena's free land, maybe
* extending block pool
*
* The arena's land can't get memory in the usual way because it is
* used in the basic allocator, so we allocate pages specially.
* The arena's free land can't get memory for its block pool in the
* usual way (via ArenaAlloc), because it is the mechanism behind
* ArenaAlloc! So we extend the block pool via a back door (see
* arenaExtendCBSBlockPool).
*
* Only fails if it can't get a page for the block pool.
*/
static Res arenaLandInsert(Range rangeReturn, Arena arena, Range range)
static Res arenaFreeLandInsertExtend(Range rangeReturn, Arena arena,
Range range)
{
Res res;
@ -835,16 +887,18 @@ static Res arenaLandInsert(Range rangeReturn, Arena arena, Range range)
}
/* ArenaFreeLandInsert -- add range to arena's land, maybe stealing memory
/* arenaFreeLandInsertSteal -- add range to arena's free land, maybe
* stealing memory
*
* See arenaLandInsert. This function may only be applied to mapped
* pages and may steal them to store Land nodes if it's unable to
* allocate space for CBS blocks.
* See arenaFreeLandInsertExtend. This function may only be applied to
* mapped pages and may steal them to store Land nodes if it's unable
* to allocate space for CBS blocks.
*
* IMPORTANT: May update rangeIO.
*/
static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
static void arenaFreeLandInsertSteal(Range rangeReturn, Arena arena,
Range rangeIO)
{
Res res;
@ -852,7 +906,7 @@ static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
AVERT(Arena, arena);
AVERT(Range, rangeIO);
res = arenaLandInsert(rangeReturn, arena, rangeIO);
res = arenaFreeLandInsertExtend(rangeReturn, arena, rangeIO);
if (res != ResOK) {
Addr pageBase;
@ -881,7 +935,8 @@ static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
}
/* ArenaFreeLandInsert -- add range to arena's land, maybe extending block pool
/* ArenaFreeLandInsert -- add range to arena's free land, maybe extending
* block pool
*
* The inserted block of address space may not abut any existing block.
* This restriction ensures that we don't coalesce chunks and allocate
@ -896,7 +951,7 @@ Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
AVERT(Arena, arena);
RangeInit(&range, base, limit);
res = arenaLandInsert(&oldRange, arena, &range);
res = arenaFreeLandInsertExtend(&oldRange, arena, &range);
if (res != ResOK)
return res;
@ -911,7 +966,8 @@ Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
}
/* ArenaFreeLandDelete -- remove range from arena's land, maybe extending block pool
/* ArenaFreeLandDelete -- remove range from arena's free land, maybe
* extending block pool
*
* This is called from ChunkFinish in order to remove address space from
* the arena.
@ -1003,7 +1059,7 @@ static Res arenaAllocFromLand(Tract *tractReturn, ZoneSet zones, Bool high,
failMark:
{
Res insertRes = arenaLandInsert(&oldRange, arena, &range);
Res insertRes = arenaFreeLandInsertExtend(&oldRange, arena, &range);
AVER(insertRes == ResOK); /* We only just deleted it. */
/* If the insert does fail, we lose some address space permanently. */
}
@ -1215,7 +1271,7 @@ void ArenaFree(Addr base, Size size, Pool pool)
RangeInit(&range, base, limit);
arenaLandInsertSteal(&oldRange, arena, &range); /* may update range */
arenaFreeLandInsertSteal(&oldRange, arena, &range); /* may update range */
(*arena->class->free)(RangeBase(&range), RangeSize(&range), pool);
@ -1231,7 +1287,7 @@ void ArenaFree(Addr base, Size size, Pool pool)
Size ArenaReserved(Arena arena)
{
AVERT(Arena, arena);
return (*arena->class->reserved)(arena);
return arena->reserved;
}
Size ArenaCommitted(Arena arena)

View file

@ -81,8 +81,15 @@ static Bool ClientChunkCheck(ClientChunk clChunk)
ATTRIBUTE_UNUSED
static Bool ClientArenaCheck(ClientArena clientArena)
{
Arena arena;
CHECKS(ClientArena, clientArena);
CHECKD(Arena, ClientArena2Arena(clientArena));
arena = ClientArena2Arena(clientArena);
CHECKD(Arena, arena);
/* See <code/arena.c#.reserved.check> */
CHECKL(arena->committed <= arena->reserved);
CHECKL(arena->spareCommitted == 0);
return TRUE;
}
@ -125,12 +132,13 @@ static Res clientChunkCreate(Chunk *chunkReturn, ClientArena clientArena,
chunk = ClientChunk2Chunk(clChunk);
res = ChunkInit(chunk, arena, alignedBase,
AddrAlignDown(limit, ArenaGrainSize(arena)), boot);
AddrAlignDown(limit, ArenaGrainSize(arena)),
AddrOffset(base, limit), boot);
if (res != ResOK)
goto failChunkInit;
ClientArena2Arena(clientArena)->committed +=
AddrOffset(base, PageIndexBase(chunk, chunk->allocBase));
arena->committed += ChunkPagesToSize(chunk, chunk->allocBase);
BootBlockFinish(boot);
clChunk->sig = ClientChunkSig;
@ -176,8 +184,10 @@ static Res ClientChunkInit(Chunk chunk, BootBlock boot)
static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
{
Arena arena;
Chunk chunk;
ClientChunk clChunk;
Size size;
AVERT(Tree, tree);
AVER(closureP == UNUSED_POINTER);
@ -187,8 +197,15 @@ static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
chunk = ChunkOfTree(tree);
AVERT(Chunk, chunk);
arena = ChunkArena(chunk);
AVERT(Arena, arena);
clChunk = Chunk2ClientChunk(chunk);
AVERT(ClientChunk, clChunk);
AVER(chunk->pages == clChunk->freePages);
size = ChunkPagesToSize(chunk, chunk->allocBase);
AVER(arena->committed >= size);
arena->committed -= size;
clChunk->sig = SigInvalid;
ChunkFinish(chunk);
@ -257,7 +274,7 @@ static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
AVER(base != (Addr)0);
AVERT(ArenaGrainSize, grainSize);
if (size < grainSize * MPS_WORD_SHIFT)
if (size < grainSize * MPS_WORD_WIDTH)
/* Not enough room for a full complement of zones. */
return ResMEMORY;
@ -324,6 +341,10 @@ static void ClientArenaFinish(Arena arena)
clientArena->sig = SigInvalid;
/* Destroying the chunks should leave nothing behind. */
AVER(arena->reserved == 0);
AVER(arena->committed == 0);
ArenaFinish(arena); /* <code/arena.c#finish.caller> */
}
@ -348,27 +369,6 @@ static Res ClientArenaExtend(Arena arena, Addr base, Size size)
}
/* ClientArenaReserved -- return the amount of reserved address space */
static Size ClientArenaReserved(Arena arena)
{
Size size;
Ring node, nextNode;
AVERT(Arena, arena);
size = 0;
/* .req.extend.slow */
RING_FOR(node, &arena->chunkRing, nextNode) {
Chunk chunk = RING_ELT(Chunk, arenaRing, node);
AVERT(Chunk, chunk);
size += ChunkSize(chunk);
}
return size;
}
/* ClientArenaPagesMarkAllocated -- Mark the pages allocated */
static Res ClientArenaPagesMarkAllocated(Arena arena, Chunk chunk,
@ -376,9 +376,12 @@ static Res ClientArenaPagesMarkAllocated(Arena arena, Chunk chunk,
Pool pool)
{
Index i;
ClientChunk clChunk;
AVERT(Arena, arena);
AVERT(Chunk, chunk);
clChunk = Chunk2ClientChunk(chunk);
AVERT(ClientChunk, clChunk);
AVER(chunk->allocBase <= baseIndex);
AVER(pages > 0);
AVER(baseIndex + pages <= chunk->pages);
@ -387,15 +390,17 @@ static Res ClientArenaPagesMarkAllocated(Arena arena, Chunk chunk,
for (i = 0; i < pages; ++i)
PageAlloc(chunk, baseIndex + i, pool);
Chunk2ClientChunk(chunk)->freePages -= pages;
arena->committed += ChunkPagesToSize(chunk, pages);
AVER(clChunk->freePages >= pages);
clChunk->freePages -= pages;
return ResOK;
}
/* ClientFree - free a region in the arena */
/* ClientArenaFree - free a region in the arena */
static void ClientFree(Addr base, Size size, Pool pool)
static void ClientArenaFree(Addr base, Size size, Pool pool)
{
Arena arena;
Chunk chunk = NULL; /* suppress "may be used uninitialized" */
@ -436,6 +441,8 @@ static void ClientFree(Addr base, Size size, Pool pool)
AVER(BTIsSetRange(chunk->allocTable, baseIndex, limitIndex));
BTResRange(chunk->allocTable, baseIndex, limitIndex);
AVER(arena->committed >= size);
arena->committed -= size;
clChunk->freePages += pages;
}
@ -451,10 +458,9 @@ DEFINE_ARENA_CLASS(ClientArenaClass, this)
this->varargs = ClientArenaVarargs;
this->init = ClientArenaInit;
this->finish = ClientArenaFinish;
this->reserved = ClientArenaReserved;
this->extend = ClientArenaExtend;
this->pagesMarkAllocated = ClientArenaPagesMarkAllocated;
this->free = ClientFree;
this->free = ClientArenaFree;
this->chunkInit = ClientChunkInit;
this->chunkFinish = ClientChunkFinish;
AVERT(ArenaClass, this);

View file

@ -323,7 +323,8 @@ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
/* Copy VM descriptor into its place in the chunk. */
VMCopy(VMChunkVM(vmChunk), vm);
res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit, boot);
res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit,
VMReserved(VMChunkVM(vmChunk)), boot);
if (res != ResOK)
goto failChunkInit;
@ -560,6 +561,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
res = ArenaInit(arena, class, grainSize, args);
if (res != ResOK)
goto failArenaInit;
arena->reserved = VMReserved(vm);
arena->committed = VMMapped(vm);
/* Copy VM descriptor into its place in the arena. */
@ -640,6 +642,7 @@ static void VMArenaFinish(Arena arena)
RingFinish(&vmArena->spareRing);
/* Destroying the chunks should leave only the arena's own VM. */
AVER(arena->reserved == VMReserved(VMArenaVM(vmArena)));
AVER(arena->committed == VMMapped(VMArenaVM(vmArena)));
vmArena->sig = SigInvalid;
@ -654,25 +657,6 @@ static void VMArenaFinish(Arena arena)
}
/* VMArenaReserved -- return the amount of reserved address space
*
* Add up the reserved space from all the chunks.
*/
static Size VMArenaReserved(Arena arena)
{
Size reserved;
Ring node, next;
reserved = 0;
RING_FOR(node, &arena->chunkRing, next) {
VMChunk vmChunk = Chunk2VMChunk(RING_ELT(Chunk, arenaRing, node));
reserved += VMReserved(VMChunkVM(vmChunk));
}
return reserved;
}
/* vmArenaChunkSize -- choose chunk size for arena extension
*
* .vmchunk.overhead: This code still lacks a proper estimate of
@ -723,7 +707,7 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
chunkSize = vmArenaChunkSize(vmArena, size);
EVENT3(vmArenaExtendStart, size, chunkSize,
VMArenaReserved(VMArena2Arena(vmArena)));
ArenaReserved(VMArena2Arena(vmArena)));
/* .chunk-create.fail: If we fail, try again with a smaller size */
{
@ -737,17 +721,17 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
if (chunkSize < chunkMin)
chunkSize = chunkMin;
res = ResRESOURCE;
for(;; chunkSize = chunkHalf) {
chunkHalf = chunkSize / 2;
sliceSize = chunkHalf / fidelity;
AVER(sliceSize > 0);
/* remove slices, down to chunkHalf but no further */
res = ResRESOURCE;
for(; chunkSize > chunkHalf; chunkSize -= sliceSize) {
if(chunkSize < chunkMin) {
EVENT2(vmArenaExtendFail, chunkMin,
VMArenaReserved(VMArena2Arena(vmArena)));
ArenaReserved(VMArena2Arena(vmArena)));
return res;
}
res = VMChunkCreate(&newChunk, vmArena, chunkSize);
@ -758,7 +742,7 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
}
vmArenaGrow_Done:
EVENT2(vmArenaExtendDone, chunkSize, VMArenaReserved(VMArena2Arena(vmArena)));
EVENT2(vmArenaExtendDone, chunkSize, ArenaReserved(VMArena2Arena(vmArena)));
vmArena->extended(VMArena2Arena(vmArena),
newChunk->base,
AddrOffset(newChunk->base, newChunk->limit));
@ -806,16 +790,23 @@ static Res pageDescMap(VMChunk vmChunk, Index basePI, Index limitPI)
Size before = VMMapped(VMChunkVM(vmChunk));
Arena arena = VMArena2Arena(VMChunkVMArena(vmChunk));
Res res = SparseArrayMap(&vmChunk->pages, basePI, limitPI);
arena->committed += VMMapped(VMChunkVM(vmChunk)) - before;
Size after = VMMapped(VMChunkVM(vmChunk));
AVER(before <= after);
arena->committed += after - before;
return res;
}
static void pageDescUnmap(VMChunk vmChunk, Index basePI, Index limitPI)
{
Size size, after;
Size before = VMMapped(VMChunkVM(vmChunk));
Arena arena = VMArena2Arena(VMChunkVMArena(vmChunk));
SparseArrayUnmap(&vmChunk->pages, basePI, limitPI);
arena->committed += VMMapped(VMChunkVM(vmChunk)) - before;
after = VMMapped(VMChunkVM(vmChunk));
AVER(after <= before);
size = before - after;
AVER(arena->committed >= size);
arena->committed -= size;
}
@ -1144,7 +1135,7 @@ static void VMCompact(Arena arena, Trace trace)
AVERT(VMArena, vmArena);
AVERT(Trace, trace);
vmem1 = VMArenaReserved(arena);
vmem1 = ArenaReserved(arena);
/* Destroy chunks that are completely free, but not the primary
* chunk. See <design/arena/#chunk.delete>
@ -1154,7 +1145,7 @@ static void VMCompact(Arena arena, Trace trace)
{
Size vmem0 = trace->preTraceArenaReserved;
Size vmem2 = VMArenaReserved(arena);
Size vmem2 = ArenaReserved(arena);
/* VMCompact event: emit for all client-requested collections, */
/* plus any others where chunks were gained or lost during the */
@ -1204,7 +1195,6 @@ DEFINE_ARENA_CLASS(VMArenaClass, this)
this->varargs = VMArenaVarargs;
this->init = VMArenaInit;
this->finish = VMArenaFinish;
this->reserved = VMArenaReserved;
this->purgeSpare = VMPurgeSpare;
this->grow = VMArenaGrow;
this->free = VMFree;

View file

@ -19,10 +19,8 @@
*
* TRANSGRESSIONS
*
* .trans.mod: There are several instances where pool structures are
* directly accessed by this module because <code/pool.c> does not provide
* an adequate (or adequately documented) interface. They bear this
* tag.
* .trans.mod: pool->bufferSerial is directly accessed by this module
* because <code/pool.c> does not provide an interface.
*/
#include "mpm.h"
@ -221,7 +219,7 @@ static Res BufferInit(Buffer buffer, BufferClass class,
}
buffer->fillSize = 0.0;
buffer->emptySize = 0.0;
buffer->alignment = pool->alignment; /* .trans.mod */
buffer->alignment = PoolAlignment(pool);
buffer->base = (Addr)0;
buffer->initAtFlip = (Addr)0;
/* In the next three assignments we really mean zero, not NULL, because

View file

@ -1,7 +1,7 @@
/* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .intro: This is a portable implementation of coalescing block
* structures.
@ -1069,7 +1069,7 @@ static Res cbsFindInZones(Bool *foundReturn, Range rangeReturn,
AVERT(CBS, cbs);
AVER(IsLandSubclass(CBSLand(cbs), CBSZonedLandClass));
/* AVERT(ZoneSet, zoneSet); */
AVER(BoolCheck(high));
AVERT(Bool, high);
landFind = high ? cbsFindLast : cbsFindFirst;
splayFind = high ? SplayFindLast : SplayFindFirst;
@ -1208,7 +1208,7 @@ DEFINE_LAND_CLASS(CBSZonedLandClass, class)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -36,7 +36,6 @@
# NOISY if defined and non-empty, causes commands to be emitted
# MPMPF platform-dependent C sources for the "mpm" part
# MPMS assembler sources for the "mpm" part (.s files)
# MPMPS pre-processor assembler sources for the "mpm" part (.S files)
#
# %%PART: When adding a new part, add a new parameter above for the
# files included in the part.
@ -309,12 +308,12 @@ all: $(ALL_TARGETS)
# testci = continuous integration tests, must be known good
# testall = all test cases, for ensuring quality of a release
# testansi = tests that run on the generic ("ANSI") platform
# testpoll = tests that run on the generic platform with CONFIG_POLL_NONE
# testpollnone = tests that run on the generic platform with CONFIG_POLL_NONE
TEST_SUITES=testrun testci testall testansi testpoll
TEST_SUITES=testrun testci testall testansi testpollnone
$(addprefix $(PFM)/$(VARIETY)/,$(TEST_SUITES)): $(TEST_TARGETS)
../tool/testrun.sh "$(PFM)/$(VARIETY)" "$(notdir $@)"
../tool/testrun.sh -s "$(notdir $@)" "$(PFM)/$(VARIETY)"
# These convenience targets allow one to type "make foo" to build target

View file

@ -1,11 +1,330 @@
# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-
# -*- makefile -*-
#
# comm.nmk: COMMON NMAKE FRAGMENT
#
# $Id$
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
#
# DESCRIPTION
#
# Second common makefile fragment for w3*mv.nmk. See commpre.nmk
# This makefile fragment is included in more specific makefiles for
# platforms which use nmake.
#
# %%PART: When adding a new part, add a new parameter for the files included
# in the part
# Parameters:
# PFM platform code, e.g. "w3i3mv"
# PFMDEFS /D options to define platforms preprocessor symbols
# to the compiler. Avoid using this if possible, as it
# prevents the MPS being built with a simple command like
# "cl mps.c".
# MPMCOMMON list of sources which make up the "mpm" part for all
# platforms. Each source is stripped of its .c extension
# and surrounded with [brackets].
# MPMPF as above for the current platform.
# PLINTH as above for the "plinth" part
# AMC as above for the "amc" part
# AMS as above for the "ams" part
# LO as above for the "lo" part
# POOLN as above for the "pooln" part
# SNC as above for the "snc" part
# POOLS as above for all pools included in the target
# MPM as above for the MPMCOMMON + MPMPF + PLINTH + POOLS
# DW as above for the "dw" part
# FMTTEST as above for the "fmttest" part
# FMTSCHEME as above for the "fmtscheme" part
# TESTLIB as above for the "testlib" part
# TESTTHR as above for the "testthr" part
# NOISY if defined, causes command to be emitted
#
#
# EDITING
#
# To add new targets. varieties, and parts:
# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this makefile
# and follow the instructions.
#
# TARGETS
#
#
# %%TARGET: When adding a new target, add it to one of the variables
# in this section. Library components go in LIB_TARGETS.
LIB_TARGETS=mps.lib
# Test cases go in TEST_TARGETS.
TEST_TARGETS=\
abqtest.exe \
airtest.exe \
amcss.exe \
amcsshe.exe \
amcssth.exe \
amsss.exe \
amssshe.exe \
apss.exe \
arenacv.exe \
awlut.exe \
awluthe.exe \
awlutth.exe \
btcv.exe \
bttest.exe \
djbench.exe \
exposet0.exe \
expt825.exe \
finalcv.exe \
finaltest.exe \
fotest.exe \
gcbench.exe \
landtest.exe \
locbwcss.exe \
lockcov.exe \
lockut.exe \
locusss.exe \
locv.exe \
messtest.exe \
mpmss.exe \
mpsicv.exe \
mv2test.exe \
nailboardtest.exe \
poolncv.exe \
qs.exe \
sacss.exe \
segsmss.exe \
steptest.exe \
teletest.exe \
walkt0.exe \
zcoll.exe \
zmess.exe
# Stand-alone programs go in EXTRA_TARGETS if they should always be
# built, or in OPTIONAL_TARGETS if they should only be built if
EXTRA_TARGETS=mpseventcnv.exe mpseventtxt.exe
OPTIONAL_TARGETS=mpseventsql.exe
# This target records programs that we were once able to build but
# can't at the moment:
#
# replay -- depends on the EPVM pool.
UNBUILDABLE_TARGETS=replay.exe
ALL_TARGETS=$(LIB_TARGETS) $(TEST_TARGETS) $(EXTRA_TARGETS)
# PARAMETERS
#
#
# %%PART: When adding a new part, add the sources for the new part here.
MPMCOMMON=\
[abq] \
[arena] \
[arenacl] \
[arenavm] \
[arg] \
[boot] \
[bt] \
[buffer] \
[cbs] \
[dbgpool] \
[dbgpooli] \
[event] \
[failover] \
[format] \
[freelist] \
[global] \
[land] \
[ld] \
[locus] \
[message] \
[meter] \
[mpm] \
[mpsi] \
[nailboard] \
[pool] \
[poolabs] \
[poolmfs] \
[poolmrg] \
[poolmv2] \
[poolmv] \
[protocol] \
[range] \
[ref] \
[reserv] \
[ring] \
[root] \
[sa] \
[sac] \
[seg] \
[shield] \
[splay] \
[ss] \
[table] \
[trace] \
[traceanc] \
[tract] \
[tree] \
[version] \
[vm] \
[walk]
PLINTH = [mpsliban] [mpsioan]
AMC = [poolamc]
AMS = [poolams] [poolamsi]
AWL = [poolawl]
LO = [poollo]
MVFF = [poolmvff]
POOLN = [pooln]
SNC = [poolsnc]
FMTDY = [fmtdy] [fmtno]
FMTTEST = [fmthe] [fmtdy] [fmtno] [fmtdytst]
FMTSCHEME = [fmtscheme]
TESTLIB = [testlib] [getoptl]
TESTTHR = [testthrw3]
POOLS = $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(SNC)
MPM = $(MPMCOMMON) $(MPMPF) $(POOLS) $(PLINTH)
# CHECK PARAMETERS
#
#
# %%PART: When adding a new part, add checks for the parameter with the
# sources for the new part.
!IFNDEF PFM
!ERROR comm.nmk: PFM not defined
!ENDIF
!IFNDEF MPM
!ERROR comm.nmk: MPM not defined
!ENDIF
!IFNDEF MPMCOMMON
!ERROR comm.nmk: MPMCOMMON not defined
!ENDIF
!IFNDEF MPMPF
!ERROR comm.nmk: MPMPF not defined
!ENDIF
!IFNDEF PLINTH
!ERROR comm.nmk: PLINTH not defined
!ENDIF
!IFNDEF LO
!ERROR comm.nmk: LO not defined
!ENDIF
!IFNDEF AMC
!ERROR comm.nmk: AMC not defined
!ENDIF
!IFNDEF AMS
!ERROR comm.nmk: AMS not defined
!ENDIF
!IFNDEF POOLN
!ERROR comm.nmk: POOLN not defined
!ENDIF
!IFNDEF SNC
!ERROR comm.nmk: SNC not defined
!ENDIF
!IFNDEF FMTDY
!ERROR comm.nmk: FMTDY not defined
!ENDIF
!IFNDEF FMTTEST
!ERROR comm.nmk: FMTTEST not defined
!ENDIF
!IFNDEF FMTSCHEME
!ERROR comm.nmk: FMTSCHEME not defined
!ENDIF
!IFNDEF TESTLIB
!ERROR comm.nmk: TESTLIB not defined
!ENDIF
!IFNDEF TESTTHR
!ERROR comm.nmk: TESTTHR not defined
!ENDIF
# DECLARATIONS
!IFDEF NOISY
ECHO = rem
!ELSE
.SILENT:
ECHO = echo
!ENDIF
# C FLAGS
CFLAGSTARGETPRE =
CFLAGSTARGETPOST =
CRTFLAGSHOT =
CRTFLAGSCOOL =
LINKFLAGSHOT =
LINKFLAGSCOOL =
CFLAGSSQLPRE = /nologo $(PFMDEFS)
CFLAGSCOMMONPRE = /nologo $(PFMDEFS) $(CFLAGSTARGETPRE)
CFLAGSSQLPOST =
CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST)
# Flags for use in the variety combinations
CFLAGSHOT = /O2
# (above /O2 (maximise speed) used to be set to /Ox
# (maximise optimisations) in for tool versions before VS 9)
# We used to have /GZ here (stack probe).
# Note that GZ is specific to version 12 of the cl tool. drj 2003-11-04
# It is ignored on earlier versions of the cl tool.
# /GZ here generates a dependency on the C library and when we are
# building a DLL, mpsdy.dll, the linker step will fail (error LNK2001:
# unresolved external symbol __chkesp). See
# http://support.microsoft.com/kb/q191669/
CFLAGSCOOL =
CFLAGSINTERNAL = /Zi
CFLAGSEXTERNAL =
# The combinations of variety
# %%VARIETY: When adding a new variety, define a macro containing the set
# of flags for the new variety.
CFRASH = /DCONFIG_VAR_RASH $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL)
CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL)
CFCOOL = /DCONFIG_VAR_COOL $(CRTFLAGSCOOL) $(CFLAGSCOOL) $(CFLAGSINTERNAL)
# Microsoft documentation is not very clear on the point of using both
# optimization and debug information
# LINKER FLAGS
# %%VARIETY: When adding a new variety, define a macro containing the flags
# for the new variety
LINKER = link
LINKFLAGSCOMMON = /nologo /LARGEADDRESSAWARE
LINKFLAGSINTERNAL = /DEBUG
# ( Internal flags used to be set to /DEBUG:full )
LINKFLAGSEXTERNAL = /RELEASE
LFRASH = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL)
LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL)
LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL)
#LFCV = /PROFILE /DEBUG:full /DEBUGTYPE:cv
# Library manager
# %%VARIETY: When adding a new variety, define a macro containing the flags
# for the new variety
LIBMAN = lib # can't call this LIB - it screws the environment
LIBFLAGSCOMMON =
LIBFLAGSRASH =
LIBFLAGSHOT =
LIBFLAGSCOOL =
# Browser database manager [not used at present]
#BSC = bscmake
#BSCFLAGS = /nologo /n
# == Common definitions ==
# %%PART: When adding a new part, add it here, unless it's platform-specific
# [It is not possible use a macro, like $(PFM), in a substitution,
# hence all parts end up being platform-specific.]
# == Pseudo-targets ==
@ -56,10 +375,10 @@ variety: $(PFM)\$(VARIETY)\$(TARGET)
!ENDIF
!ENDIF
# testrun testci testall testansi testpoll
# testrun testci testall testansi testpollnone
# Runs automated test cases.
testrun testci testall testansi testpoll: $(TEST_TARGETS)
testrun testci testall testansi testpollnone: $(TEST_TARGETS)
!IFDEF VARIETY
..\tool\testrun.bat $(PFM) $(VARIETY) $@
!ELSE
@ -382,18 +701,18 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
# 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.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
#
# 3. Redistributions in any form must be accompanied by information on how
# to obtain complete source code for this software and any accompanying
# software that uses this software. The source code must either be
@ -404,7 +723,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
# include source code for modules or files that typically accompany the
# major components of the operating system on which the executable file
# runs.
#
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR

View file

@ -1,369 +0,0 @@
# commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-1
#
# $Id$
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
#
# DESCRIPTION
#
# .description: This makefile fragment is included in more specific
# makefiles for platforms which use the "mv" builder. This is
# the first of two common makefile fragements (the other is commpost.nmk).
# Alas, due to shortcomings in nmake, it is not possible to use only one
# common fragment.
#
# %%PART: When adding a new part, add a new parameter for the files included
# in the part
# Parameters:
# PFM platform code, e.g. "w3i3mv"
# PFMDEFS /D options to define platforms preprocessor symbols
# to the compiler. Eg "/DOS_NT /DARCH_386 /DBUILD_MVC"
# MPMCOMMON list of sources which make up the "mpm" part for all
# platforms. Each source is stripped of its .c extension
# and surrounded with [brackets].
# MPM as above, plus sources for the "mpm" part for the current
# platform.
# PLINTH as above for the "plinth" part
# AMC as above for the "amc" part
# AMS as above for the "ams" part
# LO as above for the "lo" part
# POOLN as above for the "pooln" part
# SNC as above for the "snc" part
# DW as above for the "dw" part
# FMTTEST as above for the "fmttest" part
# FMTSCHEME as above for the "fmtscheme" part
# TESTLIB as above for the "testlib" part
# TESTTHR as above for the "testthr" part
# NOISY if defined, causes command to be emitted
#
#
# EDITING
#
# To add new targets. varieties, and parts:
# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this makefile
# and follow the instructions.
#
# TARGETS
#
#
# %%TARGET: When adding a new target, add it to one of the variables
# in this section. Library components go in LIB_TARGETS.
LIB_TARGETS=mps.lib
# Test cases go in TEST_TARGETS.
TEST_TARGETS=\
abqtest.exe \
airtest.exe \
amcss.exe \
amcsshe.exe \
amcssth.exe \
amsss.exe \
amssshe.exe \
apss.exe \
arenacv.exe \
awlut.exe \
awluthe.exe \
awlutth.exe \
btcv.exe \
bttest.exe \
djbench.exe \
exposet0.exe \
expt825.exe \
finalcv.exe \
finaltest.exe \
fotest.exe \
gcbench.exe \
landtest.exe \
locbwcss.exe \
lockcov.exe \
lockut.exe \
locusss.exe \
locv.exe \
messtest.exe \
mpmss.exe \
mpsicv.exe \
mv2test.exe \
nailboardtest.exe \
poolncv.exe \
qs.exe \
sacss.exe \
segsmss.exe \
steptest.exe \
teletest.exe \
walkt0.exe \
zcoll.exe \
zmess.exe
# Stand-alone programs go in EXTRA_TARGETS if they should always be
# built, or in OPTIONAL_TARGETS if they should only be built if
EXTRA_TARGETS=mpseventcnv.exe mpseventtxt.exe
OPTIONAL_TARGETS=mpseventsql.exe
# This target records programs that we were once able to build but
# can't at the moment:
#
# replay -- depends on the EPVM pool.
UNBUILDABLE_TARGETS=replay.exe
ALL_TARGETS=$(LIB_TARGETS) $(TEST_TARGETS) $(EXTRA_TARGETS)
# PARAMETERS
#
#
# %%PART: When adding a new part, add the sources for the new part here.
MPMCOMMON=\
[abq] \
[arena] \
[arenacl] \
[arenavm] \
[arg] \
[boot] \
[bt] \
[buffer] \
[cbs] \
[dbgpool] \
[dbgpooli] \
[event] \
[failover] \
[format] \
[freelist] \
[global] \
[land] \
[ld] \
[locus] \
[message] \
[meter] \
[mpm] \
[mpsi] \
[nailboard] \
[pool] \
[poolabs] \
[poolmfs] \
[poolmrg] \
[poolmv2] \
[poolmv] \
[protocol] \
[range] \
[ref] \
[reserv] \
[ring] \
[root] \
[sa] \
[sac] \
[seg] \
[shield] \
[splay] \
[ss] \
[table] \
[trace] \
[traceanc] \
[tract] \
[tree] \
[version] \
[vm] \
[walk]
PLINTH = [mpsliban] [mpsioan]
AMC = [poolamc]
AMS = [poolams] [poolamsi]
AWL = [poolawl]
LO = [poollo]
MVFF = [poolmvff]
POOLN = [pooln]
SNC = [poolsnc]
FMTDY = [fmtdy] [fmtno]
FMTTEST = [fmthe] [fmtdy] [fmtno] [fmtdytst]
FMTSCHEME = [fmtscheme]
TESTLIB = [testlib] [getoptl]
TESTTHR = [testthrw3]
POOLS = $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(SNC)
MPM = $(MPMCOMMON) $(MPMPF) $(POOLS) $(PLINTH)
# CHECK PARAMETERS
#
#
# %%PART: When adding a new part, add checks for the parameter with the
# sources for the new part.
!IFNDEF PFM
!ERROR commpre.nmk: PFM not defined
!ENDIF
!IFNDEF PFMDEFS
!ERROR commpre.nmk: PFMDEFS not defined
!ENDIF
!IFNDEF MPM
!ERROR commpre.nmk: MPM not defined
!ENDIF
!IFNDEF MPMCOMMON
!ERROR commpre.nmk: MPMCOMMON not defined
!ENDIF
!IFNDEF MPMPF
!ERROR commpre.nmk: MPMPF not defined
!ENDIF
!IFNDEF PLINTH
!ERROR commpre.nmk: PLINTH not defined
!ENDIF
!IFNDEF LO
!ERROR commpre.nmk: LO not defined
!ENDIF
!IFNDEF AMC
!ERROR commpre.nmk: AMC not defined
!ENDIF
!IFNDEF AMS
!ERROR commpre.nmk: AMS not defined
!ENDIF
!IFNDEF POOLN
!ERROR commpre.nmk: POOLN not defined
!ENDIF
!IFNDEF SNC
!ERROR commpre.nmk: SNC not defined
!ENDIF
!IFNDEF FMTDY
!ERROR commpre.nmk: FMTDY not defined
!ENDIF
!IFNDEF FMTTEST
!ERROR commpre.nmk: FMTTEST not defined
!ENDIF
!IFNDEF FMTSCHEME
!ERROR commpre.nmk: FMTSCHEME not defined
!ENDIF
!IFNDEF TESTLIB
!ERROR commpre.nmk: TESTLIB not defined
!ENDIF
!IFNDEF TESTTHR
!ERROR commpre.nmk: TESTTHR not defined
!ENDIF
# DECLARATIONS
!IFDEF NOISY
ECHO = rem
!ELSE
.SILENT:
ECHO = echo
!ENDIF
# C FLAGS
CFLAGSTARGETPRE =
CFLAGSTARGETPOST =
CRTFLAGSHOT =
CRTFLAGSCOOL =
LINKFLAGSHOT =
LINKFLAGSCOOL =
CFLAGSSQLPRE = /nologo $(PFMDEFS)
CFLAGSCOMMONPRE = /nologo $(PFMDEFS) $(CFLAGSTARGETPRE)
CFLAGSSQLPOST =
CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST)
# Flags for use in the variety combinations
CFLAGSHOT = /O2
# (above /O2 (maximise speed) used to be set to /Ox
# (maximise optimisations) in for tool versions before VS 9)
# We used to have /GZ here (stack probe).
# Note that GZ is specific to version 12 of the cl tool. drj 2003-11-04
# It is ignored on earlier versions of the cl tool.
# /GZ here generates a dependency on the C library and when we are
# building a DLL, mpsdy.dll, the linker step will fail (error LNK2001:
# unresolved external symbol __chkesp). See
# http://support.microsoft.com/kb/q191669/
CFLAGSCOOL =
CFLAGSINTERNAL = /Zi
CFLAGSEXTERNAL =
# The combinations of variety
# %%VARIETY: When adding a new variety, define a macro containing the set
# of flags for the new variety.
CFRASH = /DCONFIG_VAR_RASH $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL)
CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL)
CFCOOL = /DCONFIG_VAR_COOL $(CRTFLAGSCOOL) $(CFLAGSCOOL) $(CFLAGSINTERNAL)
# Microsoft documentation is not very clear on the point of using both
# optimization and debug information
# LINKER FLAGS
# %%VARIETY: When adding a new variety, define a macro containing the flags
# for the new variety
LINKER = link
LINKFLAGSCOMMON = /nologo /LARGEADDRESSAWARE
LINKFLAGSINTERNAL = /DEBUG
# ( Internal flags used to be set to /DEBUG:full )
LINKFLAGSEXTERNAL = /RELEASE
LFRASH = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL)
LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL)
LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL)
#LFCV = /PROFILE /DEBUG:full /DEBUGTYPE:cv
# Library manager
# %%VARIETY: When adding a new variety, define a macro containing the flags
# for the new variety
LIBMAN = lib # can't call this LIB - it screws the environment
LIBFLAGSCOMMON =
LIBFLAGSRASH =
LIBFLAGSHOT =
LIBFLAGSCOOL =
# Browser database manager [not used at present]
#BSC = bscmake
#BSCFLAGS = /nologo /n
# == Common definitions ==
# %%PART: When adding a new part, add it here, unless it's platform-specific
# [It is not possible use a macro, like $(PFM), in a substitution,
# hence all parts end up being platform-specific.]
# C. COPYRIGHT AND LICENSE
#
# 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.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Redistributions in any form must be accompanied by information on how
# to obtain complete source code for this software and any accompanying
# software that uses this software. The source code must either be
# included in the distribution or be available for no more than the cost
# of distribution plus a nominal fee, and must be freely redistributable
# under reasonable conditions. For an executable file, complete source
# code means the source code for all modules it contains. It does not
# include source code for modules or files that typically accompany the
# major components of the operating system on which the executable file
# runs.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -13,10 +13,15 @@
#include "mps.c"
#include "getopt.h"
#include "testlib.h"
#include "testthr.h"
#ifdef MPS_OS_W3
#include "getopt.h"
#else
#include <getopt.h>
#endif
#include <stdio.h> /* fprintf, stderr */
#include <stdlib.h> /* alloca, exit, EXIT_SUCCESS, EXIT_FAILURE */
#include <time.h> /* CLOCKS_PER_SEC, clock */

View file

@ -1,7 +1,7 @@
/* freelist.c: FREE LIST ALLOCATOR IMPLEMENTATION
*
* $Id$
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2013-2015 Ravenbrook Limited. See end of file for license.
*
* .sources: <design/freelist/>.
*/
@ -18,11 +18,11 @@ SRCID(freelist, "$Id$");
typedef union FreelistBlockUnion {
struct {
struct FreelistBlockSmall {
FreelistBlock next; /* tagged with low bit 1 */
/* limit is (char *)this + freelistAlignment(fl) */
} small;
struct {
struct FreelistBlockLarge {
FreelistBlock next; /* not tagged (low bit 0) */
Addr limit;
} large;
@ -101,6 +101,9 @@ static Bool FreelistBlockCheck(FreelistBlock block)
CHECKL(freelistBlockNext(block) == freelistEND
|| block < freelistBlockNext(block));
CHECKL(freelistBlockIsSmall(block) || (Addr)block < block->large.limit);
/* Would like to CHECKL(!freelistBlockIsSmall(block) ||
* freelistBlockSize(fl, block) == freelistAlignment(fl)) but we
* don't have 'fl' here. This is checked in freelistBlockSetLimit. */
return TRUE;
}
@ -139,6 +142,7 @@ static void freelistBlockSetLimit(Freelist fl, FreelistBlock block, Addr limit)
} else {
AVER(size >= sizeof(block->small));
block->small.next = freelistTagSet(block->small.next);
AVER(freelistBlockSize(fl, block) == freelistAlignment(fl));
}
AVER(freelistBlockLimit(fl, block) == limit);
}
@ -170,6 +174,9 @@ Bool FreelistCheck(Freelist fl)
CHECKS(Freelist, fl);
land = FreelistLand(fl);
CHECKD(Land, land);
CHECKL(AlignCheck(FreelistMinimumAlignment));
CHECKL(sizeof(struct FreelistBlockSmall) < sizeof(struct FreelistBlockLarge));
CHECKL(sizeof(struct FreelistBlockSmall) <= freelistAlignment(fl));
/* See <design/freelist/#impl.grain.align> */
CHECKL(AlignIsAligned(freelistAlignment(fl), FreelistMinimumAlignment));
CHECKL((fl->list == freelistEND) == (fl->listSize == 0));
@ -236,12 +243,14 @@ static Size freelistSize(Land land)
* Otherwise, if next is freelistEND, make prev the last block in the list.
* Otherwise, make next follow prev in the list.
* Update the count of blocks by 'delta'.
*
* It is tempting to try to simplify this code by putting a
* FreelistBlockUnion into the FreelistStruct and so avoiding the
* special case on prev. But the problem with that idea is that we
* can't guarantee that such a sentinel would respect the isolated
* range invariant, and so it would still have to be special-cases.
* range invariant (it would have to be at a lower address than the
* first block in the free list, which the MPS has no mechanism to
* enforce), and so it would still have to be special-cased.
*/
static void freelistBlockSetPrevNext(Freelist fl, FreelistBlock prev,
@ -781,6 +790,7 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth)
res = WriteF(stream, depth,
"Freelist $P {\n", (WriteFP)fl,
" listSize = $U\n", (WriteFU)fl->listSize,
" size = $U\n", (WriteFU)fl->size,
NULL);
b = LandIterate(land, freelistDescribeVisitor, stream, depth + 2);
@ -815,7 +825,7 @@ DEFINE_LAND_CLASS(FreelistLandClass, class)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2013-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -7,13 +7,18 @@
*/
#include "mps.c"
#include "getopt.h"
#include "testlib.h"
#include "testthr.h"
#include "fmtdy.h"
#include "fmtdytst.h"
#include "mpm.h"
#ifdef MPS_OS_W3
#include "getopt.h"
#else
#include <getopt.h>
#endif
#include <stdio.h> /* fprintf, printf, putchars, sscanf, stderr, stdout */
#include <stdlib.h> /* alloca, exit, EXIT_FAILURE, EXIT_SUCCESS, strtoul */
#include <time.h> /* clock, CLOCKS_PER_SEC */

View file

@ -657,7 +657,8 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context)
res = PoolAccess(SegPool(seg), seg, addr, mode, context);
AVER(res == ResOK); /* Mutator can't continue unless this succeeds */
} else {
/* Protection was already cleared: nothing to do now. */
/* Protection was already cleared, for example by another thread
or a fault in a nested exception handler: nothing to do now. */
}
EVENT4(ArenaAccess, arena, count, addr, mode);
ArenaLeave(arena);

View file

@ -1,7 +1,7 @@
/* land.c: LAND (COLLECTION OF ADDRESS RANGES) IMPLEMENTATION
*
* $Id$
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2014-2015 Ravenbrook Limited. See end of file for license.
*
* .design: <design/land/>
*/
@ -282,7 +282,7 @@ Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size
AVER(oldRangeReturn != NULL);
AVERT(Land, land);
AVER(SizeIsAligned(size, land->alignment));
AVER(FindDeleteCheck(findDelete));
AVERT(FindDelete, findDelete);
landEnter(land);
b = (*land->class->findFirst)(rangeReturn, oldRangeReturn, land, size,
@ -306,7 +306,7 @@ Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size,
AVER(oldRangeReturn != NULL);
AVERT(Land, land);
AVER(SizeIsAligned(size, land->alignment));
AVER(FindDeleteCheck(findDelete));
AVERT(FindDelete, findDelete);
landEnter(land);
b = (*land->class->findLast)(rangeReturn, oldRangeReturn, land, size,
@ -330,7 +330,7 @@ Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size si
AVER(oldRangeReturn != NULL);
AVERT(Land, land);
AVER(SizeIsAligned(size, land->alignment));
AVER(FindDeleteCheck(findDelete));
AVERT(FindDelete, findDelete);
landEnter(land);
b = (*land->class->findLargest)(rangeReturn, oldRangeReturn, land, size,
@ -470,7 +470,7 @@ Bool LandClassCheck(LandClass class)
static Res landTrivInit(Land land, ArgList args)
{
AVERT(Land, land);
AVER(ArgListCheck(args));
AVERT(ArgList, args);
UNUSED(args);
return ResOK;
}
@ -555,7 +555,7 @@ static Bool landNoFind(Range rangeReturn, Range oldRangeReturn, Land land, Size
AVER(oldRangeReturn != NULL);
AVERT(Land, land);
UNUSED(size);
AVER(FindDeleteCheck(findDelete));
AVERT(FindDelete, findDelete);
return ResUNIMPL;
}
@ -567,7 +567,7 @@ static Res landNoFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRang
AVERT(Land, land);
UNUSED(size);
UNUSED(zoneSet);
AVER(BoolCheck(high));
AVERT(Bool, high);
return ResUNIMPL;
}
@ -606,7 +606,7 @@ DEFINE_CLASS(LandClass, class)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2014-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* ld.c: LOCATION DEPENDENCY IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .def: A location dependency records the fact that the bit-patterns
* of some references will be used directly (most likely for
@ -92,6 +92,15 @@ void LDReset(mps_ld_t ld, Arena arena)
* occured since the epoch recorded in the dependency. If the location
* were used first only the new location of the reference would end up
* in the set.
*
* .add.no-arena-check: Add does not check that the address belongs to
* the arena because this would require taking the arena lock. We
* would rather that this function be lock-free even if some errors
* are not detected.
*
* .add.no-align-check: Add does not check that the address is
* aligned, for the same reason as .add.check: it can't find out which
* pool the address belongs to without taking the lock.
*/
void LDAdd(mps_ld_t ld, Arena arena, Addr addr)
{
@ -153,6 +162,10 @@ Bool LDIsStaleAny(mps_ld_t ld, Arena arena)
* .stale.conservative: In fact we just ignore the address and test if
* any dependency is stale. This is conservatively correct (no false
* negatives) but provides a hook for future improvement.
*
* .stale.no-arena-check: See .add.no-arena-check.
*
* .stale.no-align-check: See .add.no-align-check.
*/
Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr)
{
@ -225,7 +238,7 @@ void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* mpm.c: GENERAL MPM SUPPORT
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .purpose: Miscellaneous support for the implementation of the MPM
* and pool classes.
@ -137,6 +137,16 @@ Bool AlignCheck(Align align)
}
/* AccessSetCheck -- check that an access set is valid */
Bool AccessSetCheck(AccessSet mode)
{
CHECKL(mode < ((ULongest)1 << AccessLIMIT));
UNUSED(mode); /* see .check.unused */
return TRUE;
}
#endif /* defined(AVER_AND_CHECK) */
@ -638,7 +648,7 @@ Bool StringEqual(const char *s1, const char *s2)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* mpm.h: MEMORY POOL MANAGER DEFINITIONS
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2002 Global Graphics Software.
*
* .trans.bufferinit: The Buffer data structure has an Init field and
@ -46,6 +46,7 @@ extern Bool FunCheck(Fun f);
extern Bool ShiftCheck(Shift shift);
extern Bool AttrCheck(Attr attr);
extern Bool RootVarCheck(RootVar rootVar);
extern Bool AccessSetCheck(AccessSet mode);
/* Address/Size Interface -- see <code/mpm.c> */
@ -562,13 +563,14 @@ extern Bool (ArenaStep)(Globals globals, double interval, double multiplier);
extern void ArenaClamp(Globals globals);
extern void ArenaRelease(Globals globals);
extern void ArenaPark(Globals globals);
extern void ArenaExposeRemember(Globals globals, int remember);
extern void ArenaExposeRemember(Globals globals, Bool remember);
extern void ArenaRestoreProtection(Globals globals);
extern Res ArenaStartCollect(Globals globals, int why);
extern Res ArenaCollect(Globals globals, int why);
extern Bool ArenaHasAddr(Arena arena, Addr addr);
extern Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr);
extern void ArenaChunkInsert(Arena arena, Chunk chunk);
extern void ArenaChunkRemoved(Arena arena, Chunk chunk);
extern void ArenaSetEmergency(Arena arena, Bool emergency);
extern Bool ArenaEmergency(Arena arean);
@ -1052,7 +1054,7 @@ extern LandClass LandClassGet(void);
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -526,7 +526,6 @@ typedef struct mps_arena_class_s {
ArenaVarargsMethod varargs;
ArenaInitMethod init;
ArenaFinishMethod finish;
ArenaReservedMethod reserved;
ArenaPurgeSpareMethod purgeSpare;
ArenaExtendMethod extend;
ArenaGrowMethod grow;
@ -714,7 +713,8 @@ typedef struct mps_arena_s {
ReservoirStruct reservoirStruct; /* <design/reservoir/> */
Size committed; /* amount of committed RAM */
Size reserved; /* total reserved address space */
Size committed; /* total committed memory */
Size commitLimit; /* client-configurable commit limit */
Size spareCommitted; /* Amount of memory in hysteresis fund */

View file

@ -120,7 +120,6 @@ typedef void (*ArenaVarargsMethod)(ArgStruct args[], va_list varargs);
typedef Res (*ArenaInitMethod)(Arena *arenaReturn,
ArenaClass class, ArgList args);
typedef void (*ArenaFinishMethod)(Arena arena);
typedef Size (*ArenaReservedMethod)(Arena arena);
typedef Size (*ArenaPurgeSpareMethod)(Arena arena, Size size);
typedef Res (*ArenaExtendMethod)(Arena arena, Addr base, Size size);
typedef Res (*ArenaGrowMethod)(Arena arena, LocusPref pref, Size size);

View file

@ -214,7 +214,6 @@
#include "mpsiw3.c" /* Windows interface layer extras */
/* Windows on 64-bit Intel with Microsoft Visual Studio */
/* ssw3i6.asm is also required, but can't be included here */
#elif defined(MPS_PF_W3I6MV)

View file

@ -43,16 +43,16 @@
name = testall;
productName = testrun;
};
2215A9C1192A47D500E9E2CE /* testpoll */ = {
2215A9C1192A47D500E9E2CE /* testpollnone */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 2215A9C5192A47D500E9E2CE /* Build configuration list for PBXAggregateTarget "testpoll" */;
buildConfigurationList = 2215A9C5192A47D500E9E2CE /* Build configuration list for PBXAggregateTarget "testpollnone" */;
buildPhases = (
2215A9C4192A47D500E9E2CE /* ShellScript */,
);
dependencies = (
2215A9C2192A47D500E9E2CE /* PBXTargetDependency */,
);
name = testpoll;
name = testpollnone;
productName = testrun;
};
22CDE8EF16E9E97D00366D0A /* testrun */ = {
@ -285,7 +285,6 @@
3124CAFB156BE82000753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
3124CAFC156BE82900753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
318DA8D21892B13B0089718C /* getoptl.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8D11892B13B0089718C /* getoptl.c */; };
318DA8D31892B27E0089718C /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
31A47BA4156C1E130039B1C2 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
31D60007156D3C6200337B26 /* segsmss.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60006156D3C5F00337B26 /* segsmss.c */; };
@ -327,7 +326,6 @@
31FCAE161769244F008C034C /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
31FCAE19176924D4008C034C /* scheme.c in Sources */ = {isa = PBXBuildFile; fileRef = 31FCAE18176924D4008C034C /* scheme.c */; };
6313D46918A400B200EB03EF /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
6313D46A18A400B200EB03EF /* getoptl.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8D11892B13B0089718C /* getoptl.c */; };
6313D47318A4028E00EB03EF /* djbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8CE1892B1210089718C /* djbench.c */; };
6313D47418A4029200EB03EF /* gcbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 6313D46618A3FDC900EB03EF /* gcbench.c */; };
6313D47518A40C6300EB03EF /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
@ -1635,8 +1633,6 @@
317B3C2A1731830100F9A469 /* arg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arg.c; sourceTree = "<group>"; };
318DA8CD1892B0F30089718C /* djbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djbench; sourceTree = BUILT_PRODUCTS_DIR; };
318DA8CE1892B1210089718C /* djbench.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = djbench.c; sourceTree = "<group>"; };
318DA8D01892B13B0089718C /* getopt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = getopt.h; sourceTree = "<group>"; };
318DA8D11892B13B0089718C /* getoptl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getoptl.c; sourceTree = "<group>"; };
31A47BA3156C1E130039B1C2 /* mps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mps.c; sourceTree = "<group>"; };
31A47BA5156C1E5E0039B1C2 /* ssixi3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ssixi3.c; sourceTree = "<group>"; };
31C83ADD1786281C0031A0DB /* protxc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = protxc.h; sourceTree = "<group>"; };
@ -2267,8 +2263,6 @@
318DA8C21892B0B20089718C /* Benchmarks */ = {
isa = PBXGroup;
children = (
318DA8D01892B13B0089718C /* getopt.h */,
318DA8D11892B13B0089718C /* getoptl.c */,
318DA8CE1892B1210089718C /* djbench.c */,
6313D46618A3FDC900EB03EF /* gcbench.c */,
);
@ -3403,7 +3397,7 @@
2215A9B9192A47CE00E9E2CE /* testall */,
2215A9B1192A47C500E9E2CE /* testansi */,
2215A9A9192A47BB00E9E2CE /* testci */,
2215A9C1192A47D500E9E2CE /* testpoll */,
2215A9C1192A47D500E9E2CE /* testpollnone */,
22CDE8EF16E9E97D00366D0A /* testrun */,
31EEABFA156AAF9D00714D05 /* mps */,
3114A632156E94DB001E0AA3 /* abqtest */,
@ -3468,7 +3462,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../tool/testrun.sh \"$TARGET_BUILD_DIR\" \"$TARGET_NAME\"\n";
shellScript = "../tool/testrun.sh -s \"$TARGET_NAME\" \"$TARGET_BUILD_DIR\"\n";
showEnvVarsInLog = 0;
};
2215A9B4192A47C500E9E2CE /* ShellScript */ = {
@ -3482,7 +3476,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../tool/testrun.sh \"$TARGET_BUILD_DIR\" \"$TARGET_NAME\"\n";
shellScript = "../tool/testrun.sh -s \"$TARGET_NAME\" \"$TARGET_BUILD_DIR\"\n";
showEnvVarsInLog = 0;
};
2215A9BC192A47CE00E9E2CE /* ShellScript */ = {
@ -3496,7 +3490,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../tool/testrun.sh \"$TARGET_BUILD_DIR\" \"$TARGET_NAME\"\n";
shellScript = "../tool/testrun.sh -s \"$TARGET_NAME\" \"$TARGET_BUILD_DIR\"\n";
showEnvVarsInLog = 0;
};
2215A9C4192A47D500E9E2CE /* ShellScript */ = {
@ -3510,7 +3504,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../tool/testrun.sh \"$TARGET_BUILD_DIR\" \"$TARGET_NAME\"\n";
shellScript = "../tool/testrun.sh -s \"$TARGET_NAME\" \"$TARGET_BUILD_DIR\"\n";
showEnvVarsInLog = 0;
};
22CDE8F416E9E9D400366D0A /* ShellScript */ = {
@ -3524,7 +3518,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "../tool/testrun.sh \"$TARGET_BUILD_DIR\" \"$TARGET_NAME\"\n";
shellScript = "../tool/testrun.sh -s \"$TARGET_NAME\" \"$TARGET_BUILD_DIR\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@ -3909,7 +3903,6 @@
files = (
318DA8D31892B27E0089718C /* testlib.c in Sources */,
6313D47318A4028E00EB03EF /* djbench.c in Sources */,
318DA8D21892B13B0089718C /* getoptl.c in Sources */,
22561A9A18F426BB00372C66 /* testthrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -4018,7 +4011,6 @@
6313D47418A4029200EB03EF /* gcbench.c in Sources */,
6313D47518A40C6300EB03EF /* fmtdytst.c in Sources */,
6313D47618A40C7B00EB03EF /* fmtdy.c in Sources */,
6313D46A18A400B200EB03EF /* getoptl.c in Sources */,
22561A9B18F426F300372C66 /* testthrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -5810,7 +5802,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2215A9C5192A47D500E9E2CE /* Build configuration list for PBXAggregateTarget "testpoll" */ = {
2215A9C5192A47D500E9E2CE /* Build configuration list for PBXAggregateTarget "testpollnone" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2215A9C6192A47D500E9E2CE /* Debug */,

View file

@ -1,14 +1,14 @@
/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 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,
* <code/mps.h>, and the internal MPM interfaces, as defined by
* <code/mpm.h>. .purpose.check: It performs checking of the C client's
* usage of the MPS Interface. .purpose.thread: It excludes multiple
* threads from the MPM by locking the Arena (see .thread-safety).
* threads from the MPM by locking the Arena (see <design/thread-safety/>).
*
* .design: <design/interface-c/>
*
@ -248,7 +248,7 @@ void mps_arena_park(mps_arena_t arena)
void mps_arena_expose(mps_arena_t arena)
{
ArenaEnter(arena);
ArenaExposeRemember(ArenaGlobals(arena), 0);
ArenaExposeRemember(ArenaGlobals(arena), FALSE);
ArenaLeave(arena);
}
@ -256,7 +256,7 @@ void mps_arena_expose(mps_arena_t arena)
void mps_arena_unsafe_expose_remember_protection(mps_arena_t arena)
{
ArenaEnter(arena);
ArenaExposeRemember(ArenaGlobals(arena), 1);
ArenaExposeRemember(ArenaGlobals(arena), TRUE);
ArenaLeave(arena);
}
@ -1384,6 +1384,7 @@ mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
AVER(mps_reg_scan != NULL);
AVER(mps_reg_scan == mps_stack_scan_ambig); /* .reg.scan */
AVER(reg_scan_p != NULL); /* stackBot */
AVER(AddrIsAligned(reg_scan_p, sizeof(Word)));
AVER(rank == mps_rank_ambig());
AVER(mps_rm == (mps_rm_t)0);
@ -2005,7 +2006,7 @@ void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -7,7 +7,7 @@
#
# This file is included by platform nmake files that use the Microsoft
# Visual C/C+ compiler. It defines the compiler-specific variables
# that the common nmake file fragment (<code/commpost.nmk>) requires.
# that the common nmake fragment (comm.nmk) requires.
CC = cl
LIBMAN = lib

View file

@ -7,7 +7,7 @@
#
# This file is included by platform nmake files that use the Pelles C
# compiler. It defines the compiler-specific variables that the common
# nmake file fragment (<code/commpost.nmk>) requires.
# nmake fragment (comm.nmk) requires.
CC = pocc
LIBMAN = polib

View file

@ -1,7 +1,7 @@
/* pool.c: POOL IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2001 Global Graphics Software.
*
* DESIGN
@ -328,7 +328,7 @@ Res PoolAccess(Pool pool, Seg seg, Addr addr,
AVERT(Seg, seg);
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
/* Can't check mode as there is no check method */
AVERT(AccessSet, mode);
/* Can't check MutatorFaultContext as there is no check method */
return (*pool->class->access)(pool, seg, addr, mode, context);
@ -694,7 +694,7 @@ Bool PoolHasRange(Pool pool, Addr base, Addr limit)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* poolabs.c: ABSTRACT POOL CLASSES
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2002 Global Graphics Software.
*
* PURPOSE
@ -334,7 +334,7 @@ Res PoolNoAccess(Pool pool, Seg seg, Addr addr,
AVERT(Seg, seg);
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
/* can't check AccessSet as there is no Check method */
AVERT(AccessSet, mode);
/* can't check context as there is no Check method */
UNUSED(mode);
UNUSED(context);
@ -360,7 +360,7 @@ Res PoolSegAccess(Pool pool, Seg seg, Addr addr,
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
AVER(SegPool(seg) == pool);
/* can't check AccessSet as there is no Check method */
AVERT(AccessSet, mode);
/* can't check context as there is no Check method */
UNUSED(addr);
@ -396,7 +396,7 @@ Res PoolSingleAccess(Pool pool, Seg seg, Addr addr,
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
AVER(SegPool(seg) == pool);
/* can't check AccessSet as there is no Check method */
AVERT(AccessSet, mode);
/* can't check context as there is no Check method */
arena = PoolArena(pool);
@ -691,7 +691,7 @@ Size PoolNoSize(Pool pool)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
*
* DESIGN
@ -1206,6 +1206,7 @@ static Res AWLAccess(Pool pool, Seg seg, Addr addr,
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
AVER(SegPool(seg) == pool);
AVERT(AccessSet, mode);
/* Attempt scanning a single reference if permitted */
if(AWLCanTrySingleAccess(PoolArena(pool), awl, seg, addr)) {
@ -1375,7 +1376,7 @@ static Bool AWLCheck(AWL awl)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* poolmv.c: MANUAL VARIABLE POOL
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 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
@ -260,7 +260,7 @@ static Res MVInit(Pool pool, ArgList args)
res = PoolInit(mvBlockPool(mv), arena, PoolClassMFS(), piArgs);
} MPS_ARGS_END(piArgs);
if(res != ResOK)
return res;
goto failBlockPoolInit;
spanExtendBy = sizeof(MVSpanStruct) * (maxSize/extendBy);
@ -270,7 +270,7 @@ static Res MVInit(Pool pool, ArgList args)
res = PoolInit(mvSpanPool(mv), arena, PoolClassMFS(), piArgs);
} MPS_ARGS_END(piArgs);
if(res != ResOK)
return res;
goto failSpanPoolInit;
mv->extendBy = extendBy;
mv->avgSize = avgSize;
@ -284,6 +284,11 @@ static Res MVInit(Pool pool, ArgList args)
AVERT(MV, mv);
EVENT5(PoolInitMV, pool, arena, extendBy, avgSize, maxSize);
return ResOK;
failSpanPoolInit:
PoolFinish(mvBlockPool(mv));
failBlockPoolInit:
return res;
}
@ -913,7 +918,7 @@ Bool MVCheck(MV mv)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* protan.c: ANSI MEMORY PROTECTION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
*
* DESIGN
@ -36,8 +36,7 @@ Size ProtGranularity(void)
void ProtSet(Addr base, Addr limit, AccessSet pm)
{
AVER(base < limit);
/* .improve.protset.check: There is nor AccessSetCheck, so we */
/* don't check it. */
AVERT(AccessSet, pm);
UNUSED(pm);
NOOP;
}
@ -74,7 +73,7 @@ void ProtSync(Arena arena)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* protix.c: PROTECTION FOR UNIX
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* Somewhat generic across different Unix systems. Shared between
* OS X, FreeBSD, and Linux.
@ -66,6 +66,7 @@ void ProtSet(Addr base, Addr limit, AccessSet mode)
AVER(base < limit);
AVER(base != 0);
AVER(AddrOffset(base, limit) <= INT_MAX); /* should be redundant */
AVERT(AccessSet, mode);
/* Convert between MPS AccessSet and UNIX PROT thingies.
In this function, AccessREAD means protect against read accesses
@ -122,7 +123,7 @@ Size ProtGranularity(void)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* protw3.c: PROTECTION FOR WIN32
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*/
#include "mpm.h"
@ -26,6 +26,7 @@ void ProtSet(Addr base, Addr limit, AccessSet mode)
AVER(base < limit);
AVER(base != 0);
AVERT(AccessSet, mode);
newProtect = PAGE_EXECUTE_READWRITE;
if((mode & AccessWRITE) != 0)
@ -140,7 +141,7 @@ void ProtSync(Arena arena)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -100,6 +100,7 @@ Bool ReservoirCheck(Reservoir reservoir)
}
CHECKL(SizeIsArenaGrains(reservoir->reservoirLimit, arena));
CHECKL(SizeIsArenaGrains(reservoir->reservoirSize, arena));
CHECKL(reservoir->reservoirSize <= reservoir->reservoirLimit);
return TRUE;
}

View file

@ -1,7 +1,7 @@
/* root.c: ROOT IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .purpose: This is the implementation of the root datatype.
*
@ -139,7 +139,7 @@ Bool RootCheck(Root root)
CHECKL(root->protBase != (Addr)0);
CHECKL(root->protLimit != (Addr)0);
CHECKL(root->protBase < root->protLimit);
/* there is no AccessSetCheck */
CHECKL(AccessSetCheck(root->pm));
} else {
CHECKL(root->protBase == (Addr)0);
CHECKL(root->protLimit == (Addr)0);
@ -263,7 +263,9 @@ Res RootCreateTable(Root *rootReturn, Arena arena,
AVERT(Arena, arena);
AVERT(Rank, rank);
AVER(base != 0);
AVER(base < limit);
AVER(AddrIsAligned(base, sizeof(Word)));
AVER(base < limit);
AVER(AddrIsAligned(limit, sizeof(Word)));
theUnion.table.base = base;
theUnion.table.limit = limit;
@ -315,6 +317,13 @@ Res RootCreateReg(Root *rootReturn, Arena arena,
return rootCreate(rootReturn, arena, rank, (RootMode)0, RootREG, &theUnion);
}
/* RootCreateFmt -- create root from block of formatted objects
*
* .fmt.no-align-check: Note that we don't check the alignment of base
* and limit. That's because we're only given the scan function, so we
* don't know the format's alignment requirements.
*/
Res RootCreateFmt(Root *rootReturn, Arena arena,
Rank rank, RootMode mode, mps_fmt_scan_t scan,
Addr base, Addr limit)
@ -549,7 +558,7 @@ Bool RootOfAddr(Root *rootReturn, Arena arena, Addr addr)
void RootAccess(Root root, AccessSet mode)
{
AVERT(Root, root);
/* Can't AVERT mode. */
AVERT(AccessSet, mode);
AVER((root->pm & mode) != AccessSetEMPTY);
AVER(mode == AccessWRITE); /* only write protection supported */
@ -698,7 +707,7 @@ Res RootsDescribe(Globals arenaGlobals, mps_lib_FILE *stream, Count depth)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* seg.c: SEGMENTS
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .design: The design for this module is <design/seg/>.
*
@ -529,7 +529,7 @@ Bool SegNextOfRing(Seg *segReturn, Arena arena, Pool pool, Ring next)
AVER_CRITICAL(segReturn != NULL); /* .seg.critical */
AVERT_CRITICAL(Arena, arena);
AVERT_CRITICAL(Pool, pool);
AVER_CRITICAL(RingCheck(next));
AVERT_CRITICAL(Ring, next);
if (next == PoolSegRing(pool)) {
if (!PoolNext(&pool, arena, pool) ||
@ -1224,7 +1224,7 @@ static void gcSegSetGrey(Seg seg, TraceSet grey)
Arena arena;
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
AVER_CRITICAL(TraceSetCheck(grey)); /* .seg.method.check */
AVERT_CRITICAL(TraceSet, grey); /* .seg.method.check */
AVER(seg->rankSet != RankSetEMPTY);
gcseg = SegGCSeg(seg);
AVERT_CRITICAL(GCSeg, gcseg);
@ -1264,7 +1264,7 @@ static void gcSegSetWhite(Seg seg, TraceSet white)
Addr addr, limit;
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
AVER_CRITICAL(TraceSetCheck(white)); /* .seg.method.check */
AVERT_CRITICAL(TraceSet, white); /* .seg.method.check */
gcseg = SegGCSeg(seg);
AVERT_CRITICAL(GCSeg, gcseg);
AVER_CRITICAL(&gcseg->segStruct == seg);
@ -1307,7 +1307,7 @@ static void gcSegSetRankSet(Seg seg, RankSet rankSet)
Arena arena;
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
AVER_CRITICAL(RankSetCheck(rankSet)); /* .seg.method.check */
AVERT_CRITICAL(RankSet, rankSet); /* .seg.method.check */
AVER_CRITICAL(rankSet == RankSetEMPTY
|| RankSetIsSingle(rankSet)); /* .seg.method.check */
gcseg = SegGCSeg(seg);
@ -1378,7 +1378,7 @@ static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
Arena arena;
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
AVER_CRITICAL(RankSetCheck(rankSet)); /* .seg.method.check */
AVERT_CRITICAL(RankSet, rankSet); /* .seg.method.check */
AVER_CRITICAL(rankSet == RankSetEMPTY
|| RankSetIsSingle(rankSet)); /* .seg.method.check */
gcseg = SegGCSeg(seg);
@ -1701,7 +1701,7 @@ void SegClassMixInNoSplitMerge(SegClass class)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* shield.c: SHIELD IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* See: idea.shield, design.mps.shield.
*
@ -105,6 +105,7 @@ static void protLower(Arena arena, Seg seg, AccessSet mode)
AVERT_CRITICAL(Arena, arena);
UNUSED(arena);
AVERT_CRITICAL(Seg, seg);
AVERT_CRITICAL(AccessSet, mode);
if (SegPM(seg) & mode) {
SegSetPM(seg, SegPM(seg) & ~mode);
@ -191,6 +192,7 @@ void (ShieldRaise) (Arena arena, Seg seg, AccessSet mode)
/* can't check seg. Nor can we check arena as that checks the */
/* segs in the cache. */
AVERT(AccessSet, mode);
AVER((SegSM(seg) & mode) == AccessSetEMPTY);
SegSetSM(seg, SegSM(seg) | mode); /* inv.prot.shield preserved */
@ -204,6 +206,7 @@ void (ShieldRaise) (Arena arena, Seg seg, AccessSet mode)
void (ShieldLower)(Arena arena, Seg seg, AccessSet mode)
{
/* Don't check seg or arena, see .seg.broken */
AVERT(AccessSet, mode);
AVER((SegSM(seg) & mode) == mode);
/* synced(seg) is not changed by the following
* preserving inv.unsynced.suspended
@ -336,7 +339,7 @@ void (ShieldCover)(Arena arena, Seg seg)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* splay.c: SPLAY TREE IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .purpose: Splay trees are used to manage potentially unbounded
* collections of ordered things. In the MPS these are usually
@ -9,10 +9,9 @@
*
* .source: <design/splay>
*
* .note.stack: It's important that the MPS have a bounded stack
* size, and this is a problem for tree algorithms. Basically,
* we have to avoid recursion. TODO: Design documentation for this
* requirement, meanwhile see job003651 and job003640.
* .note.stack: It's important that the MPS have a bounded stack size,
* and this is a problem for tree algorithms. Basically, we have to
* avoid recursion. See design.mps.sp.sol.depth.no-recursion.
*/
@ -1402,7 +1401,7 @@ Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, Count depth,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* trace.c: GENERIC TRACER IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited.
* Copyright (c) 2001-2015 Ravenbrook Limited.
* See end of file for license.
* Portions copyright (C) 2002 Global Graphics Software.
*
@ -1188,6 +1188,7 @@ void TraceSegAccess(Arena arena, Seg seg, AccessSet mode)
AVERT(Arena, arena);
AVERT(Seg, seg);
AVERT(AccessSet, mode);
/* If it's a read access, then the segment must be grey for a trace */
/* which is flipped. */
@ -1962,7 +1963,7 @@ Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited
* Copyright (C) 2001-2015 Ravenbrook Limited
* <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.

View file

@ -674,7 +674,7 @@ static Res arenaRememberSummaryOne(Globals global, Addr base, RefSet summary)
RememberedSummaryBlock newBlock;
int res;
res = ControlAlloc(&p, arena, sizeof *newBlock, 0);
res = ControlAlloc(&p, arena, sizeof *newBlock, FALSE);
if(res != ResOK) {
return res;
}
@ -704,12 +704,13 @@ static Res arenaRememberSummaryOne(Globals global, Addr base, RefSet summary)
protection state or not (for later restoration with
ArenaRestoreProtection).
*/
void ArenaExposeRemember(Globals globals, int remember)
void ArenaExposeRemember(Globals globals, Bool remember)
{
Seg seg;
Arena arena;
AVERT(Globals, globals);
AVERT(Bool, remember);
ArenaPark(globals);

View file

@ -167,7 +167,8 @@ Bool ChunkCheck(Chunk chunk)
/* ChunkInit -- initialize generic part of chunk */
Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, BootBlock boot)
Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
BootBlock boot)
{
Size size;
Count pages;
@ -192,6 +193,7 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, BootBlock boot)
chunk->pageShift = pageShift = SizeLog2(chunk->pageSize);
chunk->base = base;
chunk->limit = limit;
chunk->reserved = reserved;
size = ChunkSize(chunk);
chunk->pages = pages = size >> pageShift;
@ -262,17 +264,16 @@ void ChunkFinish(Chunk chunk)
PageIndexBase(chunk, chunk->allocBase),
chunk->limit);
ArenaChunkRemoved(arena, chunk);
chunk->sig = SigInvalid;
TreeFinish(&chunk->chunkTree);
RingRemove(&chunk->arenaRing);
if (chunk->arena->primary == chunk)
chunk->arena->primary = NULL;
/* Finish all other fields before class finish, because they might be */
/* unmapped there. */
(chunk->arena->class->chunkFinish)(chunk);
(*arena->class->chunkFinish)(chunk);
}

View file

@ -148,6 +148,9 @@ typedef struct ChunkStruct {
BT allocTable; /* page allocation table */
Page pageTable; /* the page table */
Count pageTablePages; /* number of pages occupied by page table */
Size reserved; /* reserved address space for chunk (including overhead
such as losses due to alignment): must not change
(or arena reserved calculation will break) */
} ChunkStruct;
@ -159,10 +162,11 @@ typedef struct ChunkStruct {
#define ChunkSizeToPages(chunk, size) ((Count)((size) >> (chunk)->pageShift))
#define ChunkPage(chunk, pi) (&(chunk)->pageTable[pi])
#define ChunkOfTree(tree) PARENT(ChunkStruct, chunkTree, tree)
#define ChunkReserved(chunk) RVALUE((chunk)->reserved)
extern Bool ChunkCheck(Chunk chunk);
extern Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit,
BootBlock boot);
Size reserved, BootBlock boot);
extern void ChunkFinish(Chunk chunk);
extern Compare ChunkCompare(Tree tree, TreeKey key);
extern TreeKey ChunkKey(Tree tree);

View file

@ -1,7 +1,7 @@
/* tree.c: BINARY TREE IMPLEMENTATION
*
* $Id$
* Copyright (C) 2014 Ravenbrook Limited. See end of file for license.
* Copyright (C) 2014-2015 Ravenbrook Limited. See end of file for license.
*
* Simple binary trees with utilities, for use as building blocks.
* Keep it simple, like Rings (see ring.h).
@ -9,10 +9,9 @@
* The performance requirements on tree implementation will depend on
* how each individual function is applied in the MPS.
*
* .note.stack: It's important that the MPS have a bounded stack
* size, and this is a problem for tree algorithms. Basically,
* we have to avoid recursion. TODO: Design documentation for this
* requirement, meanwhile see job003651 and job003640.
* .note.stack: It's important that the MPS have a bounded stack size,
* and this is a problem for tree algorithms. Basically, we have to
* avoid recursion. See design.mps.sp.sol.depth.no-recursion.
*/
#include "tree.h"
@ -569,7 +568,7 @@ void TreeTraverseAndDelete(Tree *treeIO, TreeVisitor visitor,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2014-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -5,9 +5,6 @@
PFM = w3i3mv
PFMDEFS = /DCONFIG_PF_STRING="w3i3mv" /DCONFIG_PF_W3I3MV /DWIN32 /D_WINDOWS
# MPM platform-specific sources.
MPMPF = \
[lockw3] \
[mpsiw3] \
@ -20,9 +17,8 @@ MPMPF = \
[thw3i3] \
[vmw3]
!INCLUDE commpre.nmk
!INCLUDE mv.nmk
!INCLUDE commpost.nmk
!INCLUDE comm.nmk
# C. COPYRIGHT AND LICENSE

View file

@ -5,9 +5,6 @@
PFM = w3i3pc
PFMDEFS = /DCONFIG_PF_STRING="w3i3pc" /DCONFIG_PF_W3I3PC /DWIN32 /D_WINDOWS
# MPM platform-specific sources.
MPMPF = \
[lockw3] \
[mpsiw3] \
@ -20,9 +17,8 @@ MPMPF = \
[thw3i3] \
[vmw3]
!INCLUDE commpre.nmk
!INCLUDE pc.nmk
!INCLUDE commpost.nmk
!INCLUDE comm.nmk
# C. COPYRIGHT AND LICENSE

View file

@ -5,10 +5,6 @@
PFM = w3i6mv
PFMDEFS = /DCONFIG_PF_STRING="w3i6mv" /DCONFIG_PF_W3I6MV /DWIN32 /D_WINDOWS
MASM = ml64
# MPM platform-specific sources.
MPMPF = \
[lockw3] \
[mpsiw3] \
@ -21,9 +17,8 @@ MPMPF = \
[thw3i6] \
[vmw3]
!INCLUDE commpre.nmk
!INCLUDE mv.nmk
!INCLUDE commpost.nmk
!INCLUDE comm.nmk
# C. COPYRIGHT AND LICENSE

View file

@ -7,11 +7,8 @@
PFM = w3i6pc
PFMDEFS = /DCONFIG_PF_STRING="w3i6pc" /DCONFIG_PF_W3I6PC /DWIN32 /D_WINDOWS
CFLAGSTARGETPRE = /Tamd64-coff
CFLAGSCOMMONPRE = $(CFLAGSCOMMONPRE) /Tamd64-coff
# MPM platform-specific sources.
MPMPF = \
[lockw3] \
[mpsiw3] \
@ -24,9 +21,8 @@ MPMPF = \
[thw3i6] \
[vmw3]
!INCLUDE commpre.nmk
!INCLUDE pc.nmk
!INCLUDE commpost.nmk
!INCLUDE comm.nmk
# C. COPYRIGHT AND LICENSE

216
mps/design/an.txt Normal file
View file

@ -0,0 +1,216 @@
.. mode: -*- rst -*-
Generic modules
===============
:Tag: design.mps.an
:Author: Gareth Rees
:Date: 2014-11-02
:Status: complete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms: pair: generic modules; design
Introduction
------------
_`.intro`: This is the design of generic modules in the MPS.
_`.readership`: Any MPS developer; anyone porting the MPS to a new
platform.
_`.overview`: Generic modules provide implementations of functional
modules using only the features of the Standard C Library. These
implementations are partially functional or non-functional, but
provide a basis for ports of the MPS to new platforms.
_`.name`: The name "ANSI" for the generic modules is historical: the C
language was originally standardized by the American National
Standards Institute, and so Standard C used to be known as "ANSI C".
Requirements
------------
_`.req.port`: The MPS must be portable to new platforms. (Otherwise we
can't meet the needs of customers using new platforms.)
_`.req.port.rapid`: The MPS should be portable to new platforms
rapidly.
_`.req.port.rapid.expert`: An expert MPS developer (who may be a
novice on the new platform) should be able to get a minimally useful
implementation of the MPS running on a new platform within a few
hours.
_`.req.port.rapid.novice`: A novice MPS developer (who is an expert on
the new platform) should be able to get the MPS running on a new
platform within a few days.
Design
------
_`.sol.modules`: Features of the MPS which can benefit from
platform-specific implementations are divided into *functional
modules*, with clean interfaces to the MPS and to each other. See
`.mod`_ for a list of these modules. (This helps meet `.req.port`_ by
isolating the platform dependencies, and it helps meet
`.req.port.rapid`_ because a porter can mix and match implementations,
using existing implementations where possible.)
_`.sol.generic`: Each functional module has a generic implementation
using only features of the Standard C Library. (This helps meet
`.req.port.rapid`_ because the MPS can be ported in stages, starting
with the generic modules and porting the modules needed to meet the
most urgent requirements. The generic implementations help meet
`.req.port.rapid.novice`_ by providing clear and illustrative
examples.)
_`.sol.fallback`: The interfaces to the modules are designed to make
it possible to implement `.sol.generic`_. When a platform-specific
feature is needed to meet performance (or other attribute)
requirements, the interface also makes it possible to meet the
functional requirements while missing the attribute requirements. See
`.sol.fallback.example`_ for an example. (This helps meet
`.req.port.rapid`_ by allowing the generic implementations to meet
many or most of the functional requirements.)
_`.sol.fallback.example`: The MPS normally uses incremental collection
to meet requirements on pause times, but this requires barriers. The
interface to the protection module is designed to make it possible to
write an implementation without barriers, via the function
``ProtSync()`` that synchronizes the mutator with the collector.
_`.sol.test`: There are makefiles for the pseudo-platforms ``anangc``,
``ananll`` and ``ananmv`` that compile and test the generic
implementations. See design.mps.config.opt_ for the configuration
options used to implement these platforms. (This supports
`.req.port.rapid`_ by making sure that the generic implementations are
working when it is time to use them.)
.. _design.mps.config.opt: config#opt
Modules
-------
_`.mod`: This section lists the functional modules in the MPS.
_`.mod.lock`: Locks. See design.mps.lock_.
_`.mod.prmc`: Protection mutator context. See design.mps.prmc_.
_`.mod.prot`: Memory protection. See design.mps.prot_.
_`.mod.ss`: Stack and register scanning. See design.mps.ss_.
_`.mod.sp`: Stack probe. See design.mps.sp_.
_`.mod.th`: Thread manager. See design.mps.thread-manager_.
_`.mod.vm`: Virtual mapping. See design.mps.vm_.
.. _design.mps.lock: lock
.. _design.mps.prot: prot
.. _design.mps.prmc: prmc
.. _design.mps.sp: sp
.. _design.mps.ss: ss
.. _design.mps.thread-manager: thread-manager
.. _design.mps.vm: vm
Limitations of generic implementations
--------------------------------------
_`.lim`: This section summarizes the limitations of the generic
implementations of the function modules.
_`.lim.lock`: Requires a single-threaded mutator (see
design.mps.lock.impl.an_).
_`.lim.prmc`: Does not support single-stepping of accesses (see
design.mps.prmc.impl.an.fault_) and requires a single-threaded mutator
(see design.mps.prmc.impl.an.suspend_).
_`.lim.prot`: Does not support incremental collection (see
design.mps.prot.impl.an.sync_) and is not compatible with
implementations of the protection mutator context module that support
single-stepping of accesses (see design.mps.prot.impl.an.sync.issue_).
_`.lim.sp`: Only suitable for use with programs that do not handle
stack overflow faults, or do not call into the MPS from the handler
(see design.mps.sp.issue.an_).
_`.lim.ss`: Overscans compared to a platform-specific implementation
(see design.mps.ss.impl.an_).
_`.lim.th`: Requires a single-threaded mutator (see
design.mps.thread-manager.impl.an.single_).
_`.lim.vm`: Maps all reserved addresses into main memory (see
design.mps.vm.impl.an.reserve_), thus using more main memory than a
platform-specific implementation.
.. _design.mps.lock.impl.an: lock#impl.an
.. _design.mps.prmc.impl.an.fault: prmc#impl.an.fault
.. _design.mps.prmc.impl.an.suspend: prmc#impl.an.suspend
.. _design.mps.prot.impl.an.sync: prot#impl.an.sync
.. _design.mps.prot.impl.an.sync.issue: prot#impl.an.sync.issue
.. _design.mps.sp.issue.an: sp#issue.an
.. _design.mps.ss.impl.an: ss#impl.an
.. _design.mps.thread-manager.impl.an.single: thread-manager#impl.an.single
.. _design.mps.vm.impl.an.reserve: vm#impl.an.reserve
Document History
----------------
- 2014-11-02 GDR_ Initial draft based on design.mps.protan.
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
Copyright and License
---------------------
Copyright © 2014 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
#. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
#. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
#. Redistributions in any form must be accompanied by information on how
to obtain complete source code for this software and any
accompanying software that uses this software. The source code must
either be included in the distribution or be available for no more than
the cost of distribution plus a nominal fee, and must be freely
redistributable under reasonable conditions. For an executable file,
complete source code means the source code for all modules it contains.
It does not include source code for modules or files that typically
accompany the major components of the operating system on which the
executable file runs.
**This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a
particular purpose, or non-infringement, are disclaimed. In no event
shall the copyright holders and contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or
services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.**

127
mps/design/bootstrap.txt Normal file
View file

@ -0,0 +1,127 @@
.. mode: -*- rst -*-
Bootstrapping
=============
:Tag: design.mps.bootstrap
:Author: Gareth Rees
:Date: 2015-09-01
:Status: incomplete design
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
:Index terms: pair: bootsrap; design
Introduction
------------
_`.intro`: This explains how the MPS gets started.
_`.readership`: Any MPS developer.
_`.overview`: The job of the MPS is to allocate memory to a program.
Before it can allocate memory, the MPS needs to create data structures
to represent its internal state. But before it can create those data
structures, it needs to allocate memory to store them in. This
bootstrapping problem affects the MPS at several points, which are
listed here, together with their solutions.
Bootstrapping problems
----------------------
Virtual memory descriptor
.........................
_`.vm`: Before address space can be mapped into main memory, the
virtual memory descriptor must be initialized. But before the virtual
memory descriptor can be initialized, some address space must be
mapped into main memory in order to store it. See
`design.vm.req.bootstrap`_.
_`.vm.sol`: The virtual memory descriptor is allocated initially on
the stack, and then copied into its place in the chunk after the
memory for it has been mapped. See `design.vm.sol.bootstrap`_.
.. _design.vm.req.bootstrap: vm#req.bootstrap
.. _design.vm.sol.bootstrap: vm#sol.bootstrap
Arena descriptor
................
_`.arena`: Before chunks of address space can be reserved and mapped,
the virtual memory arena descriptor must be initialized (so that the
chunks can be added to the arena's chunk tree). But before a virtual
memory arena descriptor can be initialized, address space must be
reserved and mapped in order to store it.
_`.arena.sol`: A small amount of address space is reserved and mapped
directly via ``VMInit()`` and ``VMMap()`` (not via the chunk system)
in order to provide enough memory for the arena descriptor.
Arena's free land
.................
_`.land`: Before the arena can allocate memory, a range of addresses
must be inserted into the arena's free land (so that the free land can
hand out memory from this range). But before addresses can be inserted
into the arena's free land, the arena must be able to allocate memory
(to store the nodes in the tree representing those addresses).
_`.land.sol`: The arena has two "back door" mechanisms and uses them
in combination. First, there is a mechanism for allocating a block of
memory directly from a chunk, bypassing the free land; second, the MFS
pool class has a mechanism for extending it with a block of memory.
Document History
----------------
- 2015-09-01 GDR_ Initial draft.
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
Copyright and License
---------------------
Copyright © 2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
#. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
#. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
#. Redistributions in any form must be accompanied by information on how
to obtain complete source code for this software and any
accompanying software that uses this software. The source code must
either be included in the distribution or be available for no more than
the cost of distribution plus a nominal fee, and must be freely
redistributable under reasonable conditions. For an executable file,
complete source code means the source code for all modules it contains.
It does not include source code for modules or files that typically
accompany the major components of the operating system on which the
executable file runs.
**This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a
particular purpose, or non-infringement, are disclaimed. In no event
shall the copyright holders and contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or
services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.**

View file

@ -76,14 +76,14 @@ class, a subclass of ``LandClass`` suitable for passing to
``LandClass CBSFastLandClassGet(void)``
_`.function.class`: Returns a subclass of ``CBSLandClass`` that
_`.function.class.fast`: Returns a subclass of ``CBSLandClass`` that
maintains, for each subtree, the size of the largest block in that
subtree. This enables the ``LandFindFirst()``, ``LandFindLast()``, and
``LandFindLargest()`` generic functions.
``LandClass CBSZonedLandClassGet(void)``
_`.function.class`: Returns a subclass of ``CBSFastLandClass`` that
_`.function.class.zoned`: Returns a subclass of ``CBSFastLandClass`` that
maintains, for each subtree, the union of the zone sets of all ranges
in that subtree. This enables the ``LandFindInZones()`` generic
function.

189
mps/design/exec-env.txt Normal file
View file

@ -0,0 +1,189 @@
.. mode: -*- rst -*-
Execution environment
=====================
:Tag: design.mps.exec-env
:Author: Richard Brooksby
:Date: 1996-08-30
:Status: incomplete design
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
:Index terms: pair: execution; environment
Introduction
------------
_`.intro`: This document describes how the MPS is designed to work in
different execution environments (see standard.ansic section 5.1.2).
Discussion
----------
_`.std`: These are the relevant statements from the International
Standard ISO/IEC 9899:1990 "Programming languages — C", with tags
added:
4. Compliance
[…]
_`.std.com.hosted`: A "conforming hosted implementation" shall
accept any strictly conforming program. _`.std.com.free`: A
"conforming freestanding implementation" shall accept any strictly
conforming program in which the use of the features specified in
the library clause (clause 7) is confined to the contents of the
standard headers ``<float.h>``, ``<limits.h>``, ``<stdarg.h>``,
and ``<stddef.h>``. A conforming implementation may have
extensions (including additional library functions), provided they
do not alter the behaviour of any strictly conforming program.
[…]
5.1.2 Execution environments
_`.std.def`: Two execution environments are defined:
"freestanding" and "hosted". […]
_`.std.init`: All objects in static storage shall be "initialized"
(set to their initial values) before program startup. The manner
and timing of such initialization are otherwise unspecified. […]
_`.std.term`: "Program termination" returns control to the execution
environment. […]
5.1.2.1 Freestanding environment
_`.std.free.lib`: Any library facilities available to a
freestanding environment are implementation-defined.
_`.std.free.term`: The effect of program termination in a
free-standing environment is implementation-defined.
Interpretation
--------------
_`.int.free`: We interpret the "freestanding environment" as being the
sort of environment you'd expect in an embedded system. The classic
example is a washing machine. There are no library facilities
available, only language facilities.
_`.int.free.lib`: We assume that the headers ``<float.h>``,
``<limits.h>``, ``<stdarg.h>`` and ``<stddef.h>`` are available in the
freestanding environment, because they define only language features
and not library calls. We assume that we may not make use of
definitions in any other headers in freestanding parts of the system.
_`.int.free.term`: We may not terminate the program in a freestanding
environment, and therefore we may not call :c:func:`abort`. We can't
call :c:func:`abort` anyway, because it's not defined in the headers
listed above (`.int.free.lib`_).
_`.int.free.term.own`: We can add an interface for asserting, that is,
reporting an error and not returning, for use in debugging builds
only. This is because the environment can implement this in a way that
does not return to the MPS, but doesn't terminate, either. We need
this if debugging builds are to run in a (possibly simulated or
emulated) freestanding environment at all.
Requirements
------------
_`.req`: It should be possible to make use of the MPS in a
freestanding environment such as an embedded controller.
_`.req.conf`: There can be configurations of the MPS that are not
freestanding (such as using a VM arena).
Architecture
------------
_`.arch`: Like Gaul, the MPS is divided into three parts: the *core*,
the *platform*, and the *plinth*.
_`.arch.core`: The *core* consists of the Memory Pool Manager (the
core data structures and algorithms) and the built-in Pool Classes.
The core must be freestanding.
_`.arch.platform`: The *platform* provides the core with interfaces to
features of the operating system and processor (locks, memory
protection, protection mutator context, stack probing, stack and
register scanning, thread management, and virtual memory). The
platform is specialized to a particular environment and so can safely
use whatever features are available in that environment.
_`.arch.plinth`: The *plinth* provides the core with interfaces to
features of the user environment (time, assertions, and logging). See
design.mps.io_ and design.mps.lib_.
.. _design.mps.io: io
.. _design.mps.lib: lib
_`.arch.distinction`: The distinction between *plinth* and *platform*
is that end users will need to customize the features provided by the
plinth for most programs that use the MPS (and so the interface needs
to be simple, documented and supported), whereas implementing the
platform interface is a specialized task that will typically be done
once for each platform and then maintained alongside the core.
Document History
----------------
- 1996-08-30 RB_ Created to clarify concepts needed for
design.mps.io_.
- 2015-02-06 GDR_ Converted to reStructuredText; bring the
architecture description up to date by describing the platform
interface.
.. _RB: http://www.ravenbrook.com/consultants/rb/
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
Copyright and License
---------------------
Copyright © 1996-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
#. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
#. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
#. Redistributions in any form must be accompanied by information on how
to obtain complete source code for this software and any
accompanying software that uses this software. The source code must
either be included in the distribution or be available for no more than
the cost of distribution plus a nominal fee, and must be freely
redistributable under reasonable conditions. For an executable file,
complete source code means the source code for all modules it contains.
It does not include source code for modules or files that typically
accompany the major components of the operating system on which the
executable file runs.
**This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a
particular purpose, or non-infringement, are disclaimed. In no event
shall the copyright holders and contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or
services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.**

View file

@ -22,10 +22,11 @@ hexadecimal digits.
_`.readership`: This document is intended for anyone devising
arbitrary constants which may appear in hex-dumps.
_`.sources`: This transliteration was supplied by RHSK in
`mail.richardk.1997-04-07.13-44`_.
.. _mail.richardk.1997-04-07.13-44: https://info.ravenbrook.com/project/mps/mail/1997/04/07/13-44/0.txt
_`.sources`: This transliteration was supplied by Richard Kistruck
[RHSK-1997-04-07]_ based on magic number encodings for object signatures
used by Richard Brooksby [RB-1996-02-12]_, the existence of which was
inspired by the structure marking used in the Multics operating system
[THVV-1995]_.
Transliteration
@ -78,8 +79,8 @@ _`.trans.t`: T is an exception to `.numbers`_, but is such a common
letter that it deserves it.
4. Notes
--------
Notes
-----
_`.change`: This transliteration differs from the old transliteration
used for signatures (see design.mps.sig_), as follows: J:6->1;
@ -106,6 +107,33 @@ selected (by capitalisation), e.g.::
#define SpaceSig ((Sig)0x5195BACE) /* SIGnature SPACE */
References
----------
.. [RB-1996-02-12]
"Signature magic numbers" (e-mail message);
`Richard Brooksby`_;
Harlequin;
1996-12-02 12:05:30Z.
.. _`Richard Brooksby`: mailto:rb@ravenbrook.com
.. [RHSK-1997-04-07]
"Alpha-to-Hex v1.0 beta";
Richard Kistruck;
Ravenbrook;
1997-04-07 14:42:02+0100;
<https://info.ravenbrook.com/project/mps/mail/1997/04/07/13-44/0.txt>.
.. [THVV-1995]
"Structure Marking";
Tom Van Vleck;
multicians.org_;
<http://www.multicians.org/thvv/marking.html>.
.. _multicians.org: http://www.multicians.org/
Document History
----------------
2013-05-10 RB_ Converted to reStructuredText and imported to MPS design.

View file

@ -0,0 +1,96 @@
.. mode: -*- rst -*-
Review checklist
================
:Tag: guide.review
:Status: incomplete documentation
:Author: Gareth Rees
:Organization: Ravenbrook Limited
:Date: 2015-08-10
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
:Index terms: pair: review; checklist
Introduction
------------
_`.scope`: This document contains a list of checks to apply when
reviewing code or other documents in the Memory Pool System.
_`.readership`: This document is intended for reviewers.
_`.example`: The "example" links are issues caused by a failure to
apply the checklist item.
_`.diff`: Some items in the checklist are particularly susceptible to
being ignored if one reviews only via the version control diff. These
items refer to this tag.
Checklist
---------
_`.test`: If a new feature has been added to the code, is there a test
case? Example: job003923_.
.. _job003923: http://www.ravenbrook.com/project/mps/issue/job003923/
_`.unwind`: If code has been updated in a function that unwinds its
state in failure cases, have the failure cases been updated to
correspond? Example: job003922_. See `.diff`_.
.. _job003922: http://www.ravenbrook.com/project/mps/issue/job003922/
Document History
----------------
2015-08-10 GDR_ Created.
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
Copyright and License
---------------------
Copyright © 2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
#. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
#. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
#. Redistributions in any form must be accompanied by information on how
to obtain complete source code for this software and any
accompanying software that uses this software. The source code must
either be included in the distribution or be available for no more than
the cost of distribution plus a nominal fee, and must be freely
redistributable under reasonable conditions. For an executable file,
complete source code means the source code for all modules it contains.
It does not include source code for modules or files that typically
accompany the major components of the operating system on which the
executable file runs.
**This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a
particular purpose, or non-infringement, are disclaimed. In no event
shall the copyright holders and contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or
services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.**

View file

@ -41,8 +41,10 @@ Designs
====================== ================================================
abq_ Fixed-length queues
alloc-frame_ Allocation frame protocol
an_ Generic modules
arena_ Arena
arenavm_ Virtual memory arena
bootstrap_ Bootstrapping
bt_ Bit tables
buffer_ Allocation buffers and allocation points
cbs_ Coalescing block structures
@ -52,6 +54,7 @@ collection_ Collection framework
config_ MPS configuration
critical-path_ The critical path through the MPS
diag_ Diagnostic feedback
exec-env_ Execution environment
failover_ Fail-over allocator
finalize_ Finalization
fix_ The generic fix function
@ -59,6 +62,7 @@ freelist_ Free list allocator
guide.hex.trans_ Transliterating the alphabet into hexadecimal
guide.impl.c.format_ Coding standard: conventions for the general format of C source code in the MPS
guide.impl.c.naming_ Coding standard: conventions for internal names
guide.review_ Review checklist
interface-c_ C interface
io_ I/O subsystem
keyword-arguments_ Keyword arguments
@ -82,7 +86,6 @@ poolmvt_ Manual Variable Temporal pool class
poolmvff_ Manual Variable First-Fit pool class
prmc_ Protection mutator context
prot_ Memory protection
protan_ ANSI implementation of protection module
protli_ Linux implementation of protection module
protocol_ Protocol inheritance
protsu_ SunOS 4 implementation of protection module
@ -117,8 +120,10 @@ writef_ The WriteF function
.. _abq: abq
.. _alloc-frame: alloc-frame
.. _an: an
.. _arena: arena
.. _arenavm: arenavm
.. _bootstrap: bootstrap
.. _bt: bt
.. _buffer: buffer
.. _cbs: cbs
@ -128,6 +133,7 @@ writef_ The WriteF function
.. _config: config
.. _critical-path: critical-path
.. _diag: diag
.. _exec-env: exec-env
.. _failover: failover
.. _finalize: finalize
.. _fix: fix
@ -135,6 +141,7 @@ writef_ The WriteF function
.. _guide.hex.trans: guide.hex.trans
.. _guide.impl.c.format: guide.impl.c.format
.. _guide.impl.c.naming: guide.impl.c.naming
.. _guide.review: guide.review
.. _interface-c: interface-c
.. _io: io
.. _keyword-arguments: keyword-arguments
@ -158,7 +165,6 @@ writef_ The WriteF function
.. _poolmvff: poolmvff
.. _prmc: prmc
.. _prot: prot
.. _protan: protan
.. _protli: protli
.. _protocol: protocol
.. _protsu: protsu
@ -231,7 +237,7 @@ Document History
Copyright and License
---------------------
Copyright © 2002-2014 Ravenbrook Limited. All rights reserved.
Copyright © 2002-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -95,17 +95,19 @@ which the MPM sends and receives "messages" to and from the hosted I/O
module.
_`.arch.module`: The modules are part of the MPS but not part of the
freestanding core system (see design.mps.exec-env). The I/O module is
freestanding core system (see design.mps.exec-env_). The I/O module is
responsible for transmitting those messages to the external tools, and
for receiving messages from external tools and passing them to the
MPM.
.. _design.mps.exec-env: exec-env
_`.arch.module.example`: For example, the "file implementation" might
just send/write telemetry messages into a file so that they can be
received/read later by an off-line measurement tool.
_`.arch.external`: The I/O Interface is part of interface to the
freestanding core system (see design.mps.exec-env). This is so that
freestanding core system (see design.mps.exec-env_). This is so that
the MPS can be deployed in a freestanding environment, with a special
I/O module. For example, if the MPS is used in a washing machine the
I/O module could communicate by writing output to the seven-segment
@ -429,7 +431,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
Copyright © 2013-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -86,7 +86,7 @@ indicating whether to continue with the iteration.
``typedef Bool (*LandDeleteVisitor)(Bool *deleteReturn, Land land, Range range, void *closureP, Size closureS)``
_`.type.visitor`: Type ``LandDeleteVisitor`` is a callback function that may
_`.type.deletevisitor`: Type ``LandDeleteVisitor`` is a callback function that may
be passed to ``LandIterateAndDelete()``. It is called for every isolated
contiguous range in address order. The function must return a ``Bool``
indicating whether to continue with the iteration. It may additionally
@ -187,6 +187,16 @@ _`.function.iterate.and.delete`: As ``LandIterate()``, but the visitor
function additionally returns a Boolean indicating whether the range
should be deleted from the land.
_`.function.iterate.and.delete.justify`: The reason for having both
``LandIterate()`` and ``LandIterateAndDelete()`` is that it may be
possible to use a more efficient algorithm, or to preserve more
properties of the data structure, when it is known that the land willl
not be modified during the iteration. For example, in the CBS
implementation, ``LandIterate()`` uses ``TreeTraverse()`` which
preserves the tree structure, whereas ``LandIterateAndDelete()`` uses
``TreeTraverseAndDelete()`` which flattens the tree structure, losing
information about recently accessed nodes.
``Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)``
_`.function.find.first`: Locate the first block (in address order)
@ -311,7 +321,7 @@ Document History
Copyright and License
---------------------
Copyright © 2014 Ravenbrook Limited. All rights reserved.
Copyright © 2014-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -29,11 +29,13 @@ _`.goal`: The goals of the MPS library interface are:
_`.goal.host`: To control the dependency of the MPS on the hosted ISO
C library so that the core MPS remains freestanding (see
design.mps.exec-env).
design.mps.exec-env_).
.. _design.mps.exec-env: exec-env
_`.goal.free`: To allow the core MPS convenient access to ISO C
functionality that is provided on freestanding platforms (see
design.mps.exec-env.std.com.free).
design.mps.exec-env_).
Description
@ -46,7 +48,7 @@ _`.overview.access`: The core MPS needs to access functionality that
could be provided by an ISO C hosted environment.
_`.overview.hosted`: The core MPS must not make direct use of any
facilities in the hosted environment (design.mps.exec-env). However,
facilities in the hosted environment (design.mps.exec-env_). However,
it is sensible to make use of them when the MPS is deployed in a
hosted environment.
@ -93,7 +95,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
Copyright © 2013-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -166,7 +166,7 @@ implemented using the same mechanism as normal locks. (But an
operating system-specific mechanism is used, if possible, to ensure
that the global locks are initialized just once.)
_`.impl.ansi`: Single-threaded generic implementation ``lockan.c``:
_`.impl.an`: Single-threaded generic implementation ``lockan.c``:
- single-threaded;
- no need for locking;
@ -174,7 +174,7 @@ _`.impl.ansi`: Single-threaded generic implementation ``lockan.c``:
- provides checking in debug version;
- otherwise does nothing except keep count of claims.
_`.impl.win`: Windows implementation ``lockw3.c``:
_`.impl.w3`: Windows implementation ``lockw3.c``:
- supports Windows threads;
- uses critical section objects [cso]_;
@ -182,7 +182,7 @@ _`.impl.win`: Windows implementation ``lockw3.c``:
- recursive and non-recursive calls use the same Windows function;
- also performs checking.
_`.impl.posix`: POSIX implementation ``lockix.c``:
_`.impl.ix`: POSIX implementation ``lockix.c``:
- supports [POSIXThreads]_;
- locking structure contains a mutex, initialized to check for
@ -194,7 +194,7 @@ _`.impl.posix`: POSIX implementation ``lockix.c``:
success or ``EDEADLK`` (indicating a recursive claim);
- also performs checking.
_`.impl.linux`: Linux implementation ``lockli.c``:
_`.impl.li`: Linux implementation ``lockli.c``:
- supports [POSIXThreads]_;
- also supports [LinuxThreads]_, a partial implementation of POSIX Threads

View file

@ -7,7 +7,7 @@ Protection mutator context
:Author: Gareth Rees
:Date: 2014-10-23
:Status: complete design
:Revision: $Id: //info.ravenbrook.com/project/mps/master/design/tests.txt#2 $
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms: pair: protection mutator context; design

View file

@ -116,9 +116,22 @@ _`.if.sync.noop`: ``ProtSync()`` is permitted to be a no-op if
Implementations
---------------
_`.impl.an`: Generic implementation. See design.mps.protan_.
_`.impl.an`: Generic implementation in ``protan.c``.
.. _design.mps.protan: protan
_`.impl.an.set`: ``ProtSet()`` does nothing.
_`.impl.an.sync`: ``ProtSync()`` has no way of changing the protection
of a segment, so it simulates faults on all segments that are supposed
to be protected, by calling ``TraceSegAccess()``, until it determines
that no segments require protection any more. This forces the trace to
proceed until it is completed, preventing incremental collection.
_`.impl.an.sync.issue`: This relies on the pool actually removing the
protection, otherwise there is an infinite loop here. This is
therefore not compatible with implementations of the protection
mutator context module that support single-stepping of accesses (see design.mps.prmc.req.fault.step_).
.. _design.mps.prmc.req.fault.step: prmc#req.fault.step
_`.impl.ix`: POSIX implementation.

View file

@ -1,135 +0,0 @@
.. mode: -*- rst -*-
ANSI implementation of protection module
========================================
:Tag: design.mps.protan
:Author: David Jones
:Date: 1997-03-19
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms:
pair: ANSI; protection interface design
pair: ANSI protection interface; design
Introduction
------------
_`.readership`: Any MPS developer.
_`.intro`: This is the design for the ANSI implementation of the
protection module.
Requirements
------------
_`.req.test`: This module is required for testing. Particularly on
platforms where no real implementation of the protection module
exists.
_`.req.rapid-port`: This module is required for rapid porting. It
should enable a developer to port a minimally useful configuration of
the MPS to new platforms very quickly.
Overview
--------
_`.overview`: Most of the functions in the module do nothing. The
exception is ``ProtSync()`` which traverses over all segments in the
arena and simulates an access to each segment that has any protection
on it. This means that this module depends on certain fields in the
segment structure.
_`.overview.noos`: No operating system specific (or even ANSI hosted
specific) code is in this module. It can therefore be used on any
platform, particularly where no real implementation of the module
exists. It satisfies `.req.test`_ and `.req.rapid-port`_ in this way.
Functions
---------
_`.fun.protsetup`: ``ProtSetup()`` does nothing as there is nothing to
do (under UNIX we might expect the protection module to install one or
more signal handlers at this pointer, but that is not appropriate for
the ANSI implementation). Of course, we can't have an empty function
body, so there is a ``NOOP;`` here.
_`.fun.sync`: ``ProtSync()`` is called to ensure that the actual
protection of each segment (as determined by the OS) is in accordance
with the segments's pm field. In the ANSI implementation we have no
way of changing the protection of a segment, so instead we generate
faults on all protected segments in the assumption that that will
remove the protection on segments.
_`.fun.sync.how`: Continually loops over all the segments until it
finds that all segments have no protection.
_`.fun.sync.seg`: If it finds a segment that is protected then
``PoolAccess()`` is called on that segment's pool and with that
segment. The call to ``PoolAccess()`` is wrapped with a
``ShieldEnter()`` and ``ShieldLeave()`` thereby giving the pool the
illusion that the fault was generated outside the MM. This depends on
being able to determine the protection of a segment (using the ``pm``
field), on being able to call ``ShieldEnter()`` and ``ShieldLeave()``,
and on being able to call ``PoolAccess()``.
Document History
----------------
- 1997-03-19 David Jones. Incomplete document.
- 2002-06-07 RB_ Converted from MMInfo database design document.
- 2013-05-23 GDR_ Converted to reStructuredText.
.. _RB: http://www.ravenbrook.com/consultants/rb/
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
Copyright and License
---------------------
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
#. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
#. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
#. Redistributions in any form must be accompanied by information on how
to obtain complete source code for this software and any
accompanying software that uses this software. The source code must
either be included in the distribution or be available for no more than
the cost of distribution plus a nominal fee, and must be freely
redistributable under reasonable conditions. For an executable file,
complete source code means the source code for all modules it contains.
It does not include source code for modules or files that typically
accompany the major components of the operating system on which the
executable file runs.
**This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a
particular purpose, or non-infringement, are disclaimed. In no event
shall the copyright holders and contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or
services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.**

View file

@ -7,7 +7,7 @@ Stack probe
:Author: Gareth Rees
:Date: 2014-10-23
:Status: complete design
:Revision: $Id: //info.ravenbrook.com/project/mps/master/design/thread-manager.txt#7 $
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms: pair: stack probe; design
@ -143,7 +143,7 @@ that it is only suitable for use with programs that do not handle
stack overflow faults, or do not call into the MPS from the handler.
This is because our customers have only required `.req.overflow`_ on
Windows so far. If this becomes a requirement on other platforms, the
following Standard C implementation is likely to work::
following Standard C implementation might work::
void StackProbe(Size depth) {
volatile Word w;
@ -151,8 +151,9 @@ following Standard C implementation is likely to work::
w = *p;
}
(The use of ``volatile`` is to prevent compilers from warning about
the variable ``w`` being written but never read.)
The use of ``volatile`` here is to prevent compilers from warning
about the variable ``w`` being written but never read, or worse,
optimizing away the whole statement under the "as if" rule.
Implementations

View file

@ -388,7 +388,7 @@
id="tspan4371"
x="388"
y="96.362183"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4373"
@ -400,6 +400,6 @@
y="136.36218"
x="426"
id="tspan4375"
sodipodi:role="line">y</tspan></text>
sodipodi:role="line">x</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -374,7 +374,7 @@
id="tspan4371"
x="388"
y="96.362183"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4373"
@ -386,6 +386,6 @@
y="136.36218"
x="426"
id="tspan4375"
sodipodi:role="line">y</tspan></text>
sodipodi:role="line">x</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -7,7 +7,7 @@ Stack and register scanning
:Author: Gareth Rees
:Date: 2014-10-22
:Status: complete design
:Revision: $Id: //info.ravenbrook.com/project/mps/master/design/thread-manager.txt#7 $
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms: pair: stack and register scanning; design

View file

@ -7,7 +7,7 @@ Multi-threaded testing
:Author: Gareth Rees
:Date: 2014-10-21
:Status: complete design
:Revision: $Id: //info.ravenbrook.com/project/mps/master/design/nailboard.txt#3 $
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
:Index terms: pair: threads; testing

View file

@ -180,8 +180,8 @@ Mode Description
======================== ==============================================
``BufferModeATTACHED`` Buffer is attached to a region of memory.
``BufferModeFLIPPED`` Buffer has been flipped.
``BufferModeLOGGED`` Buffer emits the events ``BufferReserve`` and
``BufferCommit``.
``BufferModeLOGGED`` Buffer remains permanently trapped, so that
all reserve and commit events can be logged.
``BufferModeTRANSITION`` Buffer is in the process of being detached.
======================== ==============================================

View file

@ -133,8 +133,8 @@ the function ``VMCopy()``. This allows the initialization of a
temporary VM descriptor on the stack. Second, call ``VMInit()`` to
reserve address space and initialize the temporary VM descriptor.
Third, call ``VMMap()`` on the new VM to map enough memory to store a
``VMChunkStruct``. Fourth, call ``VMCopy()`` to copy the temporary VM
descriptor into its place in the ``VMChunkStruct``.
``VMChunk``. Fourth, call ``VMCopy()`` to copy the temporary VM
descriptor into its place in the ``VMChunk``.
_`.sol.params`: To meet `.req.params`_, the interface provides the
function ``VMParamFromArgs()``, which decodes relevant keyword

View file

@ -6,7 +6,7 @@ The WriteF function
:Tag: design.mps.writef
:Author: Richard Brooksby
:Date: 1996-10-18
:Status: incomplete design
:Status: complete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms: pair: WriteF function; design
@ -16,11 +16,13 @@ Introduction
------------
_`.intro`: This document describes the ``WriteF()`` function, which
allows formatted output in a manner similar to ANSI C ``printf``, but
allows the MPM to operate in a freestanding environment (see
design.mps.exec-env).
allows formatted output in a manner similar to ``printf()`` from the
Standard C library, but allows the Memory Pool Manager (MPM) to
operate in a freestanding environment (see design.mps.exec-env_).
_`.background`: The documents design.mps.exec-env and design.mps.lib_
.. _design.mps.exec-env: exec-env
_`.background`: The documents design.mps.exec-env_ and design.mps.lib_
describe the design of the library interface and the reason that it
exists.
@ -31,10 +33,10 @@ Design
------
_`.no-printf`: There is no dependency on ``printf()``. The MPM only
depends on ``fputc()`` and ``fputs()``, via the Library Interface
(design.mps.lib_). This makes it much easier to deploy the MPS in a
freestanding environment. This is achieved by implementing our own
internal output routines in mpm.c.
depends on ``mps_io_fputc()`` and ``mps_io_fputs()``, via the library
interface (design.mps.lib_), part of the *plinth*. This makes it much
easier to deploy the MPS in a freestanding environment. This is
achieved by implementing our own output routines.
_`.writef`: Our output requirements are few, so the code is short. The
only output function which should be used in the rest of the MPM is
@ -42,9 +44,9 @@ only output function which should be used in the rest of the MPM is
``Res WriteF(mps_lib_FILE *stream, Count depth, ...)``
If ``depth`` is greater than zero, then the first format character,
and each format character after a newline, is preceded by ``depth``
spaces.
If ``depth`` is greater than zero, then the first output character,
and each output character after a newline in a format string, is
preceded by ``depth`` spaces.
``WriteF()`` expects a format string followed by zero or more items to
insert into the output, followed by another format string, more items,
@ -54,7 +56,8 @@ and so on, and finally a ``NULL`` format string. For example::
"Hello: $A\n", (WriteFA)address,
"Spong: $U ($S)\n", (WriteFU)number, (WriteFS)string,
NULL);
if (res != ResOK) return res;
if (res != ResOK)
return res;
This makes ``Describe()`` methods much easier to write. For example, ``BufferDescribe()`` contains the following code::
@ -83,14 +86,15 @@ This makes ``Describe()`` methods much easier to write. For example, ``BufferDes
" alignment $W\n", (WriteFW)buffer->alignment,
" rampCount $U\n", (WriteFU)buffer->rampCount,
NULL);
if (res != ResOK) return res;
if (res != ResOK)
return res;
_`.types`: For each format ``$X`` that ``WriteF()`` supports, there is a
type defined in impl.h.mpmtypes ``WriteFX()`` which is the promoted
version of that type. These are provided both to ensure promotion and
to avoid any confusion about what type should be used in a cast. It is
easy to check the casts against the formats to ensure that they
correspond.
_`.types`: For each format ``$X`` that ``WriteF()`` supports, there is
a type ``WriteFX`` defined in mpmtypes.h, which is the promoted
version of that type. These types are provided both to ensure
promotion and to avoid any confusion about what type should be used in
a cast. It is easy to check the casts against the formats to ensure
that they correspond.
_`.types.cast`: Every argument to ``WriteF()`` must be cast, because
in variable-length argument lists the "default argument promotion"
@ -154,7 +158,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
Copyright © 2013-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -96,8 +96,7 @@ Building the MPS for development
If you're making modifications to the MPS itself, want to build MPS
libraries for linking, or want to build MPS tests and tools, you should
use the MPS build. This uses makefiles or Xcode projects. [Coming
soon, Microsoft Visual Studio solutions.]
use the MPS build. This uses makefiles or Xcode projects.
Prerequisites

View file

@ -1,13 +1,11 @@
<h4>Downloads</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/release/{{ release }}/">MPS Kit release {{ release }}</a><br>
<a href="http://www.ravenbrook.com/project/mps/release/">All MPS Kit releases</a>
</p>
<h4>Issues</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/issue/?action=list&amp;view=status%3dopen&amp;display=Job:Priority:Title&amp;sort=Priority">Known issues</a><br>
<a href="http://www.ravenbrook.com/project/mps/issue/?action=fixed&release_fixed={{ release }}">Issues fixed in release {{ release }}</a>
<a href="http://www.ravenbrook.com/project/mps/issue/?action=list&amp;view=status%3dopen&amp;display=Job:Priority:Title&amp;sort=Priority">All open issues</a>
</p>

View file

@ -7,14 +7,18 @@ Design
:numbered:
abq
an
bootstrap
cbs
config
critical-path
exec-env
failover
freelist
guide.hex.trans
guide.impl.c.format
guide.impl.c.naming
guide.review
interface-c
keyword-arguments
land
@ -32,3 +36,4 @@ Design
thread-manager
type
vm
writef

View file

@ -41,7 +41,6 @@ Old design
poolmv
poolmvt
poolmvff
protan
protli
protsu
protocol
@ -61,4 +60,3 @@ Old design
version
vmo1
vmso
writef

View file

@ -182,9 +182,22 @@ Memory Management Glossary: B
.. relevance::
Bitmaps are sometimes used to represent the marks in a
:term:`mark-sweep` collector, or the used memory in a
:term:`bitmapped fits` :term:`allocator`.
:term:`mark-sweep` collector (see :term:`bitmap marking`),
or the used memory in a :term:`bitmapped fits`
:term:`allocator`.
bitmap marking
In :term:`mark-sweep` collectors, bitmap marking is a
technique for :term:`marking` objects that stores the mark
bits for the objects in a contiguous range of memory in a
separate :term:`bitmap`. This improves the collector's
:term:`locality of reference` and cache performance, because
it avoids setting the :term:`dirty bit` on the :term:`pages`
containing the marked objects.
.. bibref:: :ref:`Zorn (1989) <ZORN89>`.
bitmapped fit
A class of :term:`allocation mechanisms` that use a

View file

@ -84,6 +84,7 @@ All
:term:`bit table <bitmap>`
:term:`bit vector <bitmap>`
:term:`bitmap`
:term:`bitmap marking`
:term:`bitmapped fit`
:term:`bitmask`
:term:`bitset <bitmap>`

View file

@ -207,7 +207,11 @@ Memory Management Glossary: M
though any conservative representation of a predicate on the
:term:`memory location` of the object can be used. In
particular, storing the mark bit within the object can lead to
poor :term:`locality of reference`.
poor :term:`locality of reference` and to poor cache
performance, because the marking phases ends up setting the
:term:`dirty bit` on all :term:`pages` in the :term:`working
set`. An alternative is to store the mark bits separately:
see :term:`bitmap marking`.
.. seealso:: :term:`sweep <sweeping>`, :term:`compact <compaction>`.

View file

@ -39,7 +39,7 @@ Memory Management Glossary: R
.. mps:specific::
A value of :c:type:`mps_rank_t` indicating whether a
:term:`root` is :term:`ambiguous <ambiguous root>`
:term:`reference` is :term:`ambiguous <ambiguous root>`
(:c:func:`mps_rank_ambig`), :term:`exact <exact root>`
(:c:func:`mps_rank_exact`) or :term:`weak <weak root>`
(:c:func:`mps_rank_weak`).

View file

@ -13,4 +13,4 @@ Guide
debug
perf
advanced
malloc

View file

@ -266,6 +266,25 @@ code for creating the object format for the toy Scheme interpreter::
} MPS_ARGS_END(args);
if (res != MPS_RES_OK) error("Couldn't create obj format");
The keyword arguments specify the :term:`alignment` and the
:term:`format methods` required by the AMC pool class. These are
described in the following sections.
.. topics::
:ref:`topic-format`.
.. index::
single: alignment
single: alignment; object
single: Scheme; object alignment
.. _guide-lang-alignment:
Alignment
^^^^^^^^^
The argument for the keyword :c:macro:`MPS_KEY_FMT_ALIGN` is the
:term:`alignment` of objects belonging to this format. Determining the
alignment is hard to do portably, because it depends on the target
@ -294,13 +313,19 @@ memory. Here are some things you might try:
#define ALIGNMENT sizeof(mps_word_t)
The other keyword arguments specify the :term:`format methods`
required by the AMC pool class, which are described in the following
sections.
#. The MPS interface provides the type :c:type:`MPS_PF_ALIGN`, which
is the :term:`natural alignment` of the platform: the largest
alignment that might be required. So as a last resort, you can
use::
.. topics::
#define ALIGNMENT MPS_PF_ALIGN
:ref:`topic-format`.
But this may be larger than necessary and so waste space. For
example, on Windows on x86-64, :c:type:`MPS_PF_ALIGN` is 16 bytes,
but this is only necessary for SSE_ types; ordinary types on this
platform require no more than 8-byte alignment.
.. _SSE: http://msdn.microsoft.com/en-us/library/t467de55.aspx
.. index::

View file

@ -0,0 +1,70 @@
.. index::
single: malloc; implementing
single: free; implementing
.. _guide-malloc:
Implementing malloc and free
============================
The MPS function :c:func:`mps_free` is unlike the Standard C Library
function :c:func:`free` in that it takes a ``size`` argument. That's
because it's nearly always the case that either the size of a block is
known statically based on its type (for example, a structure), or else
the size of the block is easily computed from information that needs
to be stored anyway (for example, a vector), and so memory can be
saved by not storing the size separately. It's also better for virtual
memory performance, as a block does not have to be touched in order
to free it.
But sometimes you need to interact with :term:`foreign code` which
requires :c:func:`malloc` and :c:func:`free` (or a pair of functions
with the same interface). In this situation you can implement this
interface using a global pool variable, and putting the size of each
block into its header, like this::
#include "mps.h"
static mps_pool_t malloc_pool;
typedef union {
size_t size;
char alignment[MPS_PF_ALIGN]; /* see note below */
} header_u;
void *malloc(size_t size) {
mps_res_t res;
mps_addr_t p;
header_u *header;
size += sizeof *header;
res = mps_alloc(&p, malloc_pool, size);
if (res != MPS_RES_OK)
return NULL;
header = p;
header->size = size;
return header + 1;
}
void free(void *p) {
if (p) {
header_u *header = ((header_u *)p) - 1;
mps_free(malloc_pool, header, header->size);
}
}
The ``alignment`` member of ``union header_u`` ensures that
allocations are aligned to the platform's :term:`natural alignment`
(see :ref:`guide-lang-alignment`).
The pool needs to belong to a :term:`manually managed <manual memory
management>` pool class, for example :ref:`pool-mvff` (or its
:ref:`debugging counterpart <topic-debugging>`)::
#include "mpscmvff.h"
void malloc_pool_init(mps_arena_t arena) {
mps_res_t res;
res = mps_pool_create_k(&malloc_pool, arena, mps_class_mvff(), mps_args_none);
if (res != RES_OK)
abort();
}

View file

@ -115,7 +115,7 @@ AMC interface
method`, a :term:`forward method`, an :term:`is-forwarded
method` and a :term:`padding method`.
It accepts four optional keyword arguments:
It accepts three optional keyword arguments:
* :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies
the :term:`generation chain` for the pool. If not specified, the
@ -128,8 +128,10 @@ AMC interface
pointers` keep objects alive.
* :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`,
default 4096) is the default :term:`size` of block that the pool
will request from the :term:`arena`.
default 4096) is the minimum :term:`size` of the memory segments
that the pool requests from the :term:`arena`. Larger segments
reduce the per-segment overhead, but increase
:term:`fragmentation` and :term:`retention`.
For example::
@ -138,20 +140,12 @@ AMC interface
res = mps_pool_create_k(&pool, arena, mps_class_amc(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the format and
chain like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_amc(),
mps_fmt_t fmt,
mps_chain_t chain)
.. index::
pair: AMC; introspection
.. _pool-amc-introspection:
AMC introspection
-----------------

View file

@ -87,12 +87,11 @@ AMCZ interface
res = mps_pool_create_k(&pool, arena, mps_class_amcz(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
.. index::
pair: AMCZ; introspection
When using :c:func:`mps_pool_create`, pass the format and
chain like this::
AMCZ introspection
------------------
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_amcz(),
mps_fmt_t fmt,
mps_chain_t chain)
See :ref:`pool-amc-introspection`.

View file

@ -41,7 +41,8 @@ AMS properties
* Supports allocation via :term:`allocation points`. If an allocation
point is created in an AMS pool, the call to
:c:func:`mps_ap_create_k` takes no keyword arguments.
:c:func:`mps_ap_create_k` takes one optional keyword argument,
:c:macro:`MPS_KEY_RANK`.
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
@ -137,19 +138,8 @@ AMS interface
res = mps_pool_create_k(&pool, arena, mps_class_ams(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the format,
chain, and ambiguous flag like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_ams(),
mps_fmt_t fmt,
mps_chain_t chain,
mps_bool_t support_ambiguous)
When creating an :term:`allocation point` on an AMS pool,
:c:func:`mps_ap_create_k` accepts one keyword argument:
:c:func:`mps_ap_create_k` accepts one optional keyword argument:
* :c:macro:`MPS_KEY_RANK` (type :c:type:`mps_rank_t`, default
:c:func:`mps_rank_exact`) specifies the :term:`rank` of references
@ -166,13 +156,6 @@ AMS interface
res = mps_ap_create_k(&ap, ams_pool, args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_ap_create`, pass the rank like this::
mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool,
mps_rank_t rank)
.. c:function:: mps_pool_class_t mps_class_ams_debug(void)
@ -186,15 +169,3 @@ AMS interface
:c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` are as described above,
and :c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` specifies the debugging
options. See :c:type:`mps_pool_debug_option_s`.
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the arguments like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_ams_debug(),
mps_pool_debug_option_s debug_option,
mps_fmt_t fmt,
mps_chain_t chain,
mps_bool_t support_ambiguous)

View file

@ -59,7 +59,7 @@ AWL properties
* Supports allocation via :term:`allocation points`. If an allocation
point is created in an AWL pool, the call to
:c:func:`mps_ap_create_k` accepts one keyword argument,
:c:func:`mps_ap_create_k` accepts one optional keyword argument,
:c:macro:`MPS_KEY_RANK`.
* Supports :term:`allocation frames` but does not use them to improve
@ -350,18 +350,8 @@ AWL interface
res = mps_pool_create_k(&pool, arena, mps_class_awl(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the format and
find-dependent function like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_awl(),
mps_fmt_t fmt,
mps_awl_find_dependent_t find_dependent)
When creating an :term:`allocation point` on an AWL pool,
:c:func:`mps_ap_create_k` accepts one keyword argument:
:c:func:`mps_ap_create_k` accepts one optional keyword argument:
* :c:macro:`MPS_KEY_RANK` (type :c:type:`mps_rank_t`, default
:c:func:`mps_rank_exact`) specifies the :term:`rank` of
@ -378,13 +368,6 @@ AWL interface
res = mps_ap_create_k(&ap, awl_pool, args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_ap_create`, pass the rank like this::
mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool,
mps_rank_t rank)
.. c:type:: mps_addr_t (*mps_awl_find_dependent_t)(mps_addr_t addr)

View file

@ -136,12 +136,3 @@ LO interface
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
res = mps_pool_create_k(&pool, arena, mps_class_lo(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the format like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_lo(),
mps_fmt_t fmt)

View file

@ -87,7 +87,8 @@ MFS interface
:term:`size` of blocks that will be allocated from this pool, in
:term:`bytes (1)`. It must be at least one :term:`word`.
In addition, :c:func:`mps_pool_create_k` may take:
In addition, :c:func:`mps_pool_create_k` accepts one optional
keyword argument:
* :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`,
default 65536) is the :term:`size` of block that the pool will
@ -103,13 +104,3 @@ MFS interface
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, 1024 * 1024);
res = mps_pool_create_k(&pool, arena, mps_class_mfs(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the block size and
unit size like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mfs(),
size_t extend_size,
size_t unit_size)

View file

@ -7,10 +7,6 @@
MV (Manual Variable)
====================
.. deprecated:: starting with version 1.111.
:ref:`pool-mvff` or :ref:`pool-mvt` should be used instead.
**MV** is a general-purpose :term:`manually managed <manual memory
management>` :term:`pool class` that manages :term:`blocks` of
variable size.
@ -70,8 +66,8 @@ MV interface
Return the :term:`pool class` for an MV (Manual Variable)
:term:`pool`.
When creating an MV pool, :c:func:`mps_pool_create_k` may take
the following :term:`keyword arguments`:
When creating an MV pool, :c:func:`mps_pool_create_k` takes four
optional :term:`keyword arguments`:
* :c:macro:`MPS_KEY_ALIGN` (type :c:type:`mps_align_t`, default is
:c:macro:`MPS_PF_ALIGN`) is the
@ -105,17 +101,6 @@ MV interface
res = mps_pool_create_k(&pool, arena, mps_class_mfs(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the block size,
mean size, and maximum size like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mv(),
size_t extend_size,
size_t average_size,
mps_size_t maximum_size)
.. c:function:: mps_pool_class_t mps_class_mv_debug(void)
@ -123,49 +108,8 @@ MV interface
class.
When creating a debugging MV pool, :c:func:`mps_pool_create_k`
takes the following keyword arguments: :c:macro:`MPS_KEY_ALIGN`,
takes five optional keyword arguments: :c:macro:`MPS_KEY_ALIGN`,
:c:macro:`MPS_KEY_EXTEND_SIZE`, :c:macro:`MPS_KEY_MEAN_SIZE`,
:c:macro:`MPS_KEY_MAX_SIZE` are as described above, and
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` specifies the debugging
options. See :c:type:`mps_debug_option_s`.
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the arguments like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mv_debug(),
mps_pool_debug_option_s debug_option,
mps_size_t extend_size,
mps_size_t average_size,
mps_size_t maximum_size)
.. index::
pair: MV; introspection
MV introspection
----------------
::
#include "mpscmv.h"
.. c:function:: size_t mps_mv_free_size(mps_pool_t pool)
Return the total amount of free space in an MV pool.
``pool`` is the MV pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mv_size(mps_pool_t pool)
Return the total size of an MV pool.
``pool`` is the MV pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.
options. See :c:type:`mps_pool_debug_option_s`.

View file

@ -102,8 +102,8 @@ MVFF interface
Return the :term:`pool class` for an MVFF (Manual Variable First
Fit) :term:`pool`.
When creating an MVFF pool, :c:func:`mps_pool_create_k` may take
the following :term:`keyword arguments`:
When creating an MVFF pool, :c:func:`mps_pool_create_k` accepts
seven optional :term:`keyword arguments`:
* :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`, default
65536) is the :term:`size` of block that the pool will request
@ -132,15 +132,15 @@ MVFF interface
default false) determines whether new blocks are acquired at high
addresses (if true), or at low addresses (if false).
* :c:macro:`MPS_KEY_MVFF_SLOT_HIGH` [#not-ap]_ (type :c:type:`mps_bool_t`,
default false) determines whether to search for the highest
addressed free area (if true) or lowest (if false) when allocating
using :c:func:`mps_alloc`.
* :c:macro:`MPS_KEY_MVFF_SLOT_HIGH` [#not-ap]_ (type
:c:type:`mps_bool_t`, default false) determines whether to
search for the highest addressed free area (if true) or lowest
(if false) when allocating using :c:func:`mps_alloc`.
* :c:macro:`MPS_KEY_MVFF_FIRST_FIT` [#not-ap]_ (type :c:type:`mps_bool_t`, default
true) determines whether to allocate from the highest address in a
found free area (if true) or lowest (if false) when allocating
using :c:func:`mps_alloc`.
* :c:macro:`MPS_KEY_MVFF_FIRST_FIT` [#not-ap]_ (type
:c:type:`mps_bool_t`, default true) determines whether to
allocate from the highest address in a found free area (if true)
or lowest (if false) when allocating using :c:func:`mps_alloc`.
.. [#not-ap]
@ -150,12 +150,12 @@ MVFF interface
They use a worst-fit policy in order to maximise the number of
in-line allocations.
The defaults yield a a simple first-fit allocator. Specify
The defaults yield a a simple first-fit allocator. Specify
:c:macro:`MPS_KEY_MVFF_ARENA_HIGH` and
:c:macro:`MPS_KEY_MVFF_SLOT_HIGH` true, and
:c:macro:`MPS_KEY_MVFF_FIRST_FIT` false to get a first-fit
allocator that works from the top of memory downwards.
Other combinations may be useful in special circumstances.
allocator that works from the top of memory downwards. Other
combinations may be useful in special circumstances.
For example::
@ -169,20 +169,6 @@ MVFF interface
res = mps_pool_create_k(&pool, arena, mps_class_mvff(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the arguments like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mvff(),
size_t extend_size,
size_t average_size,
mps_align_t alignment,
mps_bool_t slot_high,
mps_bool_t arena_high,
mps_bool_t first_fit)
.. c:function:: mps_pool_class_t mps_class_mvff_debug(void)
@ -190,55 +176,11 @@ MVFF interface
class.
When creating a debugging MVFF pool, :c:func:`mps_pool_create_k`
takes seven :term:`keyword arguments`.
* :c:macro:`MPS_KEY_EXTEND_BY`, :c:macro:`MPS_KEY_MEAN_SIZE`,
:c:macro:`MPS_KEY_ALIGN`, :c:macro:`MPS_KEY_MVFF_ARENA_HIGH`,
:c:macro:`MPS_KEY_MVFF_SLOT_HIGH`, and
:c:macro:`MPS_KEY_MVFF_FIRST_FIT` are as described above, and
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` specifies the debugging
options. See :c:type:`mps_pool_debug_option_s`.
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the arguments like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mvff_debug(),
mps_pool_debug_option_s debug_option,
size_t extend_size,
size_t average_size,
mps_align_t alignment,
mps_bool_t slot_high,
mps_bool_t arena_high,
mps_bool_t first_fit)
.. index::
pair: MVFF; introspection
MVFF introspection
------------------
::
#include "mpscmvff.h"
.. c:function:: size_t mps_mvff_free_size(mps_pool_t pool)
Return the total amount of free space in an MVFF pool.
``pool`` is the MVFF pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mvff_size(mps_pool_t pool)
Return the total size of an MVFF pool.
``pool`` is the MVFF pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.
accepts eight optional :term:`keyword arguments`:
:c:macro:`MPS_KEY_EXTEND_BY`, :c:macro:`MPS_KEY_MEAN_SIZE`,
:c:macro:`MPS_KEY_ALIGN`, :c:macro:`MPS_KEY_SPARE`,
:c:macro:`MPS_KEY_MVFF_ARENA_HIGH`,
:c:macro:`MPS_KEY_MVFF_SLOT_HIGH`, and
:c:macro:`MPS_KEY_MVFF_FIRST_FIT` are as described above, and
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` specifies the debugging
options. See :c:type:`mps_pool_debug_option_s`.

View file

@ -111,8 +111,8 @@ MVT interface
Return the :term:`pool class` for an MVT (Manual Variable
Temporal) :term:`pool`.
When creating an MVT pool, :c:func:`mps_pool_create_k` may take
six :term:`keyword arguments`:
When creating an MVT pool, :c:func:`mps_pool_create_k` accepts six
optional :term:`keyword arguments`:
* :c:macro:`MPS_KEY_ALIGN` (type :c:type:`mps_align_t`, default is
:c:macro:`MPS_PF_ALIGN`) is the
@ -196,51 +196,3 @@ MVT interface
MPS_ARGS_ADD(args, MPS_KEY_MVT_FRAG_LIMIT, 0.5);
res = mps_pool_create_k(&pool, arena, mps_class_mvt(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the arguments like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mvt(),
size_t minimum_size,
size_t mean_size,
size_t maximum_size,
mps_word_t reserve_depth,
mps_word_t fragmentation_limit)
.. note::
The fragmentation_limit is a percentage from 0 to 100
inclusive when passed to :c:func:`mps_pool_create`, not a
double from 0.0 to 1.0 as in :c:func:`mps_pool_create_k`.
.. index::
pair: MVT; introspection
MVT introspection
-----------------
::
#include "mpscmvt.h"
.. c:function:: size_t mps_mvt_free_size(mps_pool_t pool)
Return the total amount of free space in an MVT pool.
``pool`` is the MVT pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mvt_size(mps_pool_t pool)
Return the total size of an MVT pool.
``pool`` is the MVT pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.

View file

@ -39,7 +39,7 @@ SNC properties
* Supports allocation via :term:`allocation points` only. If an
allocation point is created in an SNC pool, the call to
:c:func:`mps_ap_create_k` requires one keyword argument,
:c:func:`mps_ap_create_k` accepts one optional keyword argument,
:c:macro:`MPS_KEY_RANK`.
* Does not support deallocation via :c:func:`mps_free`.
@ -83,8 +83,8 @@ SNC properties
.. index::
single: SNC; interface
SNC introspection
-----------------
SNC interface
-------------
::
@ -111,21 +111,12 @@ SNC introspection
res = mps_pool_create_k(&pool, arena, mps_class_snc(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the format like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_snc(),
mps_fmt_t fmt)
When creating an :term:`allocation point` on an SNC pool,
:c:func:`mps_ap_create_k` requires one keyword argument:
:c:func:`mps_ap_create_k` accepts one optional keyword argument:
* :c:macro:`MPS_KEY_RANK` (type :c:type:`mps_rank_t`) specifies
the :term:`rank` of references in objects allocated on this
allocation point. It must be :c:func:`mps_rank_exact`.
* :c:macro:`MPS_KEY_RANK` (type :c:type:`mps_rank_t`, default
:c:func:`mps_rank_exact`) specifies the :term:`rank` of references
in objects allocated on this allocation point.
For example::
@ -133,10 +124,3 @@ SNC introspection
MPS_ARGS_ADD(args, MPS_KEY_RANK, mps_rank_exact());
res = mps_ap_create_k(&ap, awl_pool, args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_ap_create`, pass the rank like this::
mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool,
mps_rank_t rank)

View file

@ -9,6 +9,15 @@ Release notes
Release 1.115.0
---------------
New features
............
#. When creating an :ref:`pool-amc` pool, :c:func:`mps_pool_create_k`
accepts the new keyword argument :c:macro:`MPS_KEY_EXTEND_BY`,
specifying the minimum size of the memory segments that the pool
requests from the :term:`arena`.
Interface changes
.................
@ -16,6 +25,46 @@ Interface changes
name :c:type:`mps_class_t` is still available via a ``typedef``,
but is deprecated.
#. The functions :c:func:`mps_mv_free_size`, :c:func:`mps_mv_size`,
:c:func:`mps_mvff_free_size`, :c:func:`mps_mvff_size`,
:c:func:`mps_mvt_free_size` and :c:func:`mps_mvt_size` are now
deprecated in favour of the generic functions
:c:func:`mps_pool_free_size` and :c:func:`mps_pool_total_size`.
Other changes
.............
#. :c:func:`mps_arena_committed` now returns a meaningful value (the
amount of memory marked as in use in the page tables) for
:term:`client arenas`. See job001887_.
.. _job001887: https://www.ravenbrook.com/project/mps/issue/job001887/
#. :ref:`pool-amc` pools now assert that exact references into the
pool are aligned to the pool's alignment. See job002175_.
.. _job002175: https://www.ravenbrook.com/project/mps/issue/job002175/
#. Internal calculation of the address space available to the MPS no
longer takes time proportional to the number of times the arena has
been extended, speeding up allocation when memory is tight. See
job003814_.
.. _job003814: https://www.ravenbrook.com/project/mps/issue/job003814/
#. Setting :c:macro:`MPS_KEY_SPARE` for a :ref:`pool-mvff` pool now
works. See job003870_.
.. _job003870: https://www.ravenbrook.com/project/mps/issue/job003870/
#. When the arena is out of memory and cannot be extended without
hitting the :term:`commit limit`, the MPS now returns
:c:macro:`MPS_RES_COMMIT_LIMIT` rather than substituting
:c:macro:`MPS_RES_RESOURCE`. See job003899_.
.. _job003899: https://www.ravenbrook.com/project/mps/issue/job003899/
.. _release-notes-1.114:
@ -57,8 +106,8 @@ New features
generation sizes. (This is not necessary, but may improve
performance.)
#. New pool introspection functions :c:func:`mps_pool_total_size` and
:c:func:`mps_pool_free_size`.
#. New pool introspection functions :c:func:`mps_pool_free_size` and
:c:func:`mps_pool_total_size`.
Interface changes
@ -147,8 +196,8 @@ Other changes
#. Allocation into :ref:`pool-awl` pools again reliably provokes
garbage collections of the generation that the pool belongs to. (In
release 1.113.0, the generation would only be collected if a pool
of some other class allocated into it.) See job003772_.
version 1.113, the generation would only be collected if a pool of
some other class allocated into it.) See job003772_.
.. _job003772: https://www.ravenbrook.com/project/mps/issue/job003772/
@ -160,13 +209,21 @@ Other changes
.. _job003773: https://www.ravenbrook.com/project/mps/issue/job003773/
#. The :ref:`pool-mvt` and :ref:`pool-mvff` pool classes are now
around 25% faster (in our benchmarks) than they were in release
1.113.0.
around 25% faster (in our benchmarks) than they were in version
1.113.
#. The default assertion handler in the ANSI plinth now flushes the
telemetry stream before aborting. See
#. The default assertion handler in the default :term:`plinth` now
flushes the telemetry stream before aborting. See
:c:func:`mps_lib_assert_fail`.
#. Garbage collection performance is substantially improved in the
situation where the arena has been extended many times. Critical
operations now take time logarithmic in the number of times the
arena has been extended (rather than linear, as in version 1.113
and earlier). See job003554_.
.. _job003554: https://www.ravenbrook.com/project/mps/issue/job003554/
.. _release-notes-1.113:
@ -278,8 +335,8 @@ Interface changes
along indefinitely. See :ref:`topic-error-assertion-handling`.
#. The behaviour when an assertion is triggered is now configurable in
the standard ANSI :term:`plinth` by installing an assertion
handler. See :c:func:`mps_lib_assert_fail_install`.
the default :term:`plinth` by installing an assertion handler. See
:c:func:`mps_lib_assert_fail_install`.
#. Functions that take a variable number of arguments
(:c:func:`mps_arena_create`, :c:func:`mps_pool_create`,
@ -437,3 +494,74 @@ Other changes
later. See job003473_.
.. _job003473: https://www.ravenbrook.com/project/mps/issue/job003473/
.. _release-notes-1.110:
Release 1.110.0
---------------
New features
............
#. New supported platforms:
* ``fri6gc`` (FreeBSD, x86-64, GCC)
* ``lii6gc`` (Linux, x86-64, GCC)
* ``w3i6mv`` (Windows, x86-64, Microsoft Visual C)
* ``xci3ll`` (OS X, IA-32, Clang/LLVM)
* ``xci6gc`` (OS X, x86-64, GCC)
* ``xci6ll`` (OS X, x86-64, Clang/LLVM)
#. Support removed for platforms:
* ``iam4cc`` (Irix 6, MIPS R4000, MIPSpro C)
* ``lii3eg`` (Linux, IA-32, EGCS)
* ``lippgc`` (Linux, PowerPC, GCC)
* ``o1alcc`` (OSF/1, Alpha, Digital C)
* ``o1algc`` (OSF/1, Alpha, GCC)
* ``s7ppmw`` (System 7, PowerPC, MetroWerks C)
* ``sos8gc`` (Solaris, SPARC 8, GCC)
* ``sos9sc`` (Solaris, SPARC 9, SunPro C)
* ``sus8gc`` (SunOS, SPARC 8, GCC)
* ``xcppgc`` (OS X, PowerPC, GCC)
#. On Unix platforms, the MPS can now be built and installed by
running ``./configure && make install``. See :ref:`guide-build`.
#. The MPS can be compiled in a single step via the new source file
``mps.c``. This also allows you to compile the MPS in the same
compilation unit as your object format, allowing the compiler to
perform global optimizations between the two. See
:ref:`guide-build`.
#. The set of build varieties has been reduced to three: the
:term:`cool` variety for development and debugging, the :term:`hot`
variety for production, and the :term:`rash` variety for people who
like to live dangerously. See :ref:`topic-error-variety`.
#. The environment variable :envvar:`MPS_TELEMETRY_CONTROL` can now be
set to a space-separated list of event kinds. See
:ref:`topic-telemetry`.
#. Telemetry output is now emitted to the file named by the
environment variable :envvar:`MPS_TELEMETRY_FILENAME`, if it is
set. See :ref:`topic-telemetry`.
Interface changes
.................
#. Deprecated constants ``MPS_MESSAGE_TYPE_FINALIZATION``,
``MPS_MESSAGE_TYPE_GC`` and ``MPS_MESSAGE_TYPE_GC_START`` have been
removed. Use :c:func:`mps_message_type_finalization`,
:c:func:`mps_message_type_gc` and
:c:func:`mps_message_type_gc_start` instead.
#. Deprecated constants ``MPS_RANK_AMBIG``, ``MPS_RANK_EXACT`` and
``MPS_RANK_WEAK`` have been removed. Use :c:func:`mps_rank_ambig`,
:c:func:`mps_rank_exact` and :c:func:`mps_rank_weak` instead.
#. Deprecated functions with names starting ``mps_space_`` have been
removed. Use the functions with names starting ``mps_arena_``
instead.

View file

@ -120,31 +120,6 @@ many small objects. They must be used according to the
point or points.
.. c:function:: mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool, ...)
.. deprecated:: starting with version 1.112.
Use :c:func:`mps_ap_create_k` instead: the :term:`keyword
arguments` interface is more reliable and produces better
error messages.
An alternative to :c:func:`mps_ap_create_k` that takes its extra
arguments using the standard :term:`C` variable argument list
mechanism.
.. c:function:: mps_res_t mps_ap_create_v(mps_ap_t *ap_o, mps_pool_t pool, va_list args)
.. deprecated:: starting with version 1.112.
Use :c:func:`mps_ap_create_k` instead: the :term:`keyword
arguments` interface is more reliable and produces better
error messages.
An alternative to :c:func:`mps_ap_create_k` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism.
.. c:function:: void mps_ap_destroy(mps_ap_t ap)
Destroy an :term:`allocation point`.
@ -240,7 +215,8 @@ is thus::
size_t aligned_size = ALIGN(size); /* see note 1 */
do {
mps_res_t res = mps_reserve(&p, ap, aligned_size);
if (res != MPS_RES_OK) /* handle the error */;
if (res != MPS_RES_OK)
/* handle the error */;
/* p is now an ambiguous reference to the reserved block */
obj = p;
/* initialize obj */

View file

@ -92,32 +92,6 @@ the way that they acquire the memory to be managed.
:c:func:`mps_arena_destroy`.
.. c:function:: mps_res_t mps_arena_create(mps_arena_t *arena_o, mps_arena_class_t arena_class, ...)
.. deprecated:: starting with version 1.112.
Use :c:func:`mps_arena_create_k` instead: the :term:`keyword
arguments` interface is more reliable and produces better
error messages.
An alternative to :c:func:`mps_arena_create_k` that takes its
extra arguments using the standard :term:`C` variable argument
list mechanism.
.. c:function:: mps_res_t mps_arena_create_v(mps_arena_t *arena_o, mps_arena_class_t arena_class, va_list args)
.. deprecated:: starting with version 1.112.
Use :c:func:`mps_arena_create_k` instead: the :term:`keyword
arguments` interface is more reliable and produces better
error messages.
An alternative to :c:func:`mps_arena_create_k` that takes its
extra arguments using the standard :term:`C` ``va_list``
mechanism.
.. c:function:: void mps_arena_destroy(mps_arena_t arena)
Destroy an :term:`arena`.
@ -192,15 +166,6 @@ Client arenas
Client arenas have no mechanism for returning unused memory.
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_arena_create`, pass the size and base
address like this::
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t mps_arena_class_cl,
size_t size, mps_addr_t base)
.. c:function:: mps_res_t mps_arena_extend(mps_arena_t arena, mps_addr_t base, size_t size)
@ -311,15 +276,6 @@ Virtual memory arenas
res = mps_arena_create_k(&arena, mps_arena_class_vm(), args);
} MPS_ARGS_END(args);
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_arena_create`, pass the size like
this::
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t arena_class_vm(),
size_t size)
.. index::
single: arena; properties
@ -391,9 +347,18 @@ Arena properties
``arena`` is the arena.
Returns the total amount of memory that has been committed to RAM
Returns the total amount of memory that has been committed for use
by the MPS, in :term:`bytes (1)`.
For a :term:`virtual memory arena`, this is the amount of memory
mapped to RAM by the operating system's virtual memory interface.
For a :term:`client arena`, this is the amount of memory marked as
in use in the arena's page tables. This is not particularly
meaningful by itself, but it corresponds to the amount of mapped
memory that the MPS would use if switched to a virtual memory
arena.
The committed memory is generally larger than the sum of the sizes
of the allocated :term:`blocks`. The reasons for this are:
@ -420,10 +385,10 @@ Arena properties
state>`). If it is called when the arena is in the unclamped state
then the value may change after this function returns. A possible
use might be to call it just after :c:func:`mps_arena_collect` to
(over-)estimate the size of the heap.
estimate the size of the heap.
If you want to know how much memory the MPS is using then you're
probably interested in the value :c:func:`mps_arena_committed()`
probably interested in the value :c:func:`mps_arena_committed`
:c:func:`mps_arena_spare_committed`.
The amount of committed memory can be limited with the function
@ -447,12 +412,12 @@ Arena properties
.. note::
For a client arena, the reserved address may be lower than the
sum of the :c:macro:`MPS_KEY_ARENA_SIZE` keyword argument
passed to :c:func:`mps_arena_create_k` and the ``size``
arguments passed to :c:func:`mps_arena_extend`, because the
arena may be unable to use the whole of each chunk for reasons
of alignment.
For a :term:`client arena`, the reserved address space may be
lower than the sum of the :c:macro:`MPS_KEY_ARENA_SIZE`
keyword argument passed to :c:func:`mps_arena_create_k` and
the ``size`` arguments passed to :c:func:`mps_arena_extend`,
because the arena may be unable to use the whole of each chunk
for reasons of alignment.
.. c:function:: size_t mps_arena_spare_commit_limit(mps_arena_t arena)
@ -517,6 +482,11 @@ Arena properties
functions for limiting the amount of :term:`committed <mapped>`
memory.
.. note::
:term:`Client arenas` do not use spare committed memory, and
so this function always returns 0.
.. index::
single: arena; states
@ -839,114 +809,3 @@ Arena introspection
return storage to the operating system). For reliable results
call this function and interpret the result while the arena is
in the :term:`parked state`.
.. index::
pair: arena; protection
Protection interface
--------------------
.. c:function:: void mps_arena_expose(mps_arena_t arena)
.. deprecated:: starting with version 1.111.
Ensure that the MPS is not protecting any :term:`page` in the
:term:`arena` with a :term:`read barrier` or :term:`write
barrier`.
``mps_arena`` is the arena to expose.
This is expected to only be useful for debugging. The arena is
left in the :term:`clamped state`.
Since barriers are used during a collection, calling this function
has the same effect as calling :c:func:`mps_arena_park`: all
collections are run to completion, and the arena is clamped so
that no new collections begin. The MPS also uses barriers to
maintain :term:`remembered sets`, so calling this
function will effectively destroy the remembered sets and any
optimization gains from them.
Calling this function is time-consuming: any active collections
will be run to completion; and the next collection will have to
recompute all the remembered sets by scanning the entire arena.
The recomputation of the remembered sets can be avoided by calling
:c:func:`mps_arena_unsafe_expose_remember_protection` instead of
:c:func:`mps_arena_expose`, and by calling
:c:func:`mps_arena_unsafe_restore_protection` before calling
:c:func:`mps_arena_release`. Those functions have unsafe aspects
and place restrictions on what the :term:`client program` can do
(basically no exposed data can be changed).
.. c:function:: void mps_arena_unsafe_expose_remember_protection(mps_arena_t arena)
.. deprecated:: starting with version 1.111.
Ensure that the MPS is not protecting any :term:`page` in the
:term:`arena` with a :term:`read barrier` or :term:`write
barrier`. In addition, request the MPS to remember some parts of its
internal state so that they can be restored later.
``mps_arena`` is the arena to expose.
This function is the same as :c:func:`mps_arena_expose`, but
additionally causes the MPS to remember its protection state. The
remembered protection state can optionally be restored later by
calling the :c:func:`mps_arena_unsafe_restore_protection` function.
This is an optimization that avoids the MPS having to recompute
all the remembered sets by scanning the entire arena.
However, restoring the remembered protections is only safe if the
contents of the exposed pages have not been changed; therefore
this function should only be used if you do not intend to change
the pages, and the remembered protection must only be restored if
the pages have not been changed.
The MPS will only remember the protection state if resources
(memory) are available. If memory is low then only some or
possibly none of the protection state will be remembered, with a
corresponding necessity to recompute it later. The MPS provides no
mechanism for the :term:`client program` to determine whether the
MPS has in fact remembered the protection state.
The remembered protection state, if any, is discarded after
calling :c:func:`mps_arena_unsafe_restore_protection`, or as soon
as the arena leaves the :term:`clamped state` by calling
:c:func:`mps_arena_release`.
.. c:function:: void mps_arena_unsafe_restore_protection(mps_arena_t arena)
.. deprecated:: starting with version 1.111.
Restore the remembered protection state for an :term:`arena`.
``mps_arena`` is the arena to restore the protection state for.
This function restores the protection state that the MPS has
remembered when the :term:`client program` called
:c:func:`mps_arena_unsafe_expose_remember_protection`. The purpose
of remembering and restoring the protection state is to avoid the
need for the MPS to recompute all the :term:`remembered sets` by scanning the entire arena, that occurs when
:c:func:`mps_arena_expose` is used, and which causes the next
:term:`garbage collection` to be slow.
The client program must not change the exposed data between the
call to :c:func:`mps_arena_unsafe_expose_remember_protection` and
:c:func:`mps_arena_unsafe_restore_protection`. If the client
program has changed the exposed data then
:c:func:`mps_arena_unsafe_restore_protection` must not be called:
in this case simply call :c:func:`mps_arena_release`.
Calling this function does not release the arena from the clamped
state: :c:func:`mps_arena_release` must be called to continue
normal collections.
Calling this function causes the MPS to forget the remember
protection state; as a consequence the same remembered state
cannot be restored more than once.

View file

@ -0,0 +1,745 @@
.. index::
single: deprecated interfaces
.. _topic-deprecated:
Deprecated interfaces
=====================
This chapter documents the public symbols in the MPS interface that
are now deprecated. These symbols may be removed in any future release
(see :ref:`topic-interface-support` for details). If you are using one
of these symbols, then you should update your code to use the
supported interface.
.. note::
If you are relying on a deprecated interface, and there is no
supported alternative, please :ref:`contact us <contact>`. It
makes a difference if we know that someone is using a feature.
.. index::
single: deprecated interfaces; in version 1.115
Deprecated in version 1.115
...........................
.. c:type:: typedef mps_pool_class_t mps_class_t
.. deprecated::
The former name for :c:type:`mps_pool_class_t`, chosen when
pools were the only objects in the MPS that belonged to
classes.
.. c:function:: size_t mps_mv_free_size(mps_pool_t pool)
.. deprecated::
Use the generic function :c:func:`mps_pool_free_size` instead.
Return the total amount of free space in an MV pool.
``pool`` is the MV pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mv_size(mps_pool_t pool)
.. deprecated::
Use the generic function :c:func:`mps_pool_total_size`
instead.
Return the total size of an MV pool.
``pool`` is the MV pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.
.. c:function:: size_t mps_mvff_free_size(mps_pool_t pool)
.. deprecated::
Use the generic function :c:func:`mps_pool_free_size` instead.
Return the total amount of free space in an MVFF pool.
``pool`` is the MVFF pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mvff_size(mps_pool_t pool)
.. deprecated::
Use the generic function :c:func:`mps_pool_total_size`
instead.
Return the total size of an MVFF pool.
``pool`` is the MVFF pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.
.. c:function:: size_t mps_mvt_free_size(mps_pool_t pool)
.. deprecated::
Use the generic function :c:func:`mps_pool_free_size` instead.
Return the total amount of free space in an MVT pool.
``pool`` is the MVT pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mvt_size(mps_pool_t pool)
.. deprecated::
Use the generic function :c:func:`mps_pool_total_size`
instead.
Return the total size of an MVT pool.
``pool`` is the MVT pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.
.. index::
single: deprecated interfaces; in version 1.113
Deprecated in version 1.113
...........................
.. c:function:: MPS_ARGS_DONE(args)
.. deprecated::
Formerly this was used to finalize a list of :term:`keyword
arguments` before passing it to a function. It is no longer
needed.
.. index::
single: deprecated interfaces; in version 1.112
Deprecated in version 1.112
...........................
.. c:function:: mps_res_t mps_arena_create(mps_arena_t *arena_o, mps_arena_class_t arena_class, ...)
.. deprecated::
Use :c:func:`mps_arena_create_k` instead.
An alternative to :c:func:`mps_arena_create_k` that takes its
extra arguments using the standard :term:`C` variable argument
list mechanism.
When creating an arena of class :c:func:`mps_arena_class_cl`, pass
the values for the keyword arguments :c:macro:`MPS_KEY_ARENA_SIZE`
and :c:macro:`MPS_KEY_ARENA_CL_BASE` like this::
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t mps_arena_class_cl(),
size_t arena_size,
mps_addr_t cl_base)
When creating an arena of class :c:func:`mps_arena_class_vm`, pass
the value for the keyword argument :c:macro:`MPS_KEY_ARENA_SIZE`
like this::
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t mps_arena_class_vm(),
size_t arena_size)
.. c:function:: mps_res_t mps_arena_create_v(mps_arena_t *arena_o, mps_arena_class_t arena_class, va_list args)
.. deprecated::
Use :c:func:`mps_arena_create_k` instead.
An alternative to :c:func:`mps_arena_create_k` that takes its
extra arguments using the standard :term:`C` ``va_list``
mechanism. See :c:func:`mps_arena_create` for details of which
arguments to pass for the different arena classes.
.. c:function:: mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena, mps_pool_class_t pool_class, ...)
.. deprecated::
Use :c:func:`mps_pool_create_k` instead.
An alternative to :c:func:`mps_pool_create_k` that takes its
extra arguments using the standard :term:`C` variable argument
list mechanism.
When creating a pool of class :c:func:`mps_class_amc` or
:c:func:`mps_class_amcz`, pass the values for the keyword
arguments :c:macro:`MPS_KEY_FORMAT` and :c:macro:`MPS_KEY_CHAIN`
like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_amc(),
mps_fmt_t format,
mps_chain_t chain)
When creating a pool of class :c:func:`mps_class_ams`, pass the
values for the keyword arguments :c:macro:`MPS_KEY_FORMAT`,
:c:macro:`MPS_KEY_CHAIN` and ambiguous flag
:c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_ams(),
mps_fmt_t format,
mps_chain_t chain,
mps_bool_t ams_support_ambiguous)
When creating a pool of class :c:func:`mps_class_ams_debug`, pass
the values for the keyword arguments
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS`, :c:macro:`MPS_KEY_FORMAT`,
:c:macro:`MPS_KEY_CHAIN` and
:c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_ams_debug(),
mps_pool_debug_option_s *pool_debug_options,
mps_fmt_t format,
mps_chain_t chain,
mps_bool_t ams_support_ambiguous)
When creating a pool of class :c:func:`mps_class_awl`, pass the
values for the keyword arguments :c:macro:`MPS_KEY_FORMAT` and
:c:macro:`MPS_KEY_AWL_FIND_DEPENDENT` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_awl(),
mps_fmt_t format,
mps_awl_find_dependent_t awl_find_dependent)
When creating a pool of class :c:func:`mps_class_lo`, pass the
value for the keyword argument :c:macro:`MPS_KEY_FORMAT` like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_lo(),
mps_fmt_t format)
When creating a pool of class :c:func:`mps_class_mfs`, pass the
values for the keyword arguments :c:macro:`MPS_KEY_EXTEND_BY` and
:c:macro:`MPS_KEY_MFS_UNIT_SIZE` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mfs(),
size_t extend_by,
size_t unit_size)
When creating a pool of class :c:func:`mps_class_mv`, pass the
values for the keyword arguments :c:macro:`MPS_KEY_EXTEND_BY`,
:c:macro:`MPS_KEY_MEAN_SIZE`, and :c:macro:`MPS_KEY_MAX_SIZE` like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mv(),
size_t extend_by,
size_t mean_size,
size_t max_size)
When creating a pool of class :c:func:`mps_class_mv_debug`, pass
the values for the keyword arguments
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS`,
:c:macro:`MPS_KEY_EXTEND_BY`, :c:macro:`MPS_KEY_MEAN_SIZE` and
:c:macro:`MPS_KEY_MAX_SIZE` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mv_debug(),
mps_pool_debug_option_s *pool_debug_options,
size_t extend_by,
size_t mean_size,
size_t max_size)
When creating a pool of class :c:func:`mps_class_mvff`, pass the
values for the keyword arguments :c:macro:`MPS_KEY_EXTEND_BY`,
:c:macro:`MPS_KEY_MEAN_SIZE`, :c:macro:`MPS_KEY_ALIGN`,
:c:macro:`MPS_KEY_MVFF_SLOT_HIGH`,
:c:macro:`MPS_KEY_MVFF_ARENA_HIGH` and
:c:macro:`MPS_KEY_MVFF_FIRST_FIT` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mvff(),
size_t extend_by,
size_t mean_size,
mps_align_t align,
mps_bool_t mvff_slot_high,
mps_bool_t mvff_arena_high,
mps_bool_t mvff_first_fit)
When creating a pool of class :c:func:`mps_class_mvff_debug`, pass
the values for the keyword arguments
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS`,
:c:macro:`MPS_KEY_EXTEND_BY`, :c:macro:`MPS_KEY_MEAN_SIZE`,
:c:macro:`MPS_KEY_ALIGN`, :c:macro:`MPS_KEY_MVFF_SLOT_HIGH`,
:c:macro:`MPS_KEY_MVFF_ARENA_HIGH`, and
:c:macro:`MPS_KEY_MVFF_FIRST_FIT` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mvff_debug(),
mps_pool_debug_option_s *pool_debug_options,
size_t extend_by,
size_t mean_size,
mps_align_t align,
mps_bool_t mvff_slot_high,
mps_bool_t mvff_arena_high,
mps_bool_t mvff_first_fit)
When creating a pool of class :c:func:`mps_class_mvt`, pass the
values for the keyword arguments :c:macro:`MPS_KEY_MIN_SIZE`,
:c:macro:`MPS_KEY_MEAN_SIZE`, :c:macro:`MPS_KEY_MAX_SIZE`,
:c:macro:`MPS_KEY_MVT_RESERVE_DEPTH` and
:c:macro:`MPS_KEY_MVT_FRAG_LIMIT` like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_mvt(),
size_t min_size,
size_t mean_size,
size_t max_size,
mps_word_t mvt_reserve_depth,
mps_word_t mvt_frag_limit)
.. note::
The ``mvt_frag_limit`` is a percentage from 0 to 100
inclusive when passed to :c:func:`mps_pool_create`, not a
double from 0.0 to 1.0 as in :c:func:`mps_pool_create_k`.
When creating a pool of class :c:func:`mps_class_snc`, pass the
value for the keyword argument :c:macro:`MPS_KEY_FORMAT` like
this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_pool_class_t mps_class_snc(),
mps_fmt_t format)
.. c:function:: mps_res_t mps_pool_create_v(mps_pool_t *pool_o, mps_arena_t arena, mps_pool_class_t pool_class, va_list args)
.. deprecated::
Use :c:func:`mps_pool_create_k` instead.
An alternative to :c:func:`mps_pool_create_k` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism. See
:c:func:`mps_pool_create` for details of which arguments to pass
for the different pool classes.
.. c:function:: mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool, ...)
.. deprecated::
Use :c:func:`mps_ap_create_k` instead.
An alternative to :c:func:`mps_ap_create_k` that takes its extra
arguments using the standard :term:`C` variable argument list
mechanism.
When creating an allocation point on a pool of class
:c:func:`mps_class_ams`, :c:func:`mps_class_ams_debug`,
:c:func:`mps_class_awl` or :c:func:`mps_class_snc`, pass the
keyword argument :c:macro:`MPS_KEY_RANK` like this::
mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool,
mps_rank_t rank)
.. c:function:: mps_res_t mps_ap_create_v(mps_ap_t *ap_o, mps_pool_t pool, va_list args)
.. deprecated::
Use :c:func:`mps_ap_create_k` instead.
An alternative to :c:func:`mps_ap_create_k` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism. See
:c:func:`mps_ap_create` for details of which arguments to pass
for the different pool classes.
.. c:type:: mps_fmt_A_s
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
The type of the structure used to create an :term:`object format`
of variant A. ::
typedef struct mps_fmt_A_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_A_s;
The fields of this structure correspond to the keyword arguments
to :c:func:`mps_fmt_create_k`, except for ``copy``, which is not
used. In older versions of the MPS this was a *copy method*
that copied objects belonging to this format.
.. c:function:: mps_res_t mps_fmt_create_A(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_A_s *fmt_A)
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
Create an :term:`object format` based on a description of an
object format of variant A.
.. c:type:: mps_fmt_B_s
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
The type of the structure used to create an :term:`object format`
of variant B. ::
typedef struct mps_fmt_B_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
mps_fmt_class_t mps_class;
} mps_fmt_B_s;
Variant B is the same as variant A except for the addition of the
``mps_class`` method. See :c:type:`mps_fmt_A_s`.
.. c:function:: mps_res_t mps_fmt_create_B(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_B_s *fmt_B)
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
Create an :term:`object format` based on a description of an
object format of variant B.
.. c:type:: mps_fmt_auto_header_s
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
The type of the structure used to create an :term:`object format`
of variant auto-header. ::
typedef struct mps_fmt_auto_header_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
size_t mps_headerSize;
} mps_fmt_auto_header_s;
Variant auto-header is the same as variant A except for the
removal of the unused ``copy`` method, and the addition of the
``mps_headerSize`` field. See :c:type:`mps_fmt_A_s`.
.. c:function:: mps_res_t mps_fmt_create_auto_header(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_auto_header_s *fmt_ah)
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
Create an :term:`object format` based on a description of an
object format of variant auto-header.
.. c:type:: mps_fmt_fixed_s
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
The type of the structure used to create an :term:`object format`
of variant fixed. ::
typedef struct mps_fmt_fixed_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_fixed_s;
Variant fixed is the same as variant A except for the removal of
the unused ``copy`` method, and the lack of a ``skip`` method
(this is not needed because the objects are fixed in size). See
:c:type:`mps_fmt_A_s`.
.. c:function:: mps_res_t mps_fmt_create_fixed(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_fixed_s *fmt_fixed)
.. deprecated::
Use :c:func:`mps_fmt_create_k` instead.
Create an :term:`object format` based on a description of an
object format of variant fixed.
.. index::
single: deprecated interfaces; in version 1.111
Deprecated in version 1.111
...........................
.. c:function:: mps_res_t mps_fix(mps_ss_t ss, mps_addr_t *ref_io)
.. deprecated::
Use :c:func:`MPS_FIX1` and :c:func:`MPS_FIX2` instead.
:term:`Fix` a :term:`reference`.
This is a function equivalent to::
MPS_SCAN_BEGIN(ss);
res = MPS_FIX12(ss, ref_io);
MPS_SCAN_END(ss);
return res;
Because :term:`scanning <scan>` is an operation on the
:term:`critical path`, we recommend that you use
:c:func:`MPS_FIX12` (or :c:func:`MPS_FIX1` and :c:func:`MPS_FIX2`)
to ensure that the "stage 1 fix" is inlined.
.. note::
If you call this between :c:func:`MPS_SCAN_BEGIN` and
:c:func:`MPS_SCAN_END`, you must use :c:func:`MPS_FIX_CALL` to
ensure that the scan state is passed correctly.
.. c:function:: mps_word_t mps_telemetry_control(mps_word_t reset_mask, mps_word_t flip_mask)
.. deprecated::
Use :c:func:`mps_telemetry_get`,
:c:func:`mps_telemetry_reset`, and :c:func:`mps_telemetry_set`
instead.
Update and return the :term:`telemetry filter`.
``reset_mask`` is a :term:`bitmask` indicating the bits in the
telemetry filter that should be reset.
``flip_mask`` is a bitmask indicating the bits in the telemetry
filter whose value should be flipped after the resetting.
Returns the previous value of the telemetry filter, prior to the
reset and the flip.
The parameters ``reset_mask`` and ``flip_mask`` allow the
specification of any binary operation on the filter control. For
typical operations, the parameters should be set as follows:
============ ============== =============
Operation ``reset_mask`` ``flip_mask``
============ ============== =============
``set(M)`` ``M`` ``M``
------------ -------------- -------------
``reset(M)`` ``M`` ``0``
------------ -------------- -------------
``flip(M)`` ``0`` ``M``
------------ -------------- -------------
``read()`` ``0`` ``0``
============ ============== =============
.. c:function:: void mps_tramp(void **r_o, mps_tramp_t f, void *p, size_t s)
.. deprecated::
The MPS trampoline is no longer required on any operating
system supported by the MPS.
Call a function via the MPS trampoline.
``r_o`` points to a location that will store the result of calling
``f``.
``f`` is the function to call.
``p`` and ``s`` are arguments that will be passed to ``f`` each
time it is called. This is intended to make it easy to pass, for
example, an array and its size as parameters.
The MPS relies on :term:`barriers (1)` to protect memory
that is in an inconsistent state. On some operating systems,
barrier hits generate exceptions that have to be caught by a
handler that is on the stack. On these operating systems, any code
that uses memory managed by the MPS must be called from inside
such an exception handler, that is, inside a call to
:c:func:`mps_tramp`.
If you have multiple threads that run code that uses memory
managed by the MPS, each thread must execute such code inside a
call to :c:func:`mps_tramp`.
.. index::
single: trampoline
.. c:type:: void *(*mps_tramp_t)(void *p, size_t s)
.. deprecated::
The MPS trampoline is no longer required on any operating
system supported by the MPS.
The type of a function called by :c:func:`mps_tramp`.
``p`` and ``s`` are the corresponding arguments that were passed
to :c:func:`mps_tramp`.
.. c:function:: void mps_arena_expose(mps_arena_t arena)
.. deprecated::
If you need access to protected memory for debugging,
:ref:`contact us <contact>`.
Ensure that the MPS is not protecting any :term:`page` in the
:term:`arena` with a :term:`read barrier` or :term:`write
barrier`.
``arena`` is the arena to expose.
This is expected to only be useful for debugging. The arena is
left in the :term:`clamped state`.
Since barriers are used during a collection, calling this function
has the same effect as calling :c:func:`mps_arena_park`: all
collections are run to completion, and the arena is clamped so
that no new collections begin. The MPS also uses barriers to
maintain :term:`remembered sets`, so calling this
function will effectively destroy the remembered sets and any
optimization gains from them.
Calling this function is time-consuming: any active collections
will be run to completion; and the next collection will have to
recompute all the remembered sets by scanning the entire arena.
The recomputation of the remembered sets can be avoided by calling
:c:func:`mps_arena_unsafe_expose_remember_protection` instead of
:c:func:`mps_arena_expose`, and by calling
:c:func:`mps_arena_unsafe_restore_protection` before calling
:c:func:`mps_arena_release`. Those functions have unsafe aspects
and place restrictions on what the :term:`client program` can do
(basically no exposed data can be changed).
.. c:function:: void mps_arena_unsafe_expose_remember_protection(mps_arena_t arena)
.. deprecated::
If you need access to protected memory for debugging,
:ref:`contact us <contact>`.
Ensure that the MPS is not protecting any :term:`page` in the
:term:`arena` with a :term:`read barrier` or :term:`write
barrier`. In addition, request the MPS to remember some parts of its
internal state so that they can be restored later.
``arena`` is the arena to expose.
This function is the same as :c:func:`mps_arena_expose`, but
additionally causes the MPS to remember its protection state. The
remembered protection state can optionally be restored later by
calling the :c:func:`mps_arena_unsafe_restore_protection` function.
This is an optimization that avoids the MPS having to recompute
all the remembered sets by scanning the entire arena.
However, restoring the remembered protections is only safe if the
contents of the exposed pages have not been changed; therefore
this function should only be used if you do not intend to change
the pages, and the remembered protection must only be restored if
the pages have not been changed.
The MPS will only remember the protection state if resources
(memory) are available. If memory is low then only some or
possibly none of the protection state will be remembered, with a
corresponding necessity to recompute it later. The MPS provides no
mechanism for the :term:`client program` to determine whether the
MPS has in fact remembered the protection state.
The remembered protection state, if any, is discarded after
calling :c:func:`mps_arena_unsafe_restore_protection`, or as soon
as the arena leaves the :term:`clamped state` by calling
:c:func:`mps_arena_release`.
.. c:function:: void mps_arena_unsafe_restore_protection(mps_arena_t arena)
.. deprecated::
If you need access to protected memory for debugging,
:ref:`contact us <contact>`.
Restore the remembered protection state for an :term:`arena`.
``arena`` is the arena to restore the protection state for.
This function restores the protection state that the MPS has
remembered when the :term:`client program` called
:c:func:`mps_arena_unsafe_expose_remember_protection`. The purpose
of remembering and restoring the protection state is to avoid the
need for the MPS to recompute all the :term:`remembered sets` by
scanning the entire arena, that occurs when
:c:func:`mps_arena_expose` is used, and which causes the next
:term:`garbage collection` to be slow.
The client program must not change the exposed data between the
call to :c:func:`mps_arena_unsafe_expose_remember_protection` and
:c:func:`mps_arena_unsafe_restore_protection`. If the client
program has changed the exposed data then
:c:func:`mps_arena_unsafe_restore_protection` must not be called:
in this case simply call :c:func:`mps_arena_release`.
Calling this function does not release the arena from the clamped
state: :c:func:`mps_arena_release` must be called to continue
normal collections.
Calling this function causes the MPS to forget the remembered
protection state; as a consequence the same remembered state
cannot be restored more than once.

View file

@ -76,31 +76,28 @@ Result codes
A :term:`result code` indicating that an operation could not be
completed as requested without exceeding the :term:`commit limit`.
You need to deallocate something to make more space, or increase
You need to deallocate something or allow the :term:`garbage
collector` to reclaim something to make more space, or increase
the commit limit by calling :c:func:`mps_arena_commit_limit_set`.
.. c:macro:: MPS_RES_FAIL
A :term:`result code` indicating that something went wrong that
does not fall under the description of any other result code. The
exact meaning depends on the function that returned this result
code.
does not fall under the description of any other result code.
.. c:macro:: MPS_RES_IO
A :term:`result code` indicating that an input/output error
occurred. The exact meaning depends on the function that returned
this result code.
occurred in the :term:`telemetry` system.
.. c:macro:: MPS_RES_LIMIT
A :term:`result code` indicating that an operation could not be
completed as requested because of an internal limitation of the
MPS. The exact meaning depends on the function that returned this
result code.
MPS.
.. c:macro:: MPS_RES_MEMORY
@ -109,7 +106,7 @@ Result codes
completed because there wasn't enough memory available.
You need to deallocate something or allow the :term:`garbage
collector` to reclaim something to free enough memory, or expand
collector` to reclaim something to free enough memory, or extend
the :term:`arena` (if you're using an arena for which that does
not happen automatically).
@ -140,27 +137,23 @@ Result codes
A :term:`result code` indicating that an operation could not be
completed as requested because an invalid parameter was passed to
the operation. The exact meaning depends on the function that
returned this result code.
the operation.
.. c:macro:: MPS_RES_RESOURCE
A :term:`result code` indicating that an operation could not be
completed as requested because the MPS could not obtain a needed
resource. The resource in question depends on the operation.
resource. It can be returned when the MPS runs out of
:term:`address space`. If this happens, you need to reclaim memory
within your process (as for the result code
:c:macro:`MPS_RES_MEMORY`).
Two special cases have their own result codes: when the MPS runs
out of committed memory, it returns :c:macro:`MPS_RES_MEMORY`, and
when it cannot proceed without exceeding the :term:`commit limit`,
it returns :c:macro:`MPS_RES_COMMIT_LIMIT`.
This result code can be returned when the MPS runs out of
:term:`virtual memory`. If this happens, you need to reclaim
memory within your process (as for the result code
:c:macro:`MPS_RES_MEMORY`), or terminate other processes running
on the same machine.
.. c:macro:: MPS_RES_UNIMPL
@ -272,13 +265,49 @@ this documentation.
:c:type:`mps_fmt_t` for this argument.
``global.c: RingIsSingle(&arena->chainRing)``
The client program called :c:func:`mps_arena_destroy` without
destroying all the :term:`generation chains` belonging to the
arena. It is necessary to call :c:func:`mps_chain_destroy` first.
``global.c: RingIsSingle(&arena->formatRing)``
The client program called :c:func:`mps_arena_destroy` without
destroying all the :term:`object formats` belonging to the arena.
It is necessary to call :c:func:`mps_fmt_destroy` first.
``global.c: RingIsSingle(&arena->rootRing)``
The client program called :c:func:`mps_arena_destroy` without
destroying all the :term:`roots` belonging to the arena.
It is necessary to call :c:func:`mps_root_destroy` first.
``global.c: RingIsSingle(&arena->threadRing)``
The client program called :c:func:`mps_arena_destroy` without
deregistering all the :term:`threads` belonging to the arena.
It is necessary to call :c:func:`mps_thread_dereg` first.
``global.c: RingLength(&arenaGlobals->poolRing) == 5``
The client program called :c:func:`mps_arena_destroy` without
destroying all the :term:`pools` belonging to the arena.
It is necessary to call :c:func:`mps_pool_destroy` first.
``lockix.c: res == 0``
``lockw3.c: lock->claims == 0``
The client program has made a re-entrant call into the MPS. Look
at the backtrace to see what it was. Common culprits are
:term:`format methods` and :term:`stepper functions`.
at the backtrace to see what it was. Common culprits are signal
handlers, assertion handlers, :term:`format methods`, and
:term:`stepper functions`.
``locus.c: chain->activeTraces == TraceSetEMPTY``
@ -305,13 +334,19 @@ this documentation.
condition?
``ring.c: ring->next == ring``
``poolsnc.c: foundSeg``
The client program destroyed an object without having destroyed
all the objects that it owns first. For example, it destroyed an
arena without first destroying all pools in that arena, or it
destroyed a pool without first destroying all allocation points
created on that pool.
The client program passed an incorrect ``frame`` argument to
:c:func:`mps_ap_frame_pop`. This argument must be the result from
a previous call to :c:func:`mps_ap_frame_push` on the same
allocation point.
``seg.c: gcseg->buffer == NULL``
The client program destroyed pool without first destroying all the
allocation points created on that pool. The allocation points must
be destroyed first.
``trace.c: ss->rank < RankEXACT``
@ -320,7 +355,7 @@ this documentation.
for finalization, and then continued to run the garbage collector.
See :ref:`topic-finalization-cautions` under
:ref:`topic-finalization`, which says, "You must destroy these
pools by following the “safe tear-down” procedure described under
pools by following the safe tear-down procedure described under
:c:func:`mps_pool_destroy`."
@ -330,22 +365,24 @@ this documentation.
reference to an object that moved. See
:ref:`topic-scanning-protocol`, which says, "If :c:func:`MPS_FIX2`
returns :c:macro:`MPS_RES_OK`, it may have updated the reference.
If necessary, make sure that the updated reference is stored back
to the region being scanned."
Make sure that the updated reference is stored back to the region
being scanned."
.. index::
single: error handling; varieties
single: variety
.. _topic-error-variety:
Varieties
---------
The MPS has three behaviours with respect to internal checking and
:ref:`telemetry <topic-telemetry>`, which need to be selected at
compile time, by defining one of the following preprocessor
constants. If none is specified then :c:macro:`CONFIG_VAR_HOT` is the
default.
The MPS has three *varieties* which have different levels of internal
checking and :ref:`telemetry <topic-telemetry>`. The variety can be
selected at compile time, by defining one of the following
preprocessor constants. If none is specified then
:c:macro:`CONFIG_VAR_HOT` is the default.
.. index::
@ -354,7 +391,7 @@ default.
.. c:macro:: CONFIG_VAR_COOL
The cool variety is intended for development and testing.
The *cool variety* is intended for development and testing.
All functions check the consistency of their data structures and may
assert, including functions on the :term:`critical path`.
@ -372,7 +409,7 @@ default.
.. c:macro:: CONFIG_VAR_HOT
The hot variety is intended for production and deployment.
The *hot variety* is intended for production and deployment.
Some functions check the consistency of their data structures and
may assert, namely those not on the :term:`critical path`. However,
@ -389,7 +426,7 @@ default.
.. c:macro:: CONFIG_VAR_RASH
The rash variety is intended for mature integrations, or for
The *rash variety* is intended for mature integrations, or for
developers who like living dangerously.
No functions check the consistency of their data structures and

View file

@ -179,6 +179,20 @@ There are some cautions to be observed when using in-band headers:
#. Not all :term:`pool classes` support objects with in-band headers.
See the documentation for the pool class.
.. note::
A :term:`client program` that allocates objects with
:term:`in-band headers` has to make a choice about how to
represent references to those objects. It can represent them using
:term:`base pointers` (which is convenient for allocation, since
:c:func:`mps_reserve` returns a base pointer, but requires
decoding when scanning) or using :term:`client pointers` (which is
convenient for scanning, since the :term:`scan method` takes a
client pointer, but requires encoding on allocation). Either
approach will work, but :term:`client pointers` are normally the
better choice, since scanning is normally more
performance-critical than allocation.
.. index::
pair: object format; cautions
@ -221,9 +235,9 @@ Cautions
#. Format methods must use no more than 64 words of stack space.
This restriction is necessary to avoid stack overflow in the MPS;
see :mps:ref:`design.mps.sp` for details. If your application has
format methods that need more stack space than this, :ref:`contact
us <contact>`.
see :ref:`design-sp` for details. If your application has format
methods that need more stack space than this, :ref:`contact us
<contact>`.
#. Format methods must not:
@ -535,137 +549,3 @@ Object format introspection
c. memory not managed by the MPS;
It must not access other memory managed by the MPS.
Obsolete interface
------------------
.. deprecated:: starting with version 1.112.
Use :c:func:`mps_ap_create_k` instead: the :term:`keyword
arguments` interface is more flexible and easier to understand.
Formerly the only way to create object formats was to describe the
format in the form of a *format variant structure*.
There are four format variants.
* Variant A (:c:type:`mps_fmt_A_s`): for objects without
:term:`in-band headers`.
* Variant B (:c:type:`mps_fmt_B_s`): as variant A, but with the
addition of a class method.
* Variant auto-header (:c:type:`mps_fmt_auto_header_s`): for objects
with :term:`in-band headers`.
* Variant fixed (:c:type:`mps_fmt_fixed_s`): for fixed-size objects.
The client program creates an object format by construct a format
variant structure and then calling the appropriate ``mps_fmt_create_``
function for the variant. The variant structure can then be disposed
of.
.. c:type:: mps_fmt_A_s
The type of the structure used to create an :term:`object format`
of variant A. ::
typedef struct mps_fmt_A_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_A_s;
The fields of this structure correspond to the keyword arguments
to :c:func:`mps_fmt_create_k`, except for ``copy``, which is not
used. In older versions of the MPS this was a *copy method*
that copied objects belonging to this format.
.. c:function:: mps_res_t mps_fmt_create_A(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_A_s *fmt_A)
Create an :term:`object format` based on a description of an
object format of variant A.
.. c:type:: mps_fmt_B_s
The type of the structure used to create an :term:`object format`
of variant B. ::
typedef struct mps_fmt_B_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
mps_fmt_class_t mps_class;
} mps_fmt_B_s;
Variant B is the same as variant A except for the addition of the
``mps_class`` method. See :c:type:`mps_fmt_A_s`.
.. c:function:: mps_res_t mps_fmt_create_B(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_B_s *fmt_B)
Create an :term:`object format` based on a description of an
object format of variant B.
.. c:type:: mps_fmt_auto_header_s
The type of the structure used to create an :term:`object format`
of variant auto-header. ::
typedef struct mps_fmt_auto_header_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
size_t mps_headerSize;
} mps_fmt_auto_header_s;
Variant auto-header is the same as variant A except for the
removal of the unused ``copy`` method, and the addition of the
``mps_headerSize`` field. See :c:type:`mps_fmt_A_s`.
.. c:function:: mps_res_t mps_fmt_create_auto_header(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_auto_header_s *fmt_ah)
Create an :term:`object format` based on a description of an
object format of variant auto-header.
.. c:type:: mps_fmt_fixed_s
The type of the structure used to create an :term:`object format`
of variant fixed. ::
typedef struct mps_fmt_fixed_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_fixed_s;
Variant fixed is the same as variant A except for the removal of
the unused ``copy`` method, and the lack of a ``skip`` method
(this is not needed because the objects are fixed in size). See
:c:type:`mps_fmt_A_s`.
.. c:function:: mps_res_t mps_fmt_create_fixed(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_fixed_s *fmt_fixed)
Create an :term:`object format` based on a description of an
object format of variant fixed.

View file

@ -29,3 +29,5 @@ Reference
plinth
platform
porting
deprecated

View file

@ -35,6 +35,10 @@ Support policy
a version in which the symbol (or reliance on some of its
behaviour) is deprecated.
Symbols may be deprecated in their old place in the reference
manual, or they may be moved to the :ref:`topic-deprecated`
chapter.
.. note::
If you are relying on a feature and you see that it's
@ -204,7 +208,8 @@ Instead, we recommend this approach::
mps_addr_t p;
struct foo *fp;
res = mps_alloc(&p, pool, sizeof(struct foo));
if(res) /* handle error case */;
if (res != MPS_RES_OK)
/* handle error case */;
fp = p;
This has defined behaviour because conversion from ``void *`` to any

Some files were not shown because too many files have changed in this diff Show more