mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 20:41:23 +00:00
Catch-up merge from masters.
Copied from Perforce Change: 188921 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
bdc1a92a18
commit
a2f78d0df6
154 changed files with 3259 additions and 2100 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ lii3gc
|
|||
lii6gc
|
||||
lii6ll
|
||||
w3i3mv
|
||||
w3i3pc
|
||||
w3i6mv
|
||||
w3i6pc
|
||||
xci3gc
|
||||
xci6ll
|
||||
# Visual Studio junk
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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(®_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
|
||||
|
|
|
|||
|
|
@ -16,9 +16,8 @@ MPMPF = \
|
|||
[than] \
|
||||
[vman]
|
||||
|
||||
!INCLUDE commpre.nmk
|
||||
!INCLUDE mv.nmk
|
||||
!INCLUDE commpost.nmk
|
||||
!INCLUDE comm.nmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
206
mps/code/arena.c
206
mps/code/arena.c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
216
mps/design/an.txt
Normal 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
127
mps/design/bootstrap.txt
Normal 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.**
|
||||
|
|
@ -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
189
mps/design/exec-env.txt
Normal 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.**
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
96
mps/design/guide.review.txt
Normal file
96
mps/design/guide.review.txt
Normal 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.**
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.**
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
======================== ==============================================
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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&view=status%3dopen&display=Job:Priority:Title&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&view=status%3dopen&display=Job:Priority:Title&sort=Priority">All open issues</a>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ Old design
|
|||
poolmv
|
||||
poolmvt
|
||||
poolmvff
|
||||
protan
|
||||
protli
|
||||
protsu
|
||||
protocol
|
||||
|
|
@ -61,4 +60,3 @@ Old design
|
|||
version
|
||||
vmo1
|
||||
vmso
|
||||
writef
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>`
|
||||
|
|
|
|||
|
|
@ -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>`.
|
||||
|
||||
|
|
|
|||
|
|
@ -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`).
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@ Guide
|
|||
debug
|
||||
perf
|
||||
advanced
|
||||
|
||||
malloc
|
||||
|
|
|
|||
|
|
@ -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::
|
||||
|
|
|
|||
70
mps/manual/source/guide/malloc.rst
Normal file
70
mps/manual/source/guide/malloc.rst
Normal 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();
|
||||
}
|
||||
|
|
@ -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
|
||||
-----------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
745
mps/manual/source/topic/deprecated.rst
Normal file
745
mps/manual/source/topic/deprecated.rst
Normal 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.
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -29,3 +29,5 @@ Reference
|
|||
plinth
|
||||
platform
|
||||
porting
|
||||
deprecated
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue