mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 12:21:25 -08:00
Catch-up merge from masters.
Copied from Perforce Change: 188928 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
5dccd2e006
526 changed files with 8326 additions and 5227 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
|
||||
|
|
|
|||
|
|
@ -231,13 +231,13 @@ Count ABQDepth(ABQ abq)
|
|||
}
|
||||
|
||||
|
||||
/* ABQIterate -- call 'iterate' for each element in an ABQ */
|
||||
void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP, Size closureS)
|
||||
/* ABQIterate -- call 'visitor' for each element in an ABQ */
|
||||
void ABQIterate(ABQ abq, ABQVisitor visitor, void *closureP, Size closureS)
|
||||
{
|
||||
Index copy, index, in;
|
||||
|
||||
AVERT(ABQ, abq);
|
||||
AVER(FUNCHECK(iterate));
|
||||
AVER(FUNCHECK(visitor));
|
||||
|
||||
copy = abq->out;
|
||||
index = abq->out;
|
||||
|
|
@ -247,7 +247,7 @@ void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP, Size closureS
|
|||
void *element = ABQElement(abq, index);
|
||||
Bool delete = FALSE;
|
||||
Bool cont;
|
||||
cont = (*iterate)(&delete, element, closureP, closureS);
|
||||
cont = (*visitor)(&delete, element, closureP, closureS);
|
||||
AVERT(Bool, cont);
|
||||
AVERT(Bool, delete);
|
||||
if (!delete) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* abq.h: QUEUE INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: A fixed-length FIFO queue.
|
||||
*
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
typedef struct ABQStruct *ABQ;
|
||||
typedef Res (*ABQDescribeElement)(void *element, mps_lib_FILE *stream, Count depth);
|
||||
typedef Bool (*ABQIterateMethod)(Bool *deleteReturn, void *element, void *closureP, Size closureS);
|
||||
typedef Bool (*ABQVisitor)(Bool *deleteReturn, void *element, void *closureP, Size closureS);
|
||||
|
||||
extern Res ABQInit(Arena arena, ABQ abq, void *owner, Count elements, Size elementSize);
|
||||
extern Bool ABQCheck(ABQ abq);
|
||||
|
|
@ -36,7 +36,7 @@ extern Res ABQDescribe(ABQ abq, ABQDescribeElement describeElement, mps_lib_FILE
|
|||
extern Bool ABQIsEmpty(ABQ abq);
|
||||
extern Bool ABQIsFull(ABQ abq);
|
||||
extern Count ABQDepth(ABQ abq);
|
||||
extern void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP, Size closureS);
|
||||
extern void ABQIterate(ABQ abq, ABQVisitor visitor, void *closureP, Size closureS);
|
||||
|
||||
|
||||
/* Types */
|
||||
|
|
@ -63,7 +63,7 @@ typedef struct ABQStruct
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,85 +7,17 @@ PFM = ananmv
|
|||
|
||||
PFMDEFS = /DCONFIG_PF_ANSI /DCONFIG_THREAD_SINGLE
|
||||
|
||||
# MPM platform-specific sources.
|
||||
MPMPF = \
|
||||
<lockan> \
|
||||
<prmcan> \
|
||||
<protan> \
|
||||
<span> \
|
||||
<ssan> \
|
||||
<than> \
|
||||
<vman>
|
||||
[lockan] \
|
||||
[prmcan] \
|
||||
[protan] \
|
||||
[span] \
|
||||
[ssan] \
|
||||
[than] \
|
||||
[vman]
|
||||
|
||||
!INCLUDE commpre.nmk
|
||||
!INCLUDE mv.nmk
|
||||
|
||||
|
||||
# Source to object file mappings and CFLAGS amalgamation
|
||||
#
|
||||
# %%VARIETY %%PART: When adding a new variety or part, add new macros which
|
||||
# expand to the files included in the part for each variety
|
||||
#
|
||||
# %%VARIETY: When adding a new variety, add a CFLAGS macro which expands to
|
||||
# the flags that that variety should use when compiling C. And a LINKFLAGS
|
||||
# macro which expands to the flags that the variety should use when building
|
||||
# executables. And a LIBFLAGS macro which expands to the flags that the
|
||||
# variety should use when building libraries
|
||||
|
||||
!IF "$(VARIETY)" == "hot"
|
||||
CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST)
|
||||
CFLAGSSQL=$(CFLAGSSQLPRE) $(CFHOT) $(CFLAGSSQLPOST)
|
||||
LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT)
|
||||
LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT)
|
||||
MPMOBJ0 = $(MPM:<=ananmv\hot\)
|
||||
FMTDYOBJ0 = $(FMTDY:<=ananmv\hot\)
|
||||
FMTTESTOBJ0 = $(FMTTEST:<=ananmv\hot\)
|
||||
FMTSCHEMEOBJ0 = $(FMTSCHEME:<=ananmv\hot\)
|
||||
POOLNOBJ0 = $(POOLN:<=ananmv\hot\)
|
||||
TESTLIBOBJ0 = $(TESTLIB:<=ananmv\hot\)
|
||||
TESTTHROBJ0 = $(TESTTHR:<=ananmv\hot\)
|
||||
|
||||
!ELSEIF "$(VARIETY)" == "cool"
|
||||
CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST)
|
||||
CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST)
|
||||
LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL)
|
||||
LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL)
|
||||
MPMOBJ0 = $(MPM:<=ananmv\cool\)
|
||||
FMTDYOBJ0 = $(FMTDY:<=ananmv\cool\)
|
||||
FMTTESTOBJ0 = $(FMTTEST:<=ananmv\cool\)
|
||||
FMTSCHEMEOBJ0 = $(FMTSCHEME:<=ananmv\cool\)
|
||||
POOLNOBJ0 = $(POOLN:<=ananmv\cool\)
|
||||
TESTLIBOBJ0 = $(TESTLIB:<=ananmv\cool\)
|
||||
TESTTHROBJ0 = $(TESTTHR:<=ananmv\cool\)
|
||||
|
||||
!ELSEIF "$(VARIETY)" == "rash"
|
||||
CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST)
|
||||
CFLAGSSQL=$(CFLAGSSQLPRE) $(CFRASH) $(CFLAGSSQLPOST)
|
||||
LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH)
|
||||
LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH)
|
||||
MPMOBJ0 = $(MPM:<=ananmv\rash\)
|
||||
FMTDYOBJ0 = $(FMTDY:<=ananmv\rash\)
|
||||
FMTTESTOBJ0 = $(FMTTEST:<=ananmv\rash\)
|
||||
FMTSCHEMEOBJ0 = $(FMTSCHEME:<=ananmv\rash\)
|
||||
POOLNOBJ0 = $(POOLN:<=ananmv\rash\)
|
||||
TESTLIBOBJ0 = $(TESTLIB:<=ananmv\rash\)
|
||||
TESTTHROBJ0 = $(TESTTHR:<=ananmv\rash\)
|
||||
|
||||
!ENDIF
|
||||
|
||||
# %%PART: When adding a new part, add new macros which expand to the object
|
||||
# files included in the part
|
||||
|
||||
MPMOBJ = $(MPMOBJ0:>=.obj)
|
||||
FMTDYOBJ = $(FMTDYOBJ0:>=.obj)
|
||||
FMTTESTOBJ = $(FMTTESTOBJ0:>=.obj)
|
||||
FMTSCHEMEOBJ = $(FMTSCHEMEOBJ0:>=.obj)
|
||||
POOLNOBJ = $(POOLNOBJ0:>=.obj)
|
||||
TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj)
|
||||
TESTTHROBJ = $(TESTTHROBJ0:>=.obj)
|
||||
|
||||
|
||||
!INCLUDE commpost.nmk
|
||||
!INCLUDE comm.nmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_SPARE, rnd_double());
|
||||
die(stress(arena, NULL, align, randomSizeAligned, "MVFF",
|
||||
mps_class_mvff(), args), "stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
|
|||
214
mps/code/arena.c
214
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));
|
||||
|
|
@ -290,14 +280,51 @@ failGlobalsInit:
|
|||
* platforms, knowing that it has no effect. To do that, the key must
|
||||
* exist on all platforms. */
|
||||
|
||||
ARG_DEFINE_KEY(vmw3_top_down, Bool);
|
||||
ARG_DEFINE_KEY(VMW3_TOP_DOWN, Bool);
|
||||
|
||||
|
||||
/* ArenaCreate -- create the arena and call initializers */
|
||||
|
||||
ARG_DEFINE_KEY(arena_size, Size);
|
||||
ARG_DEFINE_KEY(arena_grain_size, Size);
|
||||
ARG_DEFINE_KEY(arena_zoned, Bool);
|
||||
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)
|
||||
{
|
||||
|
|
@ -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 @@ allDeposited:
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -121,15 +128,17 @@ static Res clientChunkCreate(Chunk *chunkReturn, ClientArena clientArena,
|
|||
res = BootAlloc(&p, boot, sizeof(ClientChunkStruct), MPS_PF_ALIGN);
|
||||
if (res != ResOK)
|
||||
goto failChunkAlloc;
|
||||
clChunk = p; chunk = ClientChunk2Chunk(clChunk);
|
||||
clChunk = p;
|
||||
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;
|
||||
|
|
@ -155,7 +164,6 @@ static Res ClientChunkInit(Chunk chunk, BootBlock boot)
|
|||
/* chunk is supposed to be uninitialized, so don't check it. */
|
||||
clChunk = Chunk2ClientChunk(chunk);
|
||||
AVERT(BootBlock, boot);
|
||||
UNUSED(boot);
|
||||
|
||||
/* TODO: An old comment claimed this is too large.
|
||||
Does it fail to exclude the page table or something? */
|
||||
|
|
@ -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);
|
||||
|
|
@ -202,7 +219,7 @@ static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
|
|||
static void ClientChunkFinish(Chunk chunk)
|
||||
{
|
||||
/* Can't check chunk as it's not valid anymore. */
|
||||
UNUSED(chunk); NOOP;
|
||||
UNUSED(chunk);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -227,7 +244,7 @@ static void ClientArenaVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
* to do the generic part of init.
|
||||
*/
|
||||
|
||||
ARG_DEFINE_KEY(arena_cl_addr, Addr);
|
||||
ARG_DEFINE_KEY(ARENA_CL_BASE, Addr);
|
||||
|
||||
static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
||||
{
|
||||
|
|
@ -257,6 +274,10 @@ static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
AVER(base != (Addr)0);
|
||||
AVERT(ArenaGrainSize, grainSize);
|
||||
|
||||
if (size < grainSize * MPS_WORD_WIDTH)
|
||||
/* Not enough room for a full complement of zones. */
|
||||
return ResMEMORY;
|
||||
|
||||
clArenaSize = SizeAlignUp(sizeof(ClientArenaStruct), MPS_PF_ALIGN);
|
||||
if (size < clArenaSize)
|
||||
return ResMEMORY;
|
||||
|
|
@ -320,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> */
|
||||
}
|
||||
|
||||
|
|
@ -344,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,
|
||||
|
|
@ -372,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);
|
||||
|
|
@ -383,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" */
|
||||
|
|
@ -432,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;
|
||||
}
|
||||
|
||||
|
|
@ -447,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);
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ static void testAllocAndIterate(Arena arena, Pool pool,
|
|||
allocator->free(&offsetRegion);
|
||||
}
|
||||
}
|
||||
LocusPrefExpress(&pref, LocusPrefZoneSet, &zone);
|
||||
LocusPrefExpress(&pref, LocusPrefZONESET, &zone);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -507,6 +508,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
{
|
||||
Size size = VM_ARENA_SIZE_DEFAULT; /* initial arena size */
|
||||
Align grainSize = MPS_PF_ALIGN; /* arena grain size */
|
||||
Size pageSize = PageSize(); /* operating system page size */
|
||||
Size chunkSize; /* size actually created */
|
||||
Size vmArenaSize; /* aligned size of VMArenaStruct */
|
||||
Res res;
|
||||
|
|
@ -522,14 +524,19 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
AVER(class == VMArenaClassGet());
|
||||
AVERT(ArgList, args);
|
||||
|
||||
if (ArgPick(&arg, args, MPS_KEY_ARENA_SIZE))
|
||||
size = arg.val.size;
|
||||
if (ArgPick(&arg, args, MPS_KEY_ARENA_GRAIN_SIZE))
|
||||
grainSize = arg.val.size;
|
||||
grainSize = SizeAlignUp(grainSize, PageSize());
|
||||
|
||||
AVER(size > 0);
|
||||
if (grainSize < pageSize)
|
||||
/* Make it easier to write portable programs by rounding up. */
|
||||
grainSize = pageSize;
|
||||
AVERT(ArenaGrainSize, grainSize);
|
||||
|
||||
if (ArgPick(&arg, args, MPS_KEY_ARENA_SIZE))
|
||||
size = arg.val.size;
|
||||
if (size < grainSize * MPS_WORD_WIDTH)
|
||||
/* There has to be enough room in the chunk for a full complement of
|
||||
zones. Make it easier to write portable programs by rounding up. */
|
||||
size = grainSize * MPS_WORD_WIDTH;
|
||||
|
||||
/* Parse remaining arguments, if any, into VM parameters. We must do
|
||||
this into some stack-allocated memory for the moment, since we
|
||||
|
|
@ -554,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. */
|
||||
|
|
@ -634,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;
|
||||
|
|
@ -648,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
|
||||
|
|
@ -717,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 */
|
||||
{
|
||||
|
|
@ -731,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);
|
||||
|
|
@ -752,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));
|
||||
|
|
@ -800,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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1117,8 +1114,10 @@ static Bool vmChunkCompact(Tree tree, void *closureP, Size closureS)
|
|||
{
|
||||
Addr base = chunk->base;
|
||||
Size size = ChunkSize(chunk);
|
||||
/* Callback before destroying the chunk, as the arena is (briefly)
|
||||
invalid afterwards. See job003893. */
|
||||
(*vmArena->contracted)(arena, base, size);
|
||||
vmChunkDestroy(tree, UNUSED_POINTER, UNUSED_SIZE);
|
||||
vmArena->contracted(arena, base, size);
|
||||
return TRUE;
|
||||
} else {
|
||||
/* Keep this chunk. */
|
||||
|
|
@ -1136,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>
|
||||
|
|
@ -1146,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 */
|
||||
|
|
@ -1196,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;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ Bool ArgCheckPool(Arg arg) {
|
|||
}
|
||||
|
||||
|
||||
ARG_DEFINE_KEY(args_end, Shouldnt);
|
||||
ARG_DEFINE_KEY(ARGS_END, Shouldnt);
|
||||
|
||||
ArgStruct mps_args_none[] = {{MPS_KEY_ARGS_END, {0}}};
|
||||
|
||||
|
|
@ -174,9 +174,8 @@ found:
|
|||
/* ArgRequire -- take a required argument out of the argument list by keyword */
|
||||
|
||||
void ArgRequire(ArgStruct *argOut, ArgList args, Key key) {
|
||||
if (ArgPick(argOut, args, key))
|
||||
return;
|
||||
NOTREACHED;
|
||||
Bool b = ArgPick(argOut, args, key);
|
||||
ASSERT(b, key->name);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ typedef struct mps_key_s {
|
|||
|
||||
#define ARG_DEFINE_KEY(id, type) \
|
||||
extern const KeyStruct _mps_key_##id; \
|
||||
const KeyStruct _mps_key_##id = {KeySig, #id, ArgCheck##type}
|
||||
const KeyStruct _mps_key_##id = {KeySig, "MPS_KEY_" #id, ArgCheck##type}
|
||||
|
||||
#define argsNone mps_args_none
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -328,12 +326,10 @@ void BufferDetach(Buffer buffer, Pool pool)
|
|||
spare = AddrOffset(init, limit);
|
||||
buffer->emptySize += spare;
|
||||
if (buffer->isMutator) {
|
||||
buffer->pool->emptyMutatorSize += spare;
|
||||
ArenaGlobals(buffer->arena)->emptyMutatorSize += spare;
|
||||
ArenaGlobals(buffer->arena)->allocMutatorSize +=
|
||||
AddrOffset(buffer->base, init);
|
||||
} else {
|
||||
buffer->pool->emptyInternalSize += spare;
|
||||
ArenaGlobals(buffer->arena)->emptyInternalSize += spare;
|
||||
}
|
||||
|
||||
|
|
@ -657,10 +653,8 @@ void BufferAttach(Buffer buffer, Addr base, Addr limit,
|
|||
Size prealloc = AddrOffset(base, init);
|
||||
ArenaGlobals(buffer->arena)->allocMutatorSize -= prealloc;
|
||||
}
|
||||
buffer->pool->fillMutatorSize += filled;
|
||||
ArenaGlobals(buffer->arena)->fillMutatorSize += filled;
|
||||
} else {
|
||||
buffer->pool->fillInternalSize += filled;
|
||||
ArenaGlobals(buffer->arena)->fillInternalSize += filled;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -215,7 +215,7 @@ static void cbsUpdateZonedNode(SplayTree splay, Tree tree)
|
|||
|
||||
ARG_DEFINE_KEY(cbs_block_pool, Pool);
|
||||
|
||||
static Res cbsInitComm(Land land, ArgList args, SplayUpdateNodeMethod update,
|
||||
static Res cbsInitComm(Land land, ArgList args, SplayUpdateNodeFunction update,
|
||||
Size blockStructSize)
|
||||
{
|
||||
CBS cbs;
|
||||
|
|
@ -1058,7 +1058,7 @@ static Res cbsFindInZones(Bool *foundReturn, Range rangeReturn,
|
|||
cbsTestNodeInZonesClosureStruct closure;
|
||||
Res res;
|
||||
LandFindMethod landFind;
|
||||
SplayFindMethod splayFind;
|
||||
SplayFindFunction splayFind;
|
||||
RangeStruct rangeStruct, oldRangeStruct;
|
||||
|
||||
AVER(foundReturn != NULL);
|
||||
|
|
@ -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.
|
||||
|
|
@ -213,7 +212,8 @@ MPMCOMMON = \
|
|||
version.c \
|
||||
vm.c \
|
||||
walk.c
|
||||
MPM = $(MPMCOMMON) $(MPMPF) $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(PLINTH)
|
||||
POOLS = $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(SNC)
|
||||
MPM = $(MPMCOMMON) $(MPMPF) $(POOLS) $(PLINTH)
|
||||
|
||||
|
||||
# These map the source file lists onto object files and dependency files
|
||||
|
|
@ -308,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
|
||||
|
|
@ -68,6 +387,69 @@ testrun testci testall testansi testpoll: $(TEST_TARGETS)
|
|||
!ENDIF
|
||||
|
||||
|
||||
# FLAGS AMALGAMATION
|
||||
#
|
||||
# %%VARIETY: When adding a new variety, add the following macros that
|
||||
# expand to sets of flags that the variety should use:
|
||||
#
|
||||
# CFLAGS -- when compiling C;
|
||||
# CFLAGSSQL -- when compiling mpseventsql;
|
||||
# LINKFLAGS -- when building executables;
|
||||
# LIBFLAGS -- when building libraries.
|
||||
|
||||
!IF "$(VARIETY)" == "hot"
|
||||
CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST)
|
||||
CFLAGSSQL=$(CFLAGSSQLPRE) $(CFHOT) $(CFLAGSSQLPOST)
|
||||
LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT)
|
||||
LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT)
|
||||
|
||||
!ELSEIF "$(VARIETY)" == "cool"
|
||||
CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST)
|
||||
CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST)
|
||||
LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL)
|
||||
LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL)
|
||||
|
||||
!ELSEIF "$(VARIETY)" == "rash"
|
||||
CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST)
|
||||
CFLAGSSQL=$(CFLAGSSQLPRE) $(CFRASH) $(CFLAGSSQLPOST)
|
||||
LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH)
|
||||
LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH)
|
||||
|
||||
!ENDIF
|
||||
|
||||
|
||||
# SOURCE TO OBJECT FILE MAPPINGS
|
||||
#
|
||||
# %%PART: When adding a new part, add new macros which expand to the object
|
||||
# files included in the part
|
||||
#
|
||||
# Note: nmake doesn't expand variables within a string replacement
|
||||
# operation. We work around this by writing out a temporary makefile
|
||||
# and including it.
|
||||
|
||||
TEMPMAKE=$(TEMP)\mps.nmk
|
||||
!IF [echo MPMOBJ0 = $$(MPM:[=$(PFM)\$(VARIETY)\) > $(TEMPMAKE)] == 0 \
|
||||
&& [echo FMTDYOBJ0 = $$(FMTDY:[=$(PFM)\$(VARIETY)\) >> $(TEMPMAKE)] == 0 \
|
||||
&& [echo FMTTESTOBJ0 = $$(FMTTEST:[=$(PFM)\$(VARIETY)\) >> $(TEMPMAKE)] == 0 \
|
||||
&& [echo FMTSCHEMEOBJ0 = $$(FMTSCHEME:[=$(PFM)\$(VARIETY)\) >> $(TEMPMAKE)] == 0 \
|
||||
&& [echo POOLNOBJ0 = $$(POOLN:[=$(PFM)\$(VARIETY)\) >> $(TEMPMAKE)] == 0 \
|
||||
&& [echo TESTLIBOBJ0 = $$(TESTLIB:[=$(PFM)\$(VARIETY)\) >> $(TEMPMAKE)] == 0 \
|
||||
&& [echo TESTTHROBJ0 = $$(TESTTHR:[=$(PFM)\$(VARIETY)\) >> $(TEMPMAKE)] == 0
|
||||
!INCLUDE $(TEMPMAKE)
|
||||
!IF [del $(TEMPMAKE)] != 0
|
||||
!ERROR Failed to delete $(TEMPMAKE)
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
MPMOBJ = $(MPMOBJ0:]=.obj)
|
||||
FMTDYOBJ = $(FMTDYOBJ0:]=.obj)
|
||||
FMTTESTOBJ = $(FMTTESTOBJ0:]=.obj)
|
||||
FMTSCHEMEOBJ = $(FMTSCHEMEOBJ0:]=.obj)
|
||||
POOLNOBJ = $(POOLNOBJ0:]=.obj)
|
||||
TESTLIBOBJ = $(TESTLIBOBJ0:]=.obj)
|
||||
TESTTHROBJ = $(TESTTHROBJ0:]=.obj)
|
||||
|
||||
|
||||
# THE MPS LIBRARY
|
||||
#
|
||||
# The MPS library is built in two ways:
|
||||
|
|
@ -319,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
|
||||
|
|
@ -341,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,368 +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 in angle 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>
|
||||
MPM = $(MPMCOMMON) $(MPMPF) $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(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.
|
||||
|
|
@ -427,14 +427,11 @@
|
|||
#define VM_ARENA_SIZE_DEFAULT ((Size)1 << 28)
|
||||
|
||||
|
||||
/* Stack configuration */
|
||||
/* Stack configuration -- see <code/sp*.c> */
|
||||
|
||||
/* Currently StackProbe has a useful implementation only on Windows. */
|
||||
#if defined(PLATFORM_ANSI)
|
||||
#define StackProbeDEPTH ((Size)0)
|
||||
#elif defined(MPS_OS_W3) && defined(MPS_ARCH_I3)
|
||||
#define StackProbeDEPTH ((Size)500)
|
||||
#elif defined(MPS_OS_W3) && defined(MPS_ARCH_I6)
|
||||
#if defined(MPS_OS_W3)
|
||||
/* See <design/sp/#sol.depth.analysis> for a justification of this value. */
|
||||
#define StackProbeDEPTH ((Size)500)
|
||||
#else
|
||||
#define StackProbeDEPTH ((Size)0)
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ Bool PoolDebugOptionsCheck(PoolDebugOptions opt)
|
|||
* Someday, this could be split into fence and tag init methods.
|
||||
*/
|
||||
|
||||
ARG_DEFINE_KEY(pool_debug_options, PoolDebugOptions);
|
||||
ARG_DEFINE_KEY(POOL_DEBUG_OPTIONS, PoolDebugOptions);
|
||||
|
||||
static PoolDebugOptionsStruct debugPoolOptionsDefault = {
|
||||
"POST", 4, "DEAD", 4,
|
||||
|
|
@ -132,7 +132,7 @@ static Res DebugPoolInit(Pool pool, ArgList args)
|
|||
Res res;
|
||||
PoolDebugOptions options = &debugPoolOptionsDefault;
|
||||
PoolDebugMixin debug;
|
||||
TagInitMethod tagInit;
|
||||
TagInitFunction tagInit;
|
||||
Size tagSize;
|
||||
ArgStruct arg;
|
||||
|
||||
|
|
@ -648,19 +648,16 @@ static void DebugPoolFree(Pool pool, Addr old, Size size)
|
|||
|
||||
/* TagWalk -- walk all objects in the pool using tags */
|
||||
|
||||
typedef void (*ObjectsStepMethod)(Addr addr, Size size, Format fmt,
|
||||
Pool pool, void *tagData, void *p);
|
||||
typedef void (*ObjectsVisitor)(Addr addr, Size size, Format fmt,
|
||||
Pool pool, void *tagData, void *p);
|
||||
|
||||
#define ObjectsStepMethodCheck(f) \
|
||||
((f) != NULL) /* that's the best we can do */
|
||||
|
||||
static void TagWalk(Pool pool, ObjectsStepMethod step, void *p)
|
||||
static void TagWalk(Pool pool, ObjectsVisitor visitor, void *p)
|
||||
{
|
||||
Tree node;
|
||||
PoolDebugMixin debug;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVERT(ObjectsStepMethod, step);
|
||||
AVER(FUNCHECK(visitor));
|
||||
/* Can't check p */
|
||||
|
||||
debug = DebugPoolDebugMixin(pool);
|
||||
|
|
@ -671,7 +668,7 @@ static void TagWalk(Pool pool, ObjectsStepMethod step, void *p)
|
|||
while (node != TreeEMPTY) {
|
||||
Tag tag = TagOfTree(node);
|
||||
|
||||
step(tag->addr, tag->size, NULL, pool, &tag->userdata, p);
|
||||
(*visitor)(tag->addr, tag->size, NULL, pool, &tag->userdata, p);
|
||||
node = SplayTreeNext(&debug->index, &tag->addr);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* See <design/object-debug>.
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* tag init methods: copying the user-supplied data into the tag */
|
||||
/* tag init function: copies the user-supplied data into the tag */
|
||||
|
||||
typedef void (*TagInitMethod)(void* tag, va_list args);
|
||||
typedef void (*TagInitFunction)(void *tag, va_list args);
|
||||
|
||||
|
||||
/* PoolDebugOptions -- option structure for debug pool init
|
||||
|
|
@ -30,7 +30,7 @@ typedef struct PoolDebugOptionsStruct {
|
|||
Size fenceSize;
|
||||
const void *freeTemplate;
|
||||
Size freeSize;
|
||||
/* TagInitMethod tagInit; */
|
||||
/* TagInitFunction tagInit; */
|
||||
/* Size tagSize; */
|
||||
} PoolDebugOptionsStruct;
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ typedef struct PoolDebugMixinStruct {
|
|||
Size fenceSize;
|
||||
const struct AddrStruct *freeTemplate;
|
||||
Size freeSize;
|
||||
TagInitMethod tagInit;
|
||||
TagInitFunction tagInit;
|
||||
Size tagSize;
|
||||
Pool tagPool;
|
||||
Count missingTags;
|
||||
|
|
@ -73,7 +73,7 @@ extern void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -88,14 +88,14 @@ static mps_addr_t FormatDefaultClass(mps_addr_t object)
|
|||
|
||||
/* FormatCreate -- create a format */
|
||||
|
||||
ARG_DEFINE_KEY(fmt_align, Align);
|
||||
ARG_DEFINE_KEY(fmt_scan, Fun);
|
||||
ARG_DEFINE_KEY(fmt_skip, Fun);
|
||||
ARG_DEFINE_KEY(fmt_fwd, Fun);
|
||||
ARG_DEFINE_KEY(fmt_isfwd, Fun);
|
||||
ARG_DEFINE_KEY(fmt_pad, Fun);
|
||||
ARG_DEFINE_KEY(fmt_header_size, Size);
|
||||
ARG_DEFINE_KEY(fmt_class, Fun);
|
||||
ARG_DEFINE_KEY(FMT_ALIGN, Align);
|
||||
ARG_DEFINE_KEY(FMT_SCAN, Fun);
|
||||
ARG_DEFINE_KEY(FMT_SKIP, Fun);
|
||||
ARG_DEFINE_KEY(FMT_FWD, Fun);
|
||||
ARG_DEFINE_KEY(FMT_ISFWD, Fun);
|
||||
ARG_DEFINE_KEY(FMT_PAD, Fun);
|
||||
ARG_DEFINE_KEY(FMT_HEADER_SIZE, Size);
|
||||
ARG_DEFINE_KEY(FMT_CLASS, Fun);
|
||||
|
||||
Res FormatCreate(Format *formatReturn, Arena arena, ArgList args)
|
||||
{
|
||||
|
|
@ -181,12 +181,11 @@ void FormatDestroy(Format format)
|
|||
|
||||
/* FormatArena -- find the arena of a format
|
||||
*
|
||||
* Must be thread-safe. See <design/interface-c/#thread-safety>. */
|
||||
* Must be thread-safe. See <design/interface-c/#check.testt>. */
|
||||
|
||||
Arena FormatArena(Format format)
|
||||
{
|
||||
/* Can't AVER format as that would not be thread-safe */
|
||||
/* AVERT(Format, format); */
|
||||
AVER(TESTT(Format, format));
|
||||
return format->arena;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,33 +3,36 @@
|
|||
# fri3gc.gmk: BUILD FOR FreeBSD/i386/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = fri3gc
|
||||
|
||||
MPMPF = lockix.c thix.c pthrdext.c vmix.c \
|
||||
protix.c protsgix.c prmcan.c prmci3fr.c ssixi3.c span.c
|
||||
MPMPF = \
|
||||
lockix.c \
|
||||
prmcan.c \
|
||||
prmci3fr.c \
|
||||
protix.c \
|
||||
protsgix.c \
|
||||
pthrdext.c \
|
||||
span.c \
|
||||
ssixi3.c \
|
||||
thix.c \
|
||||
vmix.c
|
||||
|
||||
LIBS = -lm -pthread
|
||||
|
||||
include gc.gmk
|
||||
|
||||
# FIXME: We pun types through the MPS interface, setting off this warning.
|
||||
# Can we avoid this? The puns might indeed be dangerous.
|
||||
CFLAGSCOMPILER += -Wno-strict-aliasing
|
||||
|
||||
# For SQLite3.
|
||||
LINKFLAGS += -L/usr/local/lib
|
||||
CFLAGSCOMPILER += -I/usr/local/include
|
||||
|
||||
CC = cc
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
}
|
||||
|
||||
CHECKD_NOSIG(Ring, &arena->threadRing);
|
||||
CHECKD_NOSIG(Ring, &arena->deadRing);
|
||||
|
||||
CHECKL(BoolCheck(arena->insideShield));
|
||||
CHECKL(arena->shCacheLimit <= ShieldCacheSIZE);
|
||||
|
|
@ -185,7 +186,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKL(TraceIdMessagesCheck(arena, ti));
|
||||
TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena);
|
||||
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
CHECKD_NOSIG(Ring, &arena->greyRing[rank]);
|
||||
CHECKD_NOSIG(Ring, &arena->chainRing);
|
||||
|
||||
|
|
@ -277,6 +278,7 @@ Res GlobalsInit(Globals arenaGlobals)
|
|||
arenaGlobals->rememberedSummaryIndex = 0;
|
||||
|
||||
RingInit(&arena->threadRing);
|
||||
RingInit(&arena->deadRing);
|
||||
arena->threadSerial = (Serial)0;
|
||||
RingInit(&arena->formatRing);
|
||||
arena->formatSerial = (Serial)0;
|
||||
|
|
@ -308,7 +310,7 @@ Res GlobalsInit(Globals arenaGlobals)
|
|||
arena->tMessage[ti] = NULL;
|
||||
}
|
||||
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
RingInit(&arena->greyRing[rank]);
|
||||
STATISTIC(arena->writeBarrierHitCount = 0);
|
||||
RingInit(&arena->chainRing);
|
||||
|
|
@ -405,7 +407,8 @@ void GlobalsFinish(Globals arenaGlobals)
|
|||
RingFinish(&arena->chainRing);
|
||||
RingFinish(&arena->messageRing);
|
||||
RingFinish(&arena->threadRing);
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
RingFinish(&arena->deadRing);
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
RingFinish(&arena->greyRing[rank]);
|
||||
RingFinish(&arenaGlobals->rootRing);
|
||||
RingFinish(&arenaGlobals->poolRing);
|
||||
|
|
@ -438,7 +441,7 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
arenaGlobals->defaultChain = NULL;
|
||||
ChainDestroy(defaultChain);
|
||||
|
||||
LockReleaseMPM(arenaGlobals->lock);
|
||||
LockRelease(arenaGlobals->lock);
|
||||
/* Theoretically, another thread could grab the lock here, but it's */
|
||||
/* not worth worrying about, since an attempt after the lock has been */
|
||||
/* destroyed would lead to a crash just the same. */
|
||||
|
|
@ -495,8 +498,9 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
AVER(RingIsSingle(&arena->chainRing));
|
||||
AVER(RingIsSingle(&arena->messageRing));
|
||||
AVER(RingIsSingle(&arena->threadRing));
|
||||
AVER(RingIsSingle(&arena->deadRing));
|
||||
AVER(RingIsSingle(&arenaGlobals->rootRing));
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
AVER(RingIsSingle(&arena->greyRing[rank]));
|
||||
|
||||
/* At this point the following pools still exist:
|
||||
|
|
@ -548,7 +552,7 @@ void ArenaEnterLock(Arena arena, Bool recursive)
|
|||
} else {
|
||||
LockClaim(lock);
|
||||
}
|
||||
AVERT(Arena, arena); /* can't AVER it until we've got the lock */
|
||||
AVERT(Arena, arena); /* can't AVERT it until we've got the lock */
|
||||
if(recursive) {
|
||||
/* already in shield */
|
||||
} else {
|
||||
|
|
@ -591,7 +595,7 @@ void ArenaLeaveLock(Arena arena, Bool recursive)
|
|||
if(recursive) {
|
||||
LockReleaseRecursive(lock);
|
||||
} else {
|
||||
LockReleaseMPM(lock);
|
||||
LockRelease(lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -653,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -500,7 +500,6 @@ extern int main(int argc, char *argv[])
|
|||
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSFastBlockStruct));
|
||||
MPS_ARGS_ADD(piArgs, MPS_KEY_EXTEND_BY, ArenaGrainSize(arena));
|
||||
MPS_ARGS_ADD(piArgs, MFSExtendSelf, i);
|
||||
MPS_ARGS_DONE(piArgs);
|
||||
die(PoolInit(mfs, arena, PoolClassMFS(), piArgs), "PoolInit");
|
||||
} MPS_ARGS_END(piArgs);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* ld.c: LOCATION DEPENDENCY IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 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,11 +92,21 @@ 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)
|
||||
{
|
||||
AVER(ld != NULL);
|
||||
AVER(TESTT(Arena, arena)); /* see .add.lock-free */
|
||||
AVER(ld->_epoch <= arena->epoch);
|
||||
/* AVERT(Arena, arena) -- see .add.lock-free */
|
||||
|
||||
ld->_rs = RefSetAdd(arena, ld->_rs, addr);
|
||||
}
|
||||
|
|
@ -126,8 +136,9 @@ Bool LDIsStaleAny(mps_ld_t ld, Arena arena)
|
|||
{
|
||||
RefSet rs;
|
||||
|
||||
AVER(ld != NULL);
|
||||
AVER(TESTT(Arena, arena)); /* .stale.thread-safe */
|
||||
AVER(ld->_epoch <= arena->epoch);
|
||||
/* AVERT(Arena, arena) -- .stale.thread-safe */
|
||||
|
||||
if (arena->epoch == ld->_epoch) /* .stale.current */
|
||||
return FALSE;
|
||||
|
|
@ -151,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)
|
||||
{
|
||||
|
|
@ -204,8 +219,8 @@ void LDAge(Arena arena, RefSet rs)
|
|||
*/
|
||||
void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from)
|
||||
{
|
||||
/* AVERT(Arena, arena); -- .merge.lock-free */
|
||||
AVER(ld != NULL);
|
||||
AVER(TESTT(Arena, arena)); /* .merge.lock-free */
|
||||
AVER(ld->_epoch <= arena->epoch);
|
||||
AVER(from != NULL);
|
||||
AVER(from->_epoch <= arena->epoch);
|
||||
|
|
@ -223,7 +238,7 @@ void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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,30 +1,33 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# lii3gc.gmk: BUILD FOR LINUX/INTEL/GCC PLATFORM
|
||||
# lii3gc.gmk: BUILD FOR LINUX/x86/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = lii3gc
|
||||
|
||||
THREADSRC = lockli.c thix.c pthrdext.c
|
||||
THREADLIB = -lpthread
|
||||
MPMPF = \
|
||||
lockli.c \
|
||||
prmci3li.c \
|
||||
proti3.c \
|
||||
protix.c \
|
||||
protli.c \
|
||||
pthrdext.c \
|
||||
span.c \
|
||||
ssixi3.c \
|
||||
thix.c \
|
||||
vmix.c
|
||||
|
||||
MPMPF = ${THREADSRC} vmix.c \
|
||||
protix.c protli.c proti3.c prmci3li.c ssixi3.c span.c
|
||||
|
||||
LIBS = -lm ${THREADLIB}
|
||||
LIBS = -lm -lpthread
|
||||
|
||||
include gc.gmk
|
||||
|
||||
CC = cc
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -3,28 +3,31 @@
|
|||
# lii6gc.gmk: BUILD FOR LINUX/x64/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = lii6gc
|
||||
|
||||
THREADSRC = lockli.c thix.c pthrdext.c
|
||||
THREADLIB = -lpthread
|
||||
MPMPF = \
|
||||
lockli.c \
|
||||
prmci6li.c \
|
||||
proti6.c \
|
||||
protix.c \
|
||||
protli.c \
|
||||
pthrdext.c \
|
||||
span.c \
|
||||
ssixi6.c \
|
||||
thix.c \
|
||||
vmix.c
|
||||
|
||||
MPMPF = ${THREADSRC} vmix.c \
|
||||
protix.c protli.c proti6.c prmci6li.c ssixi6.c span.c
|
||||
|
||||
LIBS = -lm ${THREADLIB}
|
||||
LIBS = -lm -lpthread
|
||||
|
||||
include gc.gmk
|
||||
|
||||
CC = cc
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -3,17 +3,23 @@
|
|||
# lii6ll.gmk: BUILD FOR LINUX/x64/Clang PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = lii6ll
|
||||
|
||||
THREADSRC = lockli.c thix.c pthrdext.c
|
||||
THREADLIB = -lpthread
|
||||
MPMPF = \
|
||||
lockli.c \
|
||||
prmci6li.c \
|
||||
proti6.c \
|
||||
protix.c \
|
||||
protli.c \
|
||||
pthrdext.c \
|
||||
span.c \
|
||||
ssixi6.c \
|
||||
thix.c \
|
||||
vmix.c
|
||||
|
||||
MPMPF = ${THREADSRC} vmix.c \
|
||||
protix.c protli.c proti6.c prmci6li.c ssixi6.c span.c
|
||||
|
||||
LIBS = -lm ${THREADLIB}
|
||||
LIBS = -lm -lpthread
|
||||
|
||||
include ll.gmk
|
||||
include comm.gmk
|
||||
|
|
@ -21,7 +27,7 @@ include comm.gmk
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,79 +1,7 @@
|
|||
/* lock.h: RECURSIVE LOCKS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .description: [@@@@ Should be combined with <design/lock/>]
|
||||
* This defines the type Lock, which supports simple recursive
|
||||
* locking. Locking ensures that only a single thread may be running
|
||||
* with a lock held. By claiming a lock in some code, this ensures
|
||||
* that only one thread can be running in that code at a time. This
|
||||
* in turn can be used to protect different threads from trying to
|
||||
* read or update data structures which are in a transitional state.
|
||||
*
|
||||
* At most one thread may own a lock at a time. A lock is initialised
|
||||
* without an owner. A lock should not have an owner when it is
|
||||
* finished. Claiming the lock will wait until the lock is not owned
|
||||
* by another thread and then cause the current thread to become the
|
||||
* owner. Releasing the the lock will relinquish ownership if the
|
||||
* number of releases matches the number of claims.
|
||||
*
|
||||
* To use a lock a structure of type LockStruct must be allocated.
|
||||
* This is defined in <code/lockst.h>. Sources which allocate such a
|
||||
* structure will need to include "lockst.h". A lock of type Lock is
|
||||
* a pointer to such an allocated structure.
|
||||
*
|
||||
* A lock must be Inited before use and should be Finished after use,
|
||||
* using LockInit and LockFinish.
|
||||
*
|
||||
* LockClaimRecursive & LockReleaseRecursive are for claiming and
|
||||
* releasing the lock. These may be used recursively.
|
||||
*
|
||||
* There is a limit on the number of recursive claims which
|
||||
* depends on the implementation. See issue.lock-claim-limit.
|
||||
*
|
||||
* LockClaim and LockReleaseMPM are the same as the Recursive versions,
|
||||
* except that LockClaim may only be used by a thread that doesn't
|
||||
* already own the lock, and LockReleaseMPM may only be used to release
|
||||
* a lock with one claim. LockClaim and LockReleaseMPM if used, must
|
||||
* be used symmetrically in pairs.
|
||||
*
|
||||
* There are two intended uses. Here is an example:
|
||||
* #include "lock.h"
|
||||
* #include "lockst.h"
|
||||
* static LockStruct lockStruct;
|
||||
* binaryUse()
|
||||
* { ;; lock not owned by this thread.
|
||||
* LockClaim(&lockStruct);
|
||||
* ;; lock owned by this thread.
|
||||
* ;; Cannot call binaryUse() at this point.
|
||||
* ;; only one thread at a time may be at this point.
|
||||
* LockReleaseMPM(&lockStruct);
|
||||
* ;; lock not owned by this thread.
|
||||
* }
|
||||
*
|
||||
* recursiveUse()
|
||||
* { ;; lock may already be owned by this thread.
|
||||
* LockClaimRecursive(&lockStruct);
|
||||
* ;; lock held by this thread.
|
||||
* ;; only one thread at a time may be at this point.
|
||||
* LockReleaseRecursive(&lockStruct);
|
||||
* ;; lock owned by this thread if it was before.
|
||||
* }
|
||||
* LockInit(&lockStruct) must be called before calling binaryUse()
|
||||
* or recursiveUse().
|
||||
* LockFinish(&lockStruct) should be called when lock is no longer
|
||||
* needed.
|
||||
* recursiveUse() may be called by both functions.
|
||||
* binaryUse() may only be called where lock is known not to be
|
||||
* already owned by this thread. In particular, it may not be
|
||||
* called by recursiveUse().
|
||||
*
|
||||
* LockClaimGlobalRecursive & LockReleaseGlobalRecursive are
|
||||
* similar to LockClaimRecursive & LockReleaseRecursive
|
||||
* except that they lock an implicit global lock. This may be
|
||||
* used for locking access to data structures which are global,
|
||||
* such as class objects.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef lock_h
|
||||
|
|
@ -129,20 +57,20 @@ extern void LockReleaseRecursive(Lock lock);
|
|||
* This may only be used when the lock is not already owned by
|
||||
* the calling thread.
|
||||
* When used it behaves like LockClaimRecursive, but must be
|
||||
* matched by a call to LockReleaseMPM.
|
||||
* matched by a call to LockRelease.
|
||||
*/
|
||||
|
||||
extern void LockClaim(Lock lock);
|
||||
|
||||
|
||||
/* LockReleaseMPM
|
||||
/* LockRelease
|
||||
*
|
||||
* This must only be used to release a Lock symmetrically
|
||||
* with LockClaim. It therefore should only be called with
|
||||
* a single claim.
|
||||
*/
|
||||
|
||||
extern void LockReleaseMPM(Lock lock);
|
||||
extern void LockRelease(Lock lock);
|
||||
|
||||
|
||||
/* LockCheck -- Validation */
|
||||
|
|
@ -204,7 +132,7 @@ extern void LockReleaseGlobal(void);
|
|||
#define LockClaimRecursive(lock) UNUSED(lock)
|
||||
#define LockReleaseRecursive(lock) UNUSED(lock)
|
||||
#define LockClaim(lock) UNUSED(lock)
|
||||
#define LockReleaseMPM(lock) UNUSED(lock)
|
||||
#define LockRelease(lock) UNUSED(lock)
|
||||
#define LockCheck(lock) ((void)lock, TRUE)
|
||||
#define LockClaimGlobalRecursive()
|
||||
#define LockReleaseGlobalRecursive()
|
||||
|
|
@ -220,7 +148,7 @@ extern void LockReleaseGlobal(void);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockan.c: ANSI RECURSIVE LOCKS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is a trivial implementation of recursive locks
|
||||
* that assumes we are not running in a multi-threaded environment.
|
||||
|
|
@ -58,7 +58,7 @@ void (LockClaim)(Lock lock)
|
|||
lock->claims = 1;
|
||||
}
|
||||
|
||||
void (LockReleaseMPM)(Lock lock)
|
||||
void (LockRelease)(Lock lock)
|
||||
{
|
||||
AVERT(Lock, lock);
|
||||
AVER(lock->claims == 1);
|
||||
|
|
@ -118,13 +118,13 @@ void (LockClaimGlobal)(void)
|
|||
|
||||
void (LockReleaseGlobal)(void)
|
||||
{
|
||||
LockReleaseMPM(globalLock);
|
||||
LockRelease(globalLock);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ int main(int argc, char *argv[])
|
|||
LockClaimGlobalRecursive();
|
||||
LockReleaseGlobal();
|
||||
LockClaimGlobal();
|
||||
LockReleaseMPM(a);
|
||||
LockRelease(a);
|
||||
LockClaimGlobalRecursive();
|
||||
LockReleaseGlobal();
|
||||
LockClaimRecursive(b);
|
||||
|
|
@ -59,7 +59,7 @@ int main(int argc, char *argv[])
|
|||
LockClaimRecursive(a);
|
||||
LockReleaseGlobalRecursive();
|
||||
LockReleaseRecursive(a);
|
||||
LockReleaseMPM(a);
|
||||
LockRelease(a);
|
||||
LockFinish(a);
|
||||
LockReleaseGlobalRecursive();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockix.c: RECURSIVE LOCKS FOR POSIX SYSTEMS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001,2007 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .posix: The implementation uses a POSIX interface, and should be reusable
|
||||
* for many Unix-like operating systems.
|
||||
|
|
@ -131,9 +131,9 @@ void (LockClaim)(Lock lock)
|
|||
}
|
||||
|
||||
|
||||
/* LockReleaseMPM -- release a lock (non-recursive) */
|
||||
/* LockRelease -- release a lock (non-recursive) */
|
||||
|
||||
void (LockReleaseMPM)(Lock lock)
|
||||
void (LockRelease)(Lock lock)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
|
@ -239,13 +239,13 @@ void (LockClaimGlobal)(void)
|
|||
|
||||
void (LockReleaseGlobal)(void)
|
||||
{
|
||||
LockReleaseMPM(globalLock);
|
||||
LockRelease(globalLock);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockli.c: RECURSIVE LOCKS FOR POSIX SYSTEMS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .linux: This implementation currently just supports LinuxThreads
|
||||
* (platform MPS_OS_LI), Single Unix i/f.
|
||||
|
|
@ -145,9 +145,9 @@ void (LockClaim)(Lock lock)
|
|||
}
|
||||
|
||||
|
||||
/* LockReleaseMPM -- release a lock (non-recursive) */
|
||||
/* LockRelease -- release a lock (non-recursive) */
|
||||
|
||||
void (LockReleaseMPM)(Lock lock)
|
||||
void (LockRelease)(Lock lock)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
|
@ -253,13 +253,13 @@ void (LockClaimGlobal)(void)
|
|||
|
||||
void (LockReleaseGlobal)(void)
|
||||
{
|
||||
LockReleaseMPM(globalLock);
|
||||
LockRelease(globalLock);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ static void inc(unsigned long i)
|
|||
tmp = shared;
|
||||
shared = tmp+1;
|
||||
i--;
|
||||
LockReleaseMPM(lock);
|
||||
LockRelease(lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockw3.c: RECURSIVE LOCKS IN WIN32
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: These are implemented using critical sections.
|
||||
* See the section titled "Synchronization functions" in the Groups
|
||||
|
|
@ -79,7 +79,7 @@ void (LockClaim)(Lock lock)
|
|||
lock->claims = 1;
|
||||
}
|
||||
|
||||
void (LockReleaseMPM)(Lock lock)
|
||||
void (LockRelease)(Lock lock)
|
||||
{
|
||||
AVERT(Lock, lock);
|
||||
AVER(lock->claims == 1); /* The lock should only be held once */
|
||||
|
|
@ -152,13 +152,13 @@ void (LockClaimGlobal)(void)
|
|||
void (LockReleaseGlobal)(void)
|
||||
{
|
||||
AVER(globalLockInit);
|
||||
LockReleaseMPM(globalLock);
|
||||
LockRelease(globalLock);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -56,17 +56,17 @@ void LocusPrefExpress(LocusPref pref, LocusPrefKind kind, void *p)
|
|||
AVER(pref != &locusPrefDefault);
|
||||
|
||||
switch(kind) {
|
||||
case LocusPrefHigh:
|
||||
case LocusPrefHIGH:
|
||||
AVER(p == NULL);
|
||||
pref->high = TRUE;
|
||||
break;
|
||||
|
||||
case LocusPrefLow:
|
||||
case LocusPrefLOW:
|
||||
AVER(p == NULL);
|
||||
pref->high = FALSE;
|
||||
break;
|
||||
|
||||
case LocusPrefZoneSet:
|
||||
case LocusPrefZONESET:
|
||||
AVER(p != NULL);
|
||||
pref->zones = *(ZoneSet *)p;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -84,7 +84,11 @@ Bool MPMCheck(void)
|
|||
* arena grain). */
|
||||
CHECKL(PageSize() % ProtGranularity() == 0);
|
||||
|
||||
return TRUE;
|
||||
/* StackProbe mustn't skip over the stack guard page. See
|
||||
* <design/sp/#sol.depth.constraint>. */
|
||||
CHECKL(StackProbeDEPTH * sizeof(Word) < PageSize());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -133,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) */
|
||||
|
||||
|
||||
|
|
@ -634,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
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include "event.h"
|
||||
#include "lock.h"
|
||||
#include "prot.h"
|
||||
#include "sp.h"
|
||||
#include "th.h"
|
||||
#include "ss.h"
|
||||
#include "mpslib.h"
|
||||
|
|
@ -44,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> */
|
||||
|
|
@ -222,9 +225,9 @@ extern Res PoolFixEmergency(Pool pool, ScanState ss, Seg seg, Addr *refIO);
|
|||
extern void PoolReclaim(Pool pool, Trace trace, Seg seg);
|
||||
extern void PoolTraceEnd(Pool pool, Trace trace);
|
||||
extern Res PoolAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr);
|
||||
extern void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
extern void PoolWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *v, size_t s);
|
||||
extern void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern void PoolFreeWalk(Pool pool, FreeBlockVisitor f, void *p);
|
||||
extern Size PoolTotalSize(Pool pool);
|
||||
extern Size PoolFreeSize(Pool pool);
|
||||
|
||||
|
|
@ -276,9 +279,9 @@ extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame);
|
|||
extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr);
|
||||
extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step,
|
||||
extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *p, size_t s);
|
||||
extern void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern void PoolTrivFreeWalk(Pool pool, FreeBlockVisitor f, void *p);
|
||||
extern PoolDebugMixin PoolNoDebugMixin(Pool pool);
|
||||
extern BufferClass PoolNoBufferClass(void);
|
||||
extern Size PoolNoSize(Pool pool);
|
||||
|
|
@ -518,6 +521,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals);
|
|||
#define GlobalsArena(glob) PARENT(ArenaStruct, globals, glob)
|
||||
|
||||
#define ArenaThreadRing(arena) (&(arena)->threadRing)
|
||||
#define ArenaDeadRing(arena) (&(arena)->deadRing)
|
||||
#define ArenaEpoch(arena) ((arena)->epoch) /* .epoch.ts */
|
||||
#define ArenaTrace(arena, ti) (&(arena)->trace[ti])
|
||||
#define ArenaZoneShift(arena) ((arena)->zoneShift)
|
||||
|
|
@ -559,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);
|
||||
|
|
@ -931,30 +936,6 @@ extern void (ShieldFlush)(Arena arena);
|
|||
#endif /* SHIELD */
|
||||
|
||||
|
||||
/* Protection Interface
|
||||
*
|
||||
* See <design/prot/> for the design of the generic interface including
|
||||
* the contracts for these functions.
|
||||
*
|
||||
* This interface has several different implementations, typically one
|
||||
* per platform, see <code/prot.c>* for the various implementations, and
|
||||
* <design/prot/>* for the corresponding designs. */
|
||||
|
||||
extern void ProtSetup(void);
|
||||
|
||||
extern Size ProtGranularity(void);
|
||||
extern void ProtSet(Addr base, Addr limit, AccessSet mode);
|
||||
extern void ProtSync(Arena arena);
|
||||
extern Bool ProtCanStepInstruction(MutatorFaultContext context);
|
||||
extern Res ProtStepInstruction(MutatorFaultContext context);
|
||||
|
||||
|
||||
/* Mutator Fault Context */
|
||||
|
||||
extern Addr MutatorFaultContextSP(MutatorFaultContext mfc);
|
||||
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc);
|
||||
|
||||
|
||||
/* Location Dependency -- see <code/ld.c> */
|
||||
|
||||
extern void LDReset(mps_ld_t ld, Arena arena);
|
||||
|
|
@ -1033,11 +1014,6 @@ extern LandClass LandClassGet(void);
|
|||
IsSubclassPoly((land)->class, className ## Get())
|
||||
|
||||
|
||||
/* Stack Probe */
|
||||
|
||||
extern void StackProbe(Size depth);
|
||||
|
||||
|
||||
/* STATISTIC -- gather statistics (in some varieties)
|
||||
*
|
||||
* The argument of STATISTIC is an expression; the expansion followed by
|
||||
|
|
@ -1078,7 +1054,7 @@ extern void StackProbe(Size 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args,
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_SPARE, rnd_double());
|
||||
die(stress(arena, NULL, randomSize8, align, "MVFF",
|
||||
mps_class_mvff(), args), "stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
@ -182,6 +183,7 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args,
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_SPARE, rnd_double());
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, options, randomSize8, align, "MVFF debug",
|
||||
mps_class_mvff_debug(), args), "stress MVFF debug");
|
||||
|
|
|
|||
|
|
@ -111,10 +111,6 @@ typedef struct mps_pool_s { /* generic structure */
|
|||
Align alignment; /* alignment for units */
|
||||
Format format; /* format only if class->attr&AttrFMT */
|
||||
PoolFixMethod fix; /* fix method */
|
||||
double fillMutatorSize; /* bytes filled, mutator buffers */
|
||||
double emptyMutatorSize; /* bytes emptied, mutator buffers */
|
||||
double fillInternalSize; /* bytes filled, internal buffers */
|
||||
double emptyInternalSize; /* bytes emptied, internal buffers */
|
||||
} PoolStruct;
|
||||
|
||||
|
||||
|
|
@ -530,7 +526,6 @@ typedef struct mps_arena_class_s {
|
|||
ArenaVarargsMethod varargs;
|
||||
ArenaInitMethod init;
|
||||
ArenaFinishMethod finish;
|
||||
ArenaReservedMethod reserved;
|
||||
ArenaPurgeSpareMethod purgeSpare;
|
||||
ArenaExtendMethod extend;
|
||||
ArenaGrowMethod grow;
|
||||
|
|
@ -718,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 */
|
||||
|
|
@ -759,6 +755,7 @@ typedef struct mps_arena_s {
|
|||
|
||||
/* thread fields (<code/thread.c>) */
|
||||
RingStruct threadRing; /* ring of attached threads */
|
||||
RingStruct deadRing; /* ring of dead threads */
|
||||
Serial threadSerial; /* serial of next thread */
|
||||
|
||||
/* shield fields (<code/shield.c>) */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -148,11 +147,11 @@ typedef Res (*TraceFixMethod)(ScanState ss, Ref *refIO);
|
|||
/* Heap Walker */
|
||||
|
||||
/* This type is used by the PoolClass method Walk */
|
||||
typedef void (*FormattedObjectsStepMethod)(Addr obj, Format fmt, Pool pool,
|
||||
typedef void (*FormattedObjectsVisitor)(Addr obj, Format fmt, Pool pool,
|
||||
void *v, size_t s);
|
||||
|
||||
/* This type is used by the PoolClass method Walk */
|
||||
typedef void (*FreeBlockStepMethod)(Addr base, Addr limit, Pool pool, void *p);
|
||||
typedef void (*FreeBlockVisitor)(Addr base, Addr limit, Pool pool, void *p);
|
||||
|
||||
|
||||
/* Seg*Method -- see <design/seg/> */
|
||||
|
|
@ -230,10 +229,9 @@ typedef void (*PoolFramePopPendingMethod)(Pool pool, Buffer buf,
|
|||
AllocFrame frame);
|
||||
typedef Res (*PoolAddrObjectMethod)(Addr *pReturn,
|
||||
Pool pool, Seg seg, Addr addr);
|
||||
typedef void (*PoolWalkMethod)(Pool pool, Seg seg,
|
||||
FormattedObjectsStepMethod f,
|
||||
typedef void (*PoolWalkMethod)(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *v, size_t s);
|
||||
typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockVisitor f, void *p);
|
||||
typedef BufferClass (*PoolBufferClassMethod)(void);
|
||||
typedef Res (*PoolDescribeMethod)(Pool pool, mps_lib_FILE *stream, Count depth);
|
||||
typedef PoolDebugMixin (*PoolDebugMixinMethod)(Pool pool);
|
||||
|
|
@ -308,9 +306,9 @@ typedef Res (*LandDescribeMethod)(Land land, mps_lib_FILE *stream, Count depth);
|
|||
|
||||
/* Locus preferences */
|
||||
enum {
|
||||
LocusPrefHigh = 1,
|
||||
LocusPrefLow,
|
||||
LocusPrefZoneSet,
|
||||
LocusPrefHIGH = 1,
|
||||
LocusPrefLOW,
|
||||
LocusPrefZONESET,
|
||||
LocusPrefLIMIT
|
||||
};
|
||||
|
||||
|
|
@ -335,6 +333,7 @@ enum {
|
|||
/* This is checked by <code/mpsi.c#check>. */
|
||||
|
||||
enum {
|
||||
RankMIN = 0,
|
||||
RankAMBIG = 0,
|
||||
RankEXACT = 1,
|
||||
RankFINAL = 2,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
112
mps/code/mps.h
112
mps/code/mps.h
|
|
@ -151,84 +151,84 @@ typedef struct mps_arg_s {
|
|||
} val;
|
||||
} mps_arg_s;
|
||||
|
||||
extern const struct mps_key_s _mps_key_args_end;
|
||||
#define MPS_KEY_ARGS_END (&_mps_key_args_end)
|
||||
extern const struct mps_key_s _mps_key_ARGS_END;
|
||||
#define MPS_KEY_ARGS_END (&_mps_key_ARGS_END)
|
||||
extern mps_arg_s mps_args_none[];
|
||||
|
||||
extern const struct mps_key_s _mps_key_arena_size;
|
||||
#define MPS_KEY_ARENA_SIZE (&_mps_key_arena_size)
|
||||
extern const struct mps_key_s _mps_key_ARENA_SIZE;
|
||||
#define MPS_KEY_ARENA_SIZE (&_mps_key_ARENA_SIZE)
|
||||
#define MPS_KEY_ARENA_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_arena_grain_size;
|
||||
#define MPS_KEY_ARENA_GRAIN_SIZE (&_mps_key_arena_grain_size)
|
||||
extern const struct mps_key_s _mps_key_ARENA_GRAIN_SIZE;
|
||||
#define MPS_KEY_ARENA_GRAIN_SIZE (&_mps_key_ARENA_GRAIN_SIZE)
|
||||
#define MPS_KEY_ARENA_GRAIN_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_arena_zoned;
|
||||
#define MPS_KEY_ARENA_ZONED (&_mps_key_arena_zoned)
|
||||
extern const struct mps_key_s _mps_key_ARENA_ZONED;
|
||||
#define MPS_KEY_ARENA_ZONED (&_mps_key_ARENA_ZONED)
|
||||
#define MPS_KEY_ARENA_ZONED_FIELD b
|
||||
extern const struct mps_key_s _mps_key_format;
|
||||
#define MPS_KEY_FORMAT (&_mps_key_format)
|
||||
extern const struct mps_key_s _mps_key_FORMAT;
|
||||
#define MPS_KEY_FORMAT (&_mps_key_FORMAT)
|
||||
#define MPS_KEY_FORMAT_FIELD format
|
||||
extern const struct mps_key_s _mps_key_chain;
|
||||
#define MPS_KEY_CHAIN (&_mps_key_chain)
|
||||
extern const struct mps_key_s _mps_key_CHAIN;
|
||||
#define MPS_KEY_CHAIN (&_mps_key_CHAIN)
|
||||
#define MPS_KEY_CHAIN_FIELD chain
|
||||
extern const struct mps_key_s _mps_key_gen;
|
||||
#define MPS_KEY_GEN (&_mps_key_gen)
|
||||
extern const struct mps_key_s _mps_key_GEN;
|
||||
#define MPS_KEY_GEN (&_mps_key_GEN)
|
||||
#define MPS_KEY_GEN_FIELD u
|
||||
extern const struct mps_key_s _mps_key_rank;
|
||||
#define MPS_KEY_RANK (&_mps_key_rank)
|
||||
extern const struct mps_key_s _mps_key_RANK;
|
||||
#define MPS_KEY_RANK (&_mps_key_RANK)
|
||||
#define MPS_KEY_RANK_FIELD rank
|
||||
|
||||
extern const struct mps_key_s _mps_key_extend_by;
|
||||
#define MPS_KEY_EXTEND_BY (&_mps_key_extend_by)
|
||||
extern const struct mps_key_s _mps_key_EXTEND_BY;
|
||||
#define MPS_KEY_EXTEND_BY (&_mps_key_EXTEND_BY)
|
||||
#define MPS_KEY_EXTEND_BY_FIELD size
|
||||
extern const struct mps_key_s _mps_key_large_size;
|
||||
#define MPS_KEY_LARGE_SIZE (&_mps_key_large_size)
|
||||
extern const struct mps_key_s _mps_key_LARGE_SIZE;
|
||||
#define MPS_KEY_LARGE_SIZE (&_mps_key_LARGE_SIZE)
|
||||
#define MPS_KEY_LARGE_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_min_size;
|
||||
#define MPS_KEY_MIN_SIZE (&_mps_key_min_size)
|
||||
extern const struct mps_key_s _mps_key_MIN_SIZE;
|
||||
#define MPS_KEY_MIN_SIZE (&_mps_key_MIN_SIZE)
|
||||
#define MPS_KEY_MIN_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_mean_size;
|
||||
#define MPS_KEY_MEAN_SIZE (&_mps_key_mean_size)
|
||||
extern const struct mps_key_s _mps_key_MEAN_SIZE;
|
||||
#define MPS_KEY_MEAN_SIZE (&_mps_key_MEAN_SIZE)
|
||||
#define MPS_KEY_MEAN_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_max_size;
|
||||
#define MPS_KEY_MAX_SIZE (&_mps_key_max_size)
|
||||
extern const struct mps_key_s _mps_key_MAX_SIZE;
|
||||
#define MPS_KEY_MAX_SIZE (&_mps_key_MAX_SIZE)
|
||||
#define MPS_KEY_MAX_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_align;
|
||||
#define MPS_KEY_ALIGN (&_mps_key_align)
|
||||
extern const struct mps_key_s _mps_key_ALIGN;
|
||||
#define MPS_KEY_ALIGN (&_mps_key_ALIGN)
|
||||
#define MPS_KEY_ALIGN_FIELD align
|
||||
extern const struct mps_key_s _mps_key_spare;
|
||||
#define MPS_KEY_SPARE (&_mps_key_spare)
|
||||
#define MPS_KEY_SPARE_FIELD double
|
||||
extern const struct mps_key_s _mps_key_interior;
|
||||
#define MPS_KEY_INTERIOR (&_mps_key_interior)
|
||||
extern const struct mps_key_s _mps_key_SPARE;
|
||||
#define MPS_KEY_SPARE (&_mps_key_SPARE)
|
||||
#define MPS_KEY_SPARE_FIELD d
|
||||
extern const struct mps_key_s _mps_key_INTERIOR;
|
||||
#define MPS_KEY_INTERIOR (&_mps_key_INTERIOR)
|
||||
#define MPS_KEY_INTERIOR_FIELD b
|
||||
|
||||
extern const struct mps_key_s _mps_key_vmw3_top_down;
|
||||
#define MPS_KEY_VMW3_TOP_DOWN (&_mps_key_vmw3_top_down)
|
||||
extern const struct mps_key_s _mps_key_VMW3_TOP_DOWN;
|
||||
#define MPS_KEY_VMW3_TOP_DOWN (&_mps_key_VMW3_TOP_DOWN)
|
||||
#define MPS_KEY_VMW3_TOP_DOWN_FIELD b
|
||||
|
||||
extern const struct mps_key_s _mps_key_fmt_align;
|
||||
#define MPS_KEY_FMT_ALIGN (&_mps_key_fmt_align)
|
||||
extern const struct mps_key_s _mps_key_FMT_ALIGN;
|
||||
#define MPS_KEY_FMT_ALIGN (&_mps_key_FMT_ALIGN)
|
||||
#define MPS_KEY_FMT_ALIGN_FIELD align
|
||||
extern const struct mps_key_s _mps_key_fmt_header_size;
|
||||
#define MPS_KEY_FMT_HEADER_SIZE (&_mps_key_fmt_header_size)
|
||||
extern const struct mps_key_s _mps_key_FMT_HEADER_SIZE;
|
||||
#define MPS_KEY_FMT_HEADER_SIZE (&_mps_key_FMT_HEADER_SIZE)
|
||||
#define MPS_KEY_FMT_HEADER_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_fmt_scan;
|
||||
#define MPS_KEY_FMT_SCAN (&_mps_key_fmt_scan)
|
||||
extern const struct mps_key_s _mps_key_FMT_SCAN;
|
||||
#define MPS_KEY_FMT_SCAN (&_mps_key_FMT_SCAN)
|
||||
#define MPS_KEY_FMT_SCAN_FIELD fmt_scan
|
||||
extern const struct mps_key_s _mps_key_fmt_skip;
|
||||
#define MPS_KEY_FMT_SKIP (&_mps_key_fmt_skip)
|
||||
extern const struct mps_key_s _mps_key_FMT_SKIP;
|
||||
#define MPS_KEY_FMT_SKIP (&_mps_key_FMT_SKIP)
|
||||
#define MPS_KEY_FMT_SKIP_FIELD fmt_skip
|
||||
extern const struct mps_key_s _mps_key_fmt_fwd;
|
||||
#define MPS_KEY_FMT_FWD (&_mps_key_fmt_fwd)
|
||||
extern const struct mps_key_s _mps_key_FMT_FWD;
|
||||
#define MPS_KEY_FMT_FWD (&_mps_key_FMT_FWD)
|
||||
#define MPS_KEY_FMT_FWD_FIELD fmt_fwd
|
||||
extern const struct mps_key_s _mps_key_fmt_isfwd;
|
||||
#define MPS_KEY_FMT_ISFWD (&_mps_key_fmt_isfwd)
|
||||
extern const struct mps_key_s _mps_key_FMT_ISFWD;
|
||||
#define MPS_KEY_FMT_ISFWD (&_mps_key_FMT_ISFWD)
|
||||
#define MPS_KEY_FMT_ISFWD_FIELD fmt_isfwd
|
||||
extern const struct mps_key_s _mps_key_fmt_pad;
|
||||
#define MPS_KEY_FMT_PAD (&_mps_key_fmt_pad)
|
||||
extern const struct mps_key_s _mps_key_FMT_PAD;
|
||||
#define MPS_KEY_FMT_PAD (&_mps_key_FMT_PAD)
|
||||
#define MPS_KEY_FMT_PAD_FIELD fmt_pad
|
||||
extern const struct mps_key_s _mps_key_fmt_class;
|
||||
#define MPS_KEY_FMT_CLASS (&_mps_key_fmt_class)
|
||||
extern const struct mps_key_s _mps_key_FMT_CLASS;
|
||||
#define MPS_KEY_FMT_CLASS (&_mps_key_FMT_CLASS)
|
||||
#define MPS_KEY_FMT_CLASS_FIELD fmt_class
|
||||
|
||||
/* Maximum length of a keyword argument list. */
|
||||
|
|
@ -294,12 +294,12 @@ extern mps_rank_t mps_rank_weak(void);
|
|||
/* Root Modes */
|
||||
/* .rm: Keep in sync with <code/mpmtypes.h#rm> */
|
||||
|
||||
#define MPS_RM_CONST (((mps_rm_t)1<<0))
|
||||
#define MPS_RM_PROT (((mps_rm_t)1<<1))
|
||||
#define MPS_RM_CONST (((mps_rm_t)1<<0))
|
||||
#define MPS_RM_PROT (((mps_rm_t)1<<1))
|
||||
#define MPS_RM_PROT_INNER (((mps_rm_t)1<<1))
|
||||
|
||||
|
||||
/* Allocation Point */
|
||||
/* .ap: Keep in sync with <code/mpmst.h#ap>. */
|
||||
|
||||
typedef struct mps_ap_s { /* allocation point descriptor */
|
||||
mps_addr_t init; /* limit of initialized memory */
|
||||
|
|
@ -775,8 +775,8 @@ typedef struct mps_pool_debug_option_s {
|
|||
size_t free_size;
|
||||
} mps_pool_debug_option_s;
|
||||
|
||||
extern const struct mps_key_s _mps_key_pool_debug_options;
|
||||
#define MPS_KEY_POOL_DEBUG_OPTIONS (&_mps_key_pool_debug_options)
|
||||
extern const struct mps_key_s _mps_key_POOL_DEBUG_OPTIONS;
|
||||
#define MPS_KEY_POOL_DEBUG_OPTIONS (&_mps_key_POOL_DEBUG_OPTIONS)
|
||||
#define MPS_KEY_POOL_DEBUG_OPTIONS_FIELD pool_debug_options
|
||||
|
||||
extern void mps_pool_check_fenceposts(mps_pool_t);
|
||||
|
|
|
|||
|
|
@ -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,7 +1,7 @@
|
|||
/* mpsacl.h: MEMORY POOL SYSTEM ARENA CLASS "CL"
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef mpsacl_h
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
#include "mps.h"
|
||||
|
||||
/* Client arena base address argument */
|
||||
extern const struct mps_key_s _mps_key_arena_cl_addr;
|
||||
#define MPS_KEY_ARENA_CL_BASE (&_mps_key_arena_cl_addr)
|
||||
extern const struct mps_key_s _mps_key_ARENA_CL_BASE;
|
||||
#define MPS_KEY_ARENA_CL_BASE (&_mps_key_ARENA_CL_BASE)
|
||||
#define MPS_KEY_ARENA_CL_BASE_FIELD addr
|
||||
|
||||
extern mps_arena_class_t mps_arena_class_cl(void);
|
||||
|
|
@ -22,7 +22,7 @@ extern mps_arena_class_t mps_arena_class_cl(void);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
extern const struct mps_key_s _mps_key_ams_support_ambiguous;
|
||||
#define MPS_KEY_AMS_SUPPORT_AMBIGUOUS (&_mps_key_ams_support_ambiguous)
|
||||
extern const struct mps_key_s _mps_key_AMS_SUPPORT_AMBIGUOUS;
|
||||
#define MPS_KEY_AMS_SUPPORT_AMBIGUOUS (&_mps_key_AMS_SUPPORT_AMBIGUOUS)
|
||||
#define MPS_KEY_AMS_SUPPORT_AMBIGUOUS_FIELD b
|
||||
|
||||
extern mps_pool_class_t mps_class_ams(void);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
extern const struct mps_key_s _mps_key_awl_find_dependent;
|
||||
#define MPS_KEY_AWL_FIND_DEPENDENT (&_mps_key_awl_find_dependent)
|
||||
extern const struct mps_key_s _mps_key_AWL_FIND_DEPENDENT;
|
||||
#define MPS_KEY_AWL_FIND_DEPENDENT (&_mps_key_AWL_FIND_DEPENDENT)
|
||||
#define MPS_KEY_AWL_FIND_DEPENDENT_FIELD addr_method
|
||||
|
||||
extern mps_pool_class_t mps_class_awl(void);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
extern const struct mps_key_s _mps_key_mfs_unit_size;
|
||||
#define MPS_KEY_MFS_UNIT_SIZE (&_mps_key_mfs_unit_size)
|
||||
extern const struct mps_key_s _mps_key_MFS_UNIT_SIZE;
|
||||
#define MPS_KEY_MFS_UNIT_SIZE (&_mps_key_MFS_UNIT_SIZE)
|
||||
#define MPS_KEY_MFS_UNIT_SIZE_FIELD size
|
||||
|
||||
extern mps_pool_class_t mps_class_mfs(void);
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
extern const struct mps_key_s _mps_key_mvff_slot_high;
|
||||
#define MPS_KEY_MVFF_SLOT_HIGH (&_mps_key_mvff_slot_high)
|
||||
extern const struct mps_key_s _mps_key_MVFF_SLOT_HIGH;
|
||||
#define MPS_KEY_MVFF_SLOT_HIGH (&_mps_key_MVFF_SLOT_HIGH)
|
||||
#define MPS_KEY_MVFF_SLOT_HIGH_FIELD b
|
||||
extern const struct mps_key_s _mps_key_mvff_arena_high;
|
||||
#define MPS_KEY_MVFF_ARENA_HIGH (&_mps_key_mvff_arena_high)
|
||||
extern const struct mps_key_s _mps_key_MVFF_ARENA_HIGH;
|
||||
#define MPS_KEY_MVFF_ARENA_HIGH (&_mps_key_MVFF_ARENA_HIGH)
|
||||
#define MPS_KEY_MVFF_ARENA_HIGH_FIELD b
|
||||
extern const struct mps_key_s _mps_key_mvff_first_fit;
|
||||
#define MPS_KEY_MVFF_FIRST_FIT (&_mps_key_mvff_first_fit)
|
||||
extern const struct mps_key_s _mps_key_MVFF_FIRST_FIT;
|
||||
#define MPS_KEY_MVFF_FIRST_FIT (&_mps_key_MVFF_FIRST_FIT)
|
||||
#define MPS_KEY_MVFF_FIRST_FIT_FIELD b
|
||||
|
||||
#define mps_mvff_free_size mps_pool_free_size
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
extern const struct mps_key_s _mps_key_mvt_reserve_depth;
|
||||
#define MPS_KEY_MVT_RESERVE_DEPTH (&_mps_key_mvt_reserve_depth)
|
||||
extern const struct mps_key_s _mps_key_MVT_RESERVE_DEPTH;
|
||||
#define MPS_KEY_MVT_RESERVE_DEPTH (&_mps_key_MVT_RESERVE_DEPTH)
|
||||
#define MPS_KEY_MVT_RESERVE_DEPTH_FIELD count
|
||||
extern const struct mps_key_s _mps_key_mvt_frag_limit;
|
||||
#define MPS_KEY_MVT_FRAG_LIMIT (&_mps_key_mvt_frag_limit)
|
||||
extern const struct mps_key_s _mps_key_MVT_FRAG_LIMIT;
|
||||
#define MPS_KEY_MVT_FRAG_LIMIT (&_mps_key_MVT_FRAG_LIMIT)
|
||||
#define MPS_KEY_MVT_FRAG_LIMIT_FIELD d
|
||||
|
||||
extern mps_pool_class_t mps_class_mvt(void);
|
||||
|
|
|
|||
|
|
@ -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/>
|
||||
*
|
||||
|
|
@ -19,6 +19,11 @@
|
|||
* (between ArenaEnter and ArenaLeave) as this will leave the Arena in
|
||||
* an unsuitable state for re-entry.
|
||||
*
|
||||
* .note.avert: Use AVERT only when "inside" the Arena (between
|
||||
* ArenaEnter and ArenaLeave), as it's not thread-safe in all
|
||||
* varieties. Use AVER(TESTT) otherwise. See
|
||||
* <design/sig/#check.arg.unlocked>.
|
||||
*
|
||||
*
|
||||
* TRANSGRESSIONS (rule.impl.trans)
|
||||
*
|
||||
|
|
@ -243,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);
|
||||
}
|
||||
|
||||
|
|
@ -251,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);
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +319,7 @@ mps_res_t mps_arena_create_v(mps_arena_t *mps_arena_o,
|
|||
va_list varargs)
|
||||
{
|
||||
mps_arg_s args[MPS_ARGS_MAX];
|
||||
AVERT(ArenaClass, arena_class);
|
||||
AVER(TESTT(ArenaClass, arena_class));
|
||||
arena_class->varargs(args, varargs);
|
||||
return mps_arena_create_k(mps_arena_o, arena_class, args);
|
||||
}
|
||||
|
|
@ -642,7 +647,7 @@ mps_res_t mps_pool_create_v(mps_pool_t *mps_pool_o, mps_arena_t arena,
|
|||
mps_pool_class_t pool_class, va_list varargs)
|
||||
{
|
||||
mps_arg_s args[MPS_ARGS_MAX];
|
||||
AVERT(PoolClass, pool_class);
|
||||
AVER(TESTT(PoolClass, pool_class));
|
||||
pool_class->varargs(args, varargs);
|
||||
return mps_pool_create_k(mps_pool_o, arena, pool_class, args);
|
||||
}
|
||||
|
|
@ -923,7 +928,7 @@ mps_bool_t (mps_commit)(mps_ap_t mps_ap, mps_addr_t p, size_t size)
|
|||
AVER(p != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(p == mps_ap->init);
|
||||
AVER((void *)((char *)mps_ap->init + size) == mps_ap->alloc);
|
||||
AVER(PointerAdd(mps_ap->init, size) == mps_ap->alloc);
|
||||
|
||||
return mps_commit(mps_ap, p, size);
|
||||
}
|
||||
|
|
@ -1379,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);
|
||||
|
||||
|
|
@ -2000,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -111,9 +111,6 @@ int (mps_lib_memcmp)(const void *s1, const void *s2, size_t n)
|
|||
}
|
||||
|
||||
|
||||
/* @@@@ Platform specific conversion? */
|
||||
/* See http://devworld.apple.com/dev/techsupport/insidemac/OSUtilities/OSUtilities-94.html#MARKER-9-32 */
|
||||
|
||||
/* If your platform has a low-resolution clock(), and there are
|
||||
* higher-resolution clocks readily available, then using one of those
|
||||
* will improve MPS scheduling decisions and the quality of telemetry
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -97,28 +97,24 @@ Bool PoolCheck(Pool pool)
|
|||
/* normally pool->format iff PoolHasAttr(pool, AttrFMT), but during
|
||||
* pool initialization pool->format may not yet be set. */
|
||||
CHECKL(pool->format == NULL || PoolHasAttr(pool, AttrFMT));
|
||||
CHECKL(pool->fillMutatorSize >= 0.0);
|
||||
CHECKL(pool->emptyMutatorSize >= 0.0);
|
||||
CHECKL(pool->fillInternalSize >= 0.0);
|
||||
CHECKL(pool->emptyInternalSize >= 0.0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Common keywords to PoolInit */
|
||||
|
||||
ARG_DEFINE_KEY(format, Format);
|
||||
ARG_DEFINE_KEY(chain, Chain);
|
||||
ARG_DEFINE_KEY(gen, Cant);
|
||||
ARG_DEFINE_KEY(rank, Rank);
|
||||
ARG_DEFINE_KEY(extend_by, Size);
|
||||
ARG_DEFINE_KEY(large_size, Size);
|
||||
ARG_DEFINE_KEY(min_size, Size);
|
||||
ARG_DEFINE_KEY(mean_size, Size);
|
||||
ARG_DEFINE_KEY(max_size, Size);
|
||||
ARG_DEFINE_KEY(align, Align);
|
||||
ARG_DEFINE_KEY(spare, double);
|
||||
ARG_DEFINE_KEY(interior, Bool);
|
||||
ARG_DEFINE_KEY(FORMAT, Format);
|
||||
ARG_DEFINE_KEY(CHAIN, Chain);
|
||||
ARG_DEFINE_KEY(GEN, Cant);
|
||||
ARG_DEFINE_KEY(RANK, Rank);
|
||||
ARG_DEFINE_KEY(EXTEND_BY, Size);
|
||||
ARG_DEFINE_KEY(LARGE_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MIN_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MEAN_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MAX_SIZE, Size);
|
||||
ARG_DEFINE_KEY(ALIGN, Align);
|
||||
ARG_DEFINE_KEY(SPARE, double);
|
||||
ARG_DEFINE_KEY(INTERIOR, Bool);
|
||||
|
||||
|
||||
/* PoolInit -- initialize a pool
|
||||
|
|
@ -157,10 +153,6 @@ Res PoolInit(Pool pool, Arena arena, PoolClass class, ArgList args)
|
|||
pool->alignment = MPS_PF_ALIGN;
|
||||
pool->format = NULL;
|
||||
pool->fix = class->fix;
|
||||
pool->fillMutatorSize = 0.0;
|
||||
pool->emptyMutatorSize = 0.0;
|
||||
pool->fillInternalSize = 0.0;
|
||||
pool->emptyInternalSize = 0.0;
|
||||
|
||||
/* Initialise signature last; see <design/sig/> */
|
||||
pool->sig = PoolSig;
|
||||
|
|
@ -304,7 +296,6 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
/* All PoolAllocs should advance the allocation clock, so we count */
|
||||
/* it all in the fillMutatorSize field. */
|
||||
pool->fillMutatorSize += size;
|
||||
ArenaGlobals(PoolArena(pool))->fillMutatorSize += size;
|
||||
|
||||
EVENT3(PoolAlloc, pool, *pReturn, size);
|
||||
|
|
@ -321,6 +312,7 @@ void PoolFree(Pool pool, Addr old, Size size)
|
|||
AVER(old != NULL);
|
||||
/* The pool methods should check that old is in pool. */
|
||||
AVER(size > 0);
|
||||
AVER(AddrIsAligned(old, pool->alignment));
|
||||
AVER(PoolHasRange(pool, old, AddrAdd(old, size)));
|
||||
|
||||
(*pool->class->free)(pool, old, size);
|
||||
|
|
@ -336,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);
|
||||
|
|
@ -495,8 +487,7 @@ Res PoolAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
|||
|
||||
/* PoolWalk -- walk objects in this segment */
|
||||
|
||||
void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
void *p, size_t s)
|
||||
void PoolWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, void *p, size_t s)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Seg, seg);
|
||||
|
|
@ -512,7 +503,7 @@ void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
|||
* PoolFreeWalk is not required to find all free blocks.
|
||||
*/
|
||||
|
||||
void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
void PoolFreeWalk(Pool pool, FreeBlockVisitor f, void *p)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(FUNCHECK(f));
|
||||
|
|
@ -569,18 +560,6 @@ Res PoolDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
res = WriteF(stream, depth + 2,
|
||||
"fillMutatorSize $UKb\n",
|
||||
(WriteFU)(pool->fillMutatorSize / 1024),
|
||||
"emptyMutatorSize $UKb\n",
|
||||
(WriteFU)(pool->emptyMutatorSize / 1024),
|
||||
"fillInternalSize $UKb\n",
|
||||
(WriteFU)(pool->fillInternalSize / 1024),
|
||||
"emptyInternalSize $UKb\n",
|
||||
(WriteFU)(pool->emptyInternalSize / 1024),
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = (*pool->class->describe)(pool, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
|
|
@ -715,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);
|
||||
|
|
@ -648,8 +648,8 @@ Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
|||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
void PoolNoWalk(Pool pool, Seg seg,
|
||||
FormattedObjectsStepMethod f, void *p, size_t s)
|
||||
void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *p, size_t s)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Seg, seg);
|
||||
|
|
@ -662,7 +662,7 @@ void PoolNoWalk(Pool pool, Seg seg,
|
|||
}
|
||||
|
||||
|
||||
void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
void PoolTrivFreeWalk(Pool pool, FreeBlockVisitor f, void *p)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(FUNCHECK(f));
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ typedef struct AMCStruct *AMC;
|
|||
typedef struct amcGenStruct *amcGen;
|
||||
|
||||
/* Function returning TRUE if block in nailboarded segment is pinned. */
|
||||
typedef Bool (*amcPinnedMethod)(AMC amc, Nailboard board, Addr base, Addr limit);
|
||||
typedef Bool (*amcPinnedFunction)(AMC amc, Nailboard board, Addr base, Addr limit);
|
||||
|
||||
|
||||
/* forward declarations */
|
||||
|
|
@ -31,7 +31,6 @@ static Bool amcSegHasNailboard(Seg seg);
|
|||
static Nailboard amcSegNailboard(Seg seg);
|
||||
static Bool AMCCheck(AMC amc);
|
||||
static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
|
||||
static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
|
||||
extern PoolClass AMCZPoolClassGet(void);
|
||||
extern BufferClass amcBufClassGet(void);
|
||||
extern SegClass amcSegClassGet(void);
|
||||
|
|
@ -71,7 +70,7 @@ enum {
|
|||
|
||||
/* amcSegStruct -- AMC-specific fields appended to GCSegStruct
|
||||
*
|
||||
* .seq.old: The "old" flag is FALSE if the segment has never been
|
||||
* .seg.old: The "old" flag is FALSE if the segment has never been
|
||||
* collected, and so its size is accounted against the pool
|
||||
* generation's newSize; it is TRUE if the segment has been collected
|
||||
* at least once, and so its size is accounted against the pool
|
||||
|
|
@ -394,71 +393,6 @@ static amcGen amcSegGen(Seg seg)
|
|||
|
||||
#define AMCSig ((Sig)0x519A3C99) /* SIGnature AMC */
|
||||
|
||||
typedef struct PageRetStruct {
|
||||
Count pCond; /* pages Condemned */
|
||||
Count pRet; /* pages Retained (in place) */
|
||||
/* Small */
|
||||
Count pCS; /* pages Condemned in Small segments */
|
||||
Count pRS; /* pages Retained in Small segments */
|
||||
/* Medium */
|
||||
Count sCM; /* segments Condemned: Medium */
|
||||
/* ...= upper bound of how many extra pages it */
|
||||
/* would have cost, had we chosen to LSP-pad */
|
||||
/* all these segments. */
|
||||
Count pCM; /* pages Condemned in Medium segments */
|
||||
Count sRM; /* segments Retained: Medium */
|
||||
Count pRM; /* pages Retained in Medium segments: */
|
||||
Count pRM1; /* ...because obj 1 was preserved in place */
|
||||
/* ...because a rest obj was pip, causing: */
|
||||
Count pRMrr; /* ...retained rest pages (page where rest obj is) */
|
||||
Count pRMr1; /* ...retained obj 1 pages (purely NMR pad) */
|
||||
/* Large */
|
||||
Count sCL; /* segments Condemned: Large */
|
||||
/* ...= upper bound of how many extra pages it */
|
||||
/* has cost to LSP-pad all these segments. */
|
||||
Count pCL; /* pages Condemned in Large segments */
|
||||
Count sRL; /* segments Retained: Large */
|
||||
Count pRL; /* pages Retained in Large segments */
|
||||
Count pRLr; /* ...because a rest obj (actually LSP) was pip */
|
||||
|
||||
/* The interesting things about this report are:
|
||||
* - How many pages are actually being retained? (pRet)
|
||||
* - Percentage? (pRet/pCond)
|
||||
* - Is the major contribution from Small, Medium, or Large segs?
|
||||
*
|
||||
* Generally, pages retained because obj 1 needed to be preserved in
|
||||
* place are ok (because no alternative placement could have retained
|
||||
* fewer pages), but pages retained by a rest obj are unfortunate
|
||||
* (better placement, putting the small rest objs in their own seg,
|
||||
* would have retained fewer pages). In particular:
|
||||
*
|
||||
* The LSP threshold is a payoff between the wasted space from
|
||||
* LSP-padding, versus the risk of increased page-retention (due to
|
||||
* rest objs) from not LSP-padding.
|
||||
*
|
||||
* For Medium segs, where we do not do LSP-padding:
|
||||
* - LSP would have required at most sCM extra pages;
|
||||
* - the extra retention incurred by not LSP-padding is pRMr1.
|
||||
* A high pRMr1 => lots of Medium segs getting retained by the rest
|
||||
* objs tacked on after obj 1. Consider lowering LSP-threshold.
|
||||
*
|
||||
* For Large segs we do LSP padding. This has a cost; upper bound is
|
||||
* sCL extra pages. But the benefit should be greatly reduced ambig
|
||||
* refs to rest objs. With LSP, the only rest obj is the LSP pad
|
||||
* itself. We expect that ambig refs to this are rare, so currently
|
||||
* we do not implement .large.lsp-no-retain. But we do record the
|
||||
* occurrence of pages retained by a ref to an LSP pad: pPLr. A high
|
||||
* pRLr => perhaps .large.lsp-no-retain should be implemented?
|
||||
*
|
||||
* If the mutator is causing a lot of page retention, then sRM/pRM
|
||||
* and sRL/pRL should give some picture of the number of retained
|
||||
* objects and their average size.
|
||||
*/
|
||||
} PageRetStruct;
|
||||
|
||||
/* static => init'd to zero */
|
||||
static struct PageRetStruct pageretstruct_Zero;
|
||||
|
||||
typedef struct AMCStruct { /* <design/poolamc/#struct> */
|
||||
PoolStruct poolStruct; /* generic pool structure */
|
||||
RankSet rankSet; /* rankSet for entire pool */
|
||||
|
|
@ -471,13 +405,9 @@ typedef struct AMCStruct { /* <design/poolamc/#struct> */
|
|||
amcGen afterRampGen; /* the generation after rampGen */
|
||||
unsigned rampCount; /* <design/poolamc/#ramp.count> */
|
||||
int rampMode; /* <design/poolamc/#ramp.mode> */
|
||||
amcPinnedMethod pinned; /* function determining if block is pinned */
|
||||
amcPinnedFunction pinned; /* function determining if block is pinned */
|
||||
Size extendBy; /* segment size to extend pool by */
|
||||
Size largeSize; /* min size of "large" segments */
|
||||
|
||||
/* page retention in an in-progress trace */
|
||||
STATISTIC_DECL(PageRetStruct pageretstruct[TraceLIMIT]);
|
||||
|
||||
Sig sig; /* <design/pool/#outer-structure.sig> */
|
||||
} AMCStruct;
|
||||
|
||||
|
|
@ -804,8 +734,6 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args)
|
|||
AMC amc;
|
||||
Res res;
|
||||
Arena arena;
|
||||
TraceId ti;
|
||||
Trace trace;
|
||||
Index i;
|
||||
size_t genArraySize;
|
||||
size_t genCount;
|
||||
|
|
@ -815,16 +743,6 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args)
|
|||
Size largeSize = AMC_LARGE_SIZE_DEFAULT;
|
||||
ArgStruct arg;
|
||||
|
||||
/* Suppress a warning about this structure not being used when there
|
||||
are no statistics. Note that simply making the declaration conditional
|
||||
does not work, because we carefully reference expressions inside
|
||||
STATISTICS to prevent such warnings on parameters and local variables.
|
||||
It's just that clang 4.0 on Mac OS X does some sort of extra check
|
||||
that produces a special warnings about static variables. */
|
||||
#if !defined(STATISTICS)
|
||||
UNUSED(pageretstruct_Zero);
|
||||
#endif
|
||||
|
||||
AVER(pool != NULL);
|
||||
|
||||
amc = PoolAMC(pool);
|
||||
|
|
@ -844,7 +762,9 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args)
|
|||
largeSize = arg.val.size;
|
||||
|
||||
AVERT(Format, pool->format);
|
||||
AVER(FormatArena(pool->format) == arena);
|
||||
AVERT(Chain, chain);
|
||||
AVER(chain->arena == arena);
|
||||
AVER(extendBy > 0);
|
||||
AVER(largeSize > 0);
|
||||
/* TODO: it would be nice to be able to manage large objects that
|
||||
|
|
@ -853,6 +773,7 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args)
|
|||
* assertion catches this bad case. */
|
||||
AVER(largeSize >= extendBy);
|
||||
pool->alignment = pool->format->alignment;
|
||||
pool->fix = AMCFix;
|
||||
amc->rankSet = rankSet;
|
||||
|
||||
RingInit(&amc->genRing);
|
||||
|
|
@ -867,16 +788,6 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args)
|
|||
amc->rampCount = 0;
|
||||
amc->rampMode = RampOUTSIDE;
|
||||
|
||||
TRACE_SET_ITER(ti, trace, TraceSetUNIV, arena)
|
||||
STATISTIC(amc->pageretstruct[ti] = pageretstruct_Zero);
|
||||
TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena);
|
||||
|
||||
if(pool->format->headerSize == 0) {
|
||||
pool->fix = AMCFix;
|
||||
} else {
|
||||
pool->fix = AMCHeaderFix;
|
||||
}
|
||||
|
||||
if (interior) {
|
||||
amc->pinned = amcPinnedInterior;
|
||||
} else {
|
||||
|
|
@ -1308,24 +1219,6 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg)
|
|||
amc = PoolAMC(pool);
|
||||
AVERT(AMC, amc);
|
||||
|
||||
STATISTIC_STAT( {
|
||||
Count pages;
|
||||
Size size = SegSize(seg);
|
||||
AVER(SizeIsArenaGrains(size, pool->arena));
|
||||
pages = size / ArenaGrainSize(pool->arena);
|
||||
AVER(pages != 0);
|
||||
amc->pageretstruct[trace->ti].pCond += pages;
|
||||
if(pages == 1) {
|
||||
amc->pageretstruct[trace->ti].pCS += pages;
|
||||
} else if(size < amc->largeSize) {
|
||||
amc->pageretstruct[trace->ti].sCM += 1;
|
||||
amc->pageretstruct[trace->ti].pCM += pages;
|
||||
} else {
|
||||
amc->pageretstruct[trace->ti].sCL += 1;
|
||||
amc->pageretstruct[trace->ti].pCL += pages;
|
||||
}
|
||||
} );
|
||||
|
||||
gen = amcSegGen(seg);
|
||||
AVERT(amcGen, gen);
|
||||
if (!amcseg->old) {
|
||||
|
|
@ -1649,155 +1542,6 @@ fixInPlace: /* see <design/poolamc/>.Nailboard.emergency */
|
|||
* See <design/poolamc/#fix>.
|
||||
*/
|
||||
static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
||||
{
|
||||
Arena arena;
|
||||
AMC amc;
|
||||
Res res;
|
||||
Format format; /* cache of pool->format */
|
||||
Ref ref; /* reference to be fixed */
|
||||
Ref newRef; /* new location, if moved */
|
||||
Size length; /* length of object to be relocated */
|
||||
Buffer buffer; /* buffer to allocate new copy into */
|
||||
amcGen gen; /* generation of old copy of object */
|
||||
TraceSet grey; /* greyness of object being relocated */
|
||||
Seg toSeg; /* segment to which object is being relocated */
|
||||
|
||||
/* <design/trace/#fix.noaver> */
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVERT_CRITICAL(ScanState, ss);
|
||||
AVERT_CRITICAL(Seg, seg);
|
||||
AVER_CRITICAL(refIO != NULL);
|
||||
EVENT0(AMCFix);
|
||||
|
||||
/* For the moment, assume that the object was already marked. */
|
||||
/* (See <design/fix/#protocol.was-marked>.) */
|
||||
ss->wasMarked = TRUE;
|
||||
|
||||
/* If the reference is ambiguous, set up the datastructures for */
|
||||
/* managing a nailed segment. This involves marking the segment */
|
||||
/* as nailed, and setting up a per-word mark table */
|
||||
if(ss->rank == RankAMBIG) {
|
||||
/* .nail.new: Check to see whether we need a Nailboard for */
|
||||
/* this seg. We use "SegNailed(seg) == TraceSetEMPTY" */
|
||||
/* rather than "!amcSegHasNailboard(seg)" because this avoids */
|
||||
/* setting up a new nailboard when the segment was nailed, but */
|
||||
/* had no nailboard. This must be avoided because otherwise */
|
||||
/* assumptions in AMCFixEmergency will be wrong (essentially */
|
||||
/* we will lose some pointer fixes because we introduced a */
|
||||
/* nailboard). */
|
||||
if(SegNailed(seg) == TraceSetEMPTY) {
|
||||
res = amcSegCreateNailboard(seg, pool);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
++ss->nailCount;
|
||||
SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces));
|
||||
}
|
||||
amcFixInPlace(pool, seg, ss, refIO);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
amc = PoolAMC(pool);
|
||||
AVERT_CRITICAL(AMC, amc);
|
||||
format = pool->format;
|
||||
ref = *refIO;
|
||||
AVER_CRITICAL(SegBase(seg) <= ref);
|
||||
AVER_CRITICAL(ref < SegLimit(seg));
|
||||
arena = pool->arena;
|
||||
|
||||
/* .exposed.seg: Statements tagged ".exposed.seg" below require */
|
||||
/* that "seg" (that is: the 'from' seg) has been ShieldExposed. */
|
||||
ShieldExpose(arena, seg);
|
||||
newRef = (*format->isMoved)(ref); /* .exposed.seg */
|
||||
|
||||
if(newRef == (Addr)0) {
|
||||
Addr clientQ;
|
||||
clientQ = (*format->skip)(ref);
|
||||
|
||||
/* If object is nailed already then we mustn't copy it: */
|
||||
if (SegNailed(seg) != TraceSetEMPTY
|
||||
&& !(amcSegHasNailboard(seg)
|
||||
&& !(*amc->pinned)(amc, amcSegNailboard(seg), ref, clientQ)))
|
||||
{
|
||||
/* Segment only needs greying if there are new traces for */
|
||||
/* which we are nailing. */
|
||||
if(!TraceSetSub(ss->traces, SegNailed(seg))) {
|
||||
if(SegRankSet(seg) != RankSetEMPTY) /* not for AMCZ */
|
||||
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
|
||||
SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces));
|
||||
}
|
||||
res = ResOK;
|
||||
goto returnRes;
|
||||
} else if(ss->rank == RankWEAK) {
|
||||
/* Object is not preserved (neither moved, nor nailed) */
|
||||
/* hence, reference should be splatted. */
|
||||
goto updateReference;
|
||||
}
|
||||
/* Object is not preserved yet (neither moved, nor nailed) */
|
||||
/* so should be preserved by forwarding. */
|
||||
|
||||
/* <design/fix/#protocol.was-marked> */
|
||||
ss->wasMarked = FALSE;
|
||||
|
||||
/* Get the forwarding buffer from the object's generation. */
|
||||
gen = amcSegGen(seg);
|
||||
buffer = gen->forward;
|
||||
AVER_CRITICAL(buffer != NULL);
|
||||
|
||||
length = AddrOffset(ref, clientQ); /* .exposed.seg */
|
||||
STATISTIC_STAT(++ss->forwardedCount);
|
||||
ss->forwardedSize += length;
|
||||
do {
|
||||
res = BUFFER_RESERVE(&newRef, buffer, length, FALSE);
|
||||
if(res != ResOK)
|
||||
goto returnRes;
|
||||
|
||||
toSeg = BufferSeg(buffer);
|
||||
ShieldExpose(arena, toSeg);
|
||||
|
||||
/* Since we're moving an object from one segment to another, */
|
||||
/* union the greyness and the summaries together. */
|
||||
grey = SegGrey(seg);
|
||||
if(SegRankSet(seg) != RankSetEMPTY) { /* not for AMCZ */
|
||||
grey = TraceSetUnion(grey, ss->traces);
|
||||
SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg)));
|
||||
} else {
|
||||
AVER(SegRankSet(toSeg) == RankSetEMPTY);
|
||||
}
|
||||
SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey));
|
||||
|
||||
/* <design/trace/#fix.copy> */
|
||||
(void)AddrCopy(newRef, ref, length); /* .exposed.seg */
|
||||
|
||||
ShieldCover(arena, toSeg);
|
||||
} while(!BUFFER_COMMIT(buffer, newRef, length));
|
||||
ss->copiedSize += length;
|
||||
|
||||
(*format->move)(ref, newRef); /* .exposed.seg */
|
||||
|
||||
EVENT1(AMCFixForward, newRef);
|
||||
} else {
|
||||
/* reference to broken heart (which should be snapped out -- */
|
||||
/* consider adding to (non-existant) snap-out cache here) */
|
||||
STATISTIC_STAT(++ss->snapCount);
|
||||
}
|
||||
|
||||
/* .fix.update: update the reference to whatever the above code */
|
||||
/* decided it should be */
|
||||
updateReference:
|
||||
*refIO = newRef;
|
||||
res = ResOK;
|
||||
|
||||
returnRes:
|
||||
ShieldCover(arena, seg); /* .exposed.seg */
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* AMCHeaderFix -- fix a reference to the pool, with headers
|
||||
*
|
||||
* See <design/poolamc/#header.fix>.
|
||||
*/
|
||||
static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
||||
{
|
||||
Arena arena;
|
||||
AMC amc;
|
||||
|
|
@ -1805,6 +1549,7 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
Format format; /* cache of pool->format */
|
||||
Size headerSize; /* cache of pool->format->headerSize */
|
||||
Ref ref; /* reference to be fixed */
|
||||
Addr base; /* base address of reference */
|
||||
Ref newRef; /* new location, if moved */
|
||||
Addr newBase; /* base address of new copy */
|
||||
Size length; /* length of object to be relocated */
|
||||
|
|
@ -1853,6 +1598,8 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
headerSize = format->headerSize;
|
||||
ref = *refIO;
|
||||
AVER_CRITICAL(AddrAdd(SegBase(seg), headerSize) <= ref);
|
||||
base = AddrSub(ref, headerSize);
|
||||
AVER_CRITICAL(AddrIsAligned(base, PoolAlignment(pool)));
|
||||
AVER_CRITICAL(ref < SegLimit(seg)); /* see .ref-limit */
|
||||
arena = pool->arena;
|
||||
|
||||
|
|
@ -1919,7 +1666,7 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey));
|
||||
|
||||
/* <design/trace/#fix.copy> */
|
||||
(void)AddrCopy(newBase, AddrSub(ref, headerSize), length); /* .exposed.seg */
|
||||
(void)AddrCopy(newBase, base, length); /* .exposed.seg */
|
||||
|
||||
ShieldCover(arena, toSeg);
|
||||
} while (!BUFFER_COMMIT(buffer, newBase, length));
|
||||
|
|
@ -1958,8 +1705,6 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
Size preservedInPlaceSize = (Size)0;
|
||||
AMC amc;
|
||||
Size headerSize;
|
||||
Addr p1; /* first obj in seg */
|
||||
Bool obj1pip = FALSE; /* first obj was preserved in place */
|
||||
Addr padBase; /* base of next padding object */
|
||||
Size padLength; /* length of next padding object */
|
||||
|
||||
|
|
@ -1981,7 +1726,6 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
} else {
|
||||
limit = SegLimit(seg);
|
||||
}
|
||||
p1 = p;
|
||||
padBase = p;
|
||||
padLength = 0;
|
||||
while(p < limit) {
|
||||
|
|
@ -2003,8 +1747,6 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
if(preserve) {
|
||||
++preservedInPlaceCount;
|
||||
preservedInPlaceSize += length;
|
||||
if(p == p1)
|
||||
obj1pip = TRUE;
|
||||
if (padLength > 0) {
|
||||
/* Replace run of forwarding pointers and unreachable objects
|
||||
* with a padding object. */
|
||||
|
|
@ -2053,38 +1795,6 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
AVER(SegBuffer(seg) == NULL);
|
||||
|
||||
PoolGenFree(&gen->pgen, seg, 0, SegSize(seg), 0, Seg2amcSeg(seg)->deferred);
|
||||
} else {
|
||||
/* Seg retained */
|
||||
STATISTIC_STAT( {
|
||||
Count pages;
|
||||
Size size = SegSize(seg);
|
||||
AVER(SizeIsArenaGrains(size, pool->arena));
|
||||
pages = size / ArenaGrainSize(pool->arena);
|
||||
AVER(pages != 0);
|
||||
amc->pageretstruct[trace->ti].pRet += pages;
|
||||
if(pages == 1) {
|
||||
amc->pageretstruct[trace->ti].pRS += pages;
|
||||
} else if(size < amc->largeSize) {
|
||||
amc->pageretstruct[trace->ti].sRM += 1;
|
||||
amc->pageretstruct[trace->ti].pRM += pages;
|
||||
if(obj1pip) {
|
||||
amc->pageretstruct[trace->ti].pRM1 += pages;
|
||||
} else {
|
||||
/* Seg retained by a rest obj. Cost: one rest page, */
|
||||
/* plus pages-1 pages of pure padding. */
|
||||
amc->pageretstruct[trace->ti].pRMrr += 1;
|
||||
amc->pageretstruct[trace->ti].pRMr1 += pages - 1;
|
||||
}
|
||||
} else {
|
||||
amc->pageretstruct[trace->ti].sRL += 1;
|
||||
amc->pageretstruct[trace->ti].pRL += pages;
|
||||
if(!obj1pip) {
|
||||
/* Seg retained by a rest obj */
|
||||
amc->pageretstruct[trace->ti].pRLr += pages;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2135,40 +1845,9 @@ static void AMCReclaim(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* AMCTraceEnd -- emit end-of-trace event */
|
||||
|
||||
static void AMCTraceEnd(Pool pool, Trace trace)
|
||||
{
|
||||
AMC amc;
|
||||
TraceId ti;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
amc = PoolAMC(pool);
|
||||
AVERT(AMC, amc);
|
||||
ti = trace->ti;
|
||||
AVERT(TraceId, ti);
|
||||
|
||||
STATISTIC_STAT ({
|
||||
Count pRetMin = 100;
|
||||
PageRetStruct *pr = &amc->pageretstruct[ti];
|
||||
if(pr->pRet >= pRetMin) {
|
||||
EVENT21(AMCTraceEnd, ArenaEpoch(pool->arena), (EventFU)trace->why,
|
||||
ArenaGrainSize(pool->arena), amc->largeSize, pRetMin, pr->pCond,
|
||||
|
||||
pr->pRet, pr->pCS, pr->pRS, pr->sCM, pr->pCM, pr->sRM, pr->pRM,
|
||||
pr->pRM1, pr->pRMrr, pr->pRMr1, pr->sCL, pr->pCL, pr->sRL,
|
||||
pr->pRL, pr->pRLr);
|
||||
}
|
||||
*pr = pageretstruct_Zero;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* AMCWalk -- Apply function to (black) objects in segment */
|
||||
|
||||
static void AMCWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
static void AMCWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *p, size_t s)
|
||||
{
|
||||
Addr object, nextObject, limit;
|
||||
|
|
@ -2218,8 +1897,7 @@ static void AMCWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
|||
|
||||
/* amcWalkAll -- Apply a function to all (black) objects in a pool */
|
||||
|
||||
static void amcWalkAll(Pool pool, FormattedObjectsStepMethod f,
|
||||
void *p, size_t s)
|
||||
static void amcWalkAll(Pool pool, FormattedObjectsVisitor f, void *p, size_t s)
|
||||
{
|
||||
Arena arena;
|
||||
Ring ring, next, node;
|
||||
|
|
@ -2453,7 +2131,6 @@ DEFINE_POOL_CLASS(AMCZPoolClass, this)
|
|||
this->fix = AMCFix;
|
||||
this->fixEmergency = AMCFixEmergency;
|
||||
this->reclaim = AMCReclaim;
|
||||
this->traceEnd = AMCTraceEnd;
|
||||
this->rampBegin = AMCRampBegin;
|
||||
this->rampEnd = AMCRampEnd;
|
||||
this->addrObject = AMCAddrObject;
|
||||
|
|
@ -2574,7 +2251,6 @@ static Bool AMCCheck(AMC amc)
|
|||
/* if BEGIN or RAMPING, count must not be zero. */
|
||||
CHECKL((amc->rampCount != 0) || ((amc->rampMode != RampBEGIN) &&
|
||||
(amc->rampMode != RampRAMPING)));
|
||||
/* pageretstruct[ti] is statistics only, currently unchecked */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
|
||||
/* AMSSegFreeWalk -- walk the free space in a segment */
|
||||
|
||||
void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockStepMethod f, void *p)
|
||||
void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockVisitor f, void *p)
|
||||
{
|
||||
Pool pool;
|
||||
Seg seg;
|
||||
|
|
@ -785,7 +785,7 @@ static void AMSDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
* allocated in the pool. See <design/poolams/#init>.
|
||||
*/
|
||||
|
||||
ARG_DEFINE_KEY(ams_support_ambiguous, Bool);
|
||||
ARG_DEFINE_KEY(AMS_SUPPORT_AMBIGUOUS, Bool);
|
||||
|
||||
static Res AMSInit(Pool pool, ArgList args)
|
||||
{
|
||||
|
|
@ -831,13 +831,15 @@ Res AMSInitInternal(AMS ams, Format format, Chain chain, unsigned gen,
|
|||
Res res;
|
||||
|
||||
/* Can't check ams, it's not initialized. */
|
||||
AVERT(Format, format);
|
||||
AVERT(Chain, chain);
|
||||
AVER(gen <= ChainGens(chain));
|
||||
|
||||
pool = AMSPool(ams);
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Format, format);
|
||||
AVER(FormatArena(format) == PoolArena(pool));
|
||||
pool->format = format;
|
||||
AVERT(Chain, chain);
|
||||
AVER(gen <= ChainGens(chain));
|
||||
AVER(chain->arena == PoolArena(pool));
|
||||
|
||||
pool->alignment = pool->format->alignment;
|
||||
ams->grainShift = SizeLog2(PoolAlignment(pool));
|
||||
|
||||
|
|
@ -1653,7 +1655,7 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg)
|
|||
|
||||
/* AMSFreeWalk -- free block walking method of the pool class */
|
||||
|
||||
static void AMSFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
static void AMSFreeWalk(Pool pool, FreeBlockVisitor f, void *p)
|
||||
{
|
||||
AMS ams;
|
||||
Ring node, ring, nextNode; /* for iterating over the segments */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolams.h: AUTOMATIC MARK & SWEEP POOL CLASS INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: Internal interface to AMS functionality. */
|
||||
|
|
@ -175,7 +175,7 @@ extern Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg);
|
|||
|
||||
#define AMSChain(ams) ((ams)->chain)
|
||||
|
||||
extern void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockStepMethod f, void *p);
|
||||
extern void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockVisitor f, void *p);
|
||||
|
||||
extern void AMSSegFreeCheck(AMSSeg amsseg);
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ extern AMSPoolClass AMSDebugPoolClassGet(void);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -74,7 +74,7 @@ typedef struct awlStatTotalStruct {
|
|||
|
||||
/* the type of a function to find an object's dependent object */
|
||||
|
||||
typedef Addr (*FindDependentMethod)(Addr object);
|
||||
typedef Addr (*FindDependentFunction)(Addr object);
|
||||
|
||||
/* AWLStruct -- AWL pool structure
|
||||
*
|
||||
|
|
@ -86,7 +86,7 @@ typedef struct AWLStruct {
|
|||
Shift alignShift;
|
||||
PoolGenStruct pgen; /* generation representing the pool */
|
||||
Count succAccesses; /* number of successive single accesses */
|
||||
FindDependentMethod findDependent; /* to find a dependent object */
|
||||
FindDependentFunction findDependent; /* to find a dependent object */
|
||||
awlStatTotalStruct stats;
|
||||
Sig sig;
|
||||
} AWLStruct, *AWL;
|
||||
|
|
@ -544,13 +544,13 @@ static Addr awlNoDependent(Addr addr)
|
|||
|
||||
/* AWLInit -- initialize an AWL pool */
|
||||
|
||||
ARG_DEFINE_KEY(awl_find_dependent, Fun);
|
||||
ARG_DEFINE_KEY(AWL_FIND_DEPENDENT, Fun);
|
||||
|
||||
static Res AWLInit(Pool pool, ArgList args)
|
||||
{
|
||||
AWL awl;
|
||||
Format format;
|
||||
FindDependentMethod findDependent = awlNoDependent;
|
||||
FindDependentFunction findDependent = awlNoDependent;
|
||||
Chain chain;
|
||||
Res res;
|
||||
ArgStruct arg;
|
||||
|
|
@ -564,7 +564,7 @@ static Res AWLInit(Pool pool, ArgList args)
|
|||
ArgRequire(&arg, args, MPS_KEY_FORMAT);
|
||||
format = arg.val.format;
|
||||
if (ArgPick(&arg, args, MPS_KEY_AWL_FIND_DEPENDENT))
|
||||
findDependent = (FindDependentMethod)arg.val.addr_method;
|
||||
findDependent = (FindDependentFunction)arg.val.addr_method;
|
||||
if (ArgPick(&arg, args, MPS_KEY_CHAIN))
|
||||
chain = arg.val.chain;
|
||||
else {
|
||||
|
|
@ -575,6 +575,7 @@ static Res AWLInit(Pool pool, ArgList args)
|
|||
gen = arg.val.u;
|
||||
|
||||
AVERT(Format, format);
|
||||
AVER(FormatArena(format) == PoolArena(pool));
|
||||
pool->format = format;
|
||||
pool->alignment = format->alignment;
|
||||
|
||||
|
|
@ -583,6 +584,7 @@ static Res AWLInit(Pool pool, ArgList args)
|
|||
|
||||
AVERT(Chain, chain);
|
||||
AVER(gen <= ChainGens(chain));
|
||||
AVER(chain->arena == PoolArena(pool));
|
||||
|
||||
res = PoolGenInit(&awl->pgen, ChainGen(chain, gen), pool);
|
||||
if (res != ResOK)
|
||||
|
|
@ -1204,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)) {
|
||||
|
|
@ -1232,7 +1235,7 @@ static Res AWLAccess(Pool pool, Seg seg, Addr addr,
|
|||
|
||||
/* AWLWalk -- walk all objects */
|
||||
|
||||
static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
static void AWLWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *p, size_t s)
|
||||
{
|
||||
AWL awl;
|
||||
|
|
@ -1373,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -401,8 +401,7 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
|
|||
/* This walks over _all_ objects in the heap, whether they are */
|
||||
/* black or white, they are still validly formatted as this is */
|
||||
/* a leaf pool, so there can't be any dangling references */
|
||||
static void LOWalk(Pool pool, Seg seg,
|
||||
FormattedObjectsStepMethod f,
|
||||
static void LOWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *p, size_t s)
|
||||
{
|
||||
Addr base;
|
||||
|
|
@ -505,8 +504,10 @@ static Res LOInit(Pool pool, ArgList args)
|
|||
gen = arg.val.u;
|
||||
|
||||
AVERT(Format, pool->format);
|
||||
AVER(FormatArena(pool->format) == arena);
|
||||
AVERT(Chain, chain);
|
||||
AVER(gen <= ChainGens(chain));
|
||||
AVER(chain->arena == arena);
|
||||
|
||||
pool->alignment = pool->format->alignment;
|
||||
lo->alignShift = SizeLog2((Size)PoolAlignment(pool));
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ static void MFSVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
AVERT(ArgList, args);
|
||||
}
|
||||
|
||||
ARG_DEFINE_KEY(mfs_unit_size, Size);
|
||||
ARG_DEFINE_KEY(MFS_UNIT_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MFSExtendSelf, Bool);
|
||||
|
||||
static Res MFSInit(Pool pool, ArgList args)
|
||||
|
|
@ -94,6 +94,8 @@ static Res MFSInit(Pool pool, ArgList args)
|
|||
if (ArgPick(&arg, args, MFSExtendSelf))
|
||||
extendSelf = arg.val.b;
|
||||
|
||||
AVER(unitSize > 0);
|
||||
AVER(extendBy > 0);
|
||||
AVERT(Bool, extendSelf);
|
||||
|
||||
mfs = PoolPoolMFS(pool);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -215,11 +215,11 @@ static void MVTVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
* minSize, meanSize, maxSize, reserveDepth, fragLimit
|
||||
*/
|
||||
|
||||
ARG_DEFINE_KEY(mvt_min_size, Size);
|
||||
ARG_DEFINE_KEY(mvt_mean_size, Size);
|
||||
ARG_DEFINE_KEY(mvt_max_size, Size);
|
||||
ARG_DEFINE_KEY(mvt_reserve_depth, Count);
|
||||
ARG_DEFINE_KEY(mvt_frag_limit, double);
|
||||
ARG_DEFINE_KEY(MVT_MIN_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MVT_MEAN_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MVT_MAX_SIZE, Size);
|
||||
ARG_DEFINE_KEY(MVT_RESERVE_DEPTH, Count);
|
||||
ARG_DEFINE_KEY(MVT_FRAG_LIMIT, double);
|
||||
|
||||
static Res MVTInit(Pool pool, ArgList args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ static void MVFFReduce(MVFF mvff)
|
|||
targetFree = freeLimit / 2;
|
||||
|
||||
/* Each time around this loop we either break, or we free at least
|
||||
one page back to the arena, thus ensuring that eventually the
|
||||
one grain back to the arena, thus ensuring that eventually the
|
||||
loop will terminate */
|
||||
|
||||
/* NOTE: If this code becomes very hot, then the test of whether there's
|
||||
|
|
@ -133,7 +133,7 @@ static void MVFFReduce(MVFF mvff)
|
|||
&& LandFindLargest(&freeRange, &oldFreeRange, MVFFFreeLand(mvff),
|
||||
grainSize, FindDeleteNONE))
|
||||
{
|
||||
RangeStruct pageRange, oldRange;
|
||||
RangeStruct grainRange, oldRange;
|
||||
Size size;
|
||||
Res res;
|
||||
Addr base, limit;
|
||||
|
|
@ -143,7 +143,7 @@ static void MVFFReduce(MVFF mvff)
|
|||
base = AddrAlignUp(RangeBase(&freeRange), grainSize);
|
||||
limit = AddrAlignDown(RangeLimit(&freeRange), grainSize);
|
||||
|
||||
/* Give up if this block doesn't contain a whole aligned page,
|
||||
/* Give up if this block doesn't contain a whole aligned grain,
|
||||
even though smaller better-aligned blocks might, because
|
||||
LandFindLargest won't be able to find those anyway. */
|
||||
if (base >= limit)
|
||||
|
|
@ -155,12 +155,12 @@ static void MVFFReduce(MVFF mvff)
|
|||
if (size > freeSize - targetFree)
|
||||
size = SizeAlignUp(freeSize - targetFree, grainSize);
|
||||
|
||||
/* Calculate the range of pages we can return to the arena near the
|
||||
/* Calculate the range of grains we can return to the arena near the
|
||||
top end of the free memory (because we're first fit). */
|
||||
RangeInit(&pageRange, AddrSub(limit, size), limit);
|
||||
AVER(!RangeIsEmpty(&pageRange));
|
||||
AVER(RangesNest(&freeRange, &pageRange));
|
||||
AVER(RangeIsAligned(&pageRange, grainSize));
|
||||
RangeInit(&grainRange, AddrSub(limit, size), limit);
|
||||
AVER(!RangeIsEmpty(&grainRange));
|
||||
AVER(RangesNest(&freeRange, &grainRange));
|
||||
AVER(RangeIsAligned(&grainRange, grainSize));
|
||||
|
||||
/* Delete the range from the free list before attempting to delete
|
||||
it from the total allocated memory, so that we don't have
|
||||
|
|
@ -168,21 +168,21 @@ static void MVFFReduce(MVFF mvff)
|
|||
to delete from the TotalCBS we add back to the free list, which
|
||||
can't fail. */
|
||||
|
||||
res = LandDelete(&oldRange, MVFFFreeLand(mvff), &pageRange);
|
||||
res = LandDelete(&oldRange, MVFFFreeLand(mvff), &grainRange);
|
||||
if (res != ResOK)
|
||||
break;
|
||||
freeSize -= RangeSize(&pageRange);
|
||||
freeSize -= RangeSize(&grainRange);
|
||||
AVER(freeSize == LandSize(MVFFFreeLand(mvff)));
|
||||
|
||||
res = LandDelete(&oldRange, MVFFTotalLand(mvff), &pageRange);
|
||||
res = LandDelete(&oldRange, MVFFTotalLand(mvff), &grainRange);
|
||||
if (res != ResOK) {
|
||||
RangeStruct coalescedRange;
|
||||
res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &pageRange);
|
||||
res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &grainRange);
|
||||
AVER(res == ResOK);
|
||||
break;
|
||||
}
|
||||
|
||||
ArenaFree(RangeBase(&pageRange), RangeSize(&pageRange), MVFFPool(mvff));
|
||||
ArenaFree(RangeBase(&grainRange), RangeSize(&grainRange), MVFFPool(mvff));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -445,9 +445,9 @@ static void MVFFDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
|
||||
/* MVFFInit -- initialize method for MVFF */
|
||||
|
||||
ARG_DEFINE_KEY(mvff_slot_high, Bool);
|
||||
ARG_DEFINE_KEY(mvff_arena_high, Bool);
|
||||
ARG_DEFINE_KEY(mvff_first_fit, Bool);
|
||||
ARG_DEFINE_KEY(MVFF_SLOT_HIGH, Bool);
|
||||
ARG_DEFINE_KEY(MVFF_ARENA_HIGH, Bool);
|
||||
ARG_DEFINE_KEY(MVFF_FIRST_FIT, Bool);
|
||||
|
||||
static Res MVFFInit(Pool pool, ArgList args)
|
||||
{
|
||||
|
|
@ -520,7 +520,7 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
|
||||
LocusPrefInit(MVFFLocusPref(mvff));
|
||||
LocusPrefExpress(MVFFLocusPref(mvff),
|
||||
arenaHigh ? LocusPrefHigh : LocusPrefLow, NULL);
|
||||
arenaHigh ? LocusPrefHIGH : LocusPrefLOW, NULL);
|
||||
|
||||
/* An MFS pool is explicitly initialised for the two CBSs partly to
|
||||
* share space, but mostly to avoid a call to PoolCreate, so that
|
||||
|
|
@ -595,6 +595,7 @@ static Bool mvffFinishVisitor(Bool *deleteReturn, Land land, Range range,
|
|||
AVER(closureP != NULL);
|
||||
pool = closureP;
|
||||
AVERT(Pool, pool);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
ArenaFree(RangeBase(range), RangeSize(range), pool);
|
||||
|
|
@ -612,7 +613,8 @@ static void MVFFFinish(Pool pool)
|
|||
AVERT(MVFF, mvff);
|
||||
mvff->sig = SigInvalid;
|
||||
|
||||
b = LandIterateAndDelete(MVFFTotalLand(mvff), mvffFinishVisitor, pool, 0);
|
||||
b = LandIterateAndDelete(MVFFTotalLand(mvff), mvffFinishVisitor, pool,
|
||||
UNUSED_SIZE);
|
||||
AVER(b);
|
||||
AVER(LandSize(MVFFTotalLand(mvff)) == 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -387,6 +387,7 @@ static Res SNCInit(Pool pool, ArgList args)
|
|||
format = arg.val.format;
|
||||
|
||||
AVERT(Format, format);
|
||||
AVER(FormatArena(format) == PoolArena(pool));
|
||||
pool->format = format;
|
||||
snc->freeSegs = NULL;
|
||||
snc->sig = SNCSig;
|
||||
|
|
@ -624,7 +625,7 @@ static void SNCFramePopPending(Pool pool, Buffer buf, AllocFrame frame)
|
|||
}
|
||||
|
||||
|
||||
static void SNCWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
static void SNCWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
||||
void *p, size_t s)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci3fr.c: PROTECTION MUTATOR CONTEXT INTEL 386 (FREEBSD)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
|
|
@ -15,10 +15,10 @@
|
|||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .sp: The stack pointer in the context is ESP (x86) or RSP (x86_64).
|
||||
* .sp: The stack pointer in the context is ESP.
|
||||
*
|
||||
* .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX (or
|
||||
* their x86_64 equivalents) are assumed to be recorded in the context at
|
||||
* .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX,
|
||||
* and they are assumed to be recorded in the context at
|
||||
* pointer-aligned boundaries.
|
||||
*/
|
||||
|
||||
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
SRCID(prmci3fr, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_FR) || !defined(MPS_ARCH_I3)
|
||||
#error "prmci3fr.c is specific to MPS_OS_FR and MPS_ARCH_I3"
|
||||
#endif
|
||||
|
||||
|
||||
Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
||||
{
|
||||
|
|
@ -53,7 +57,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@
|
|||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .sp: The stack pointer in the context is uc_stack.ss_sp.
|
||||
* .sp: The stack pointer in the context is ESP.
|
||||
*
|
||||
* .context.regroots: The root regs are assumed to be recorded in the context
|
||||
* at pointer-aligned boundaries.
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* .assume.regref: The registers in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
SRCID(prmci3li, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_LI) || !defined(MPS_ARCH_I3)
|
||||
#error "prmci3li.c is specific to MPS_OS_LI and MPS_ARCH_I3"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prmci3AddressHoldingReg -- return an address of a register in a context */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
|
||||
/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Windows)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* .assume.regref: The registers in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
SRCID(prmci3w3, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_W3) || !defined(MPS_ARCH_I3)
|
||||
#error "prmci3w3.c is specific to MPS_OS_W3 and MPS_ARCH_I3"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prmci3AddressHoldingReg -- Return an address for a given machine register */
|
||||
|
||||
|
|
|
|||
|
|
@ -20,14 +20,18 @@
|
|||
* .context.regroots: The root regs are assumed to be recorded in the context
|
||||
* at pointer-aligned boundaries.
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* .assume.regref: The registers in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
#include "prmcxc.h"
|
||||
#include "prmci3.h"
|
||||
|
||||
SRCID(prmci3li, "$Id$");
|
||||
SRCID(prmci3xc, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_XC) || !defined(MPS_ARCH_I3)
|
||||
#error "prmci3xc.c is specific to MPS_OS_XC and MPS_ARCH_I3"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prmci3AddressHoldingReg -- return an address of a register in a context */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (FREEBSD)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
|
|
@ -9,10 +9,10 @@
|
|||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .sp: The stack pointer in the context is ESP (x86) or RSP (x86_64).
|
||||
* .sp: The stack pointer in the context is RSP.
|
||||
*
|
||||
* .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX (or
|
||||
* their x86_64 equivalents) are assumed to be recorded in the context at
|
||||
* .context.regroots: The root regs are RDI, RSI, RBX, RDX, RCX, RAX,
|
||||
* and they are assumed to be recorded in the context at
|
||||
* pointer-aligned boundaries.
|
||||
*/
|
||||
|
||||
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
SRCID(prmci6fr, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_FR) || !defined(MPS_ARCH_I6)
|
||||
#error "prmci6fr.c is specific to MPS_OS_FR and MPS_ARCH_I6"
|
||||
#endif
|
||||
|
||||
|
||||
Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
||||
{
|
||||
|
|
@ -47,7 +51,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .sp: The stack pointer in the context is uc_stack.ss_sp.
|
||||
* .sp: The stack pointer in the context is RSP.
|
||||
*
|
||||
* .context.regroots: The root regs are assumed to be recorded in the context
|
||||
* at pointer-aligned boundaries.
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* .assume.regref: The registers in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
SRCID(prmci6li, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_LI) || !defined(MPS_ARCH_I6)
|
||||
#error "prmci6li.c is specific to MPS_OS_LI and MPS_ARCH_I6"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prmci6AddressHoldingReg -- return an address of a register in a context */
|
||||
|
||||
|
|
@ -75,7 +79,7 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
}
|
||||
|
||||
|
||||
/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */
|
||||
/* Prmci6DecodeFaultContext -- decode fault to find faulting address and IP */
|
||||
|
||||
void Prmci6DecodeFaultContext(MRef *faultmemReturn,
|
||||
Byte **insvecReturn,
|
||||
|
|
@ -87,7 +91,7 @@ void Prmci6DecodeFaultContext(MRef *faultmemReturn,
|
|||
}
|
||||
|
||||
|
||||
/* Prmci3StepOverIns -- modify context to step over instruction */
|
||||
/* Prmci6StepOverIns -- modify context to step over instruction */
|
||||
|
||||
void Prmci6StepOverIns(MutatorFaultContext mfc, Size inslen)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
|
||||
/* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL x64 (Windows)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* .assume.regref: The registers in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
SRCID(prmci6w3, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_W3) || !defined(MPS_ARCH_I6)
|
||||
#error "prmci6w3.c is specific to MPS_OS_W3 and MPS_ARCH_I6"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prmci6AddressHoldingReg -- Return an address for a given machine register */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* prmci6xc.c: PROTECTION MUTATOR CONTEXT x64 (MAC OS X)
|
||||
/* prmci6xc.c: PROTECTION MUTATOR CONTEXT x64 (OS X)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
|
@ -9,22 +9,26 @@
|
|||
*
|
||||
* SOURCES
|
||||
*
|
||||
* .source.linux.kernel: Linux kernel source files.
|
||||
*
|
||||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .sp: The stack pointer in the context is RSP.
|
||||
*
|
||||
* .context.regroots: The root regs are assumed to be recorded in the context
|
||||
* at pointer-aligned boundaries.
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* .assume.regref: The registers in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
#include "prmcxc.h"
|
||||
#include "prmci6.h"
|
||||
|
||||
SRCID(prmci6li, "$Id$");
|
||||
SRCID(prmci6xc, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_XC) || !defined(MPS_ARCH_I6)
|
||||
#error "prmci6xc.c is specific to MPS_OS_XC and MPS_ARCH_I6"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prmci6AddressHoldingReg -- return an address of a register in a context */
|
||||
|
|
@ -70,7 +74,7 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
}
|
||||
|
||||
|
||||
/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */
|
||||
/* Prmci6DecodeFaultContext -- decode fault to find faulting address and IP */
|
||||
|
||||
void Prmci6DecodeFaultContext(MRef *faultmemReturn,
|
||||
Byte **insvecReturn,
|
||||
|
|
@ -81,7 +85,7 @@ void Prmci6DecodeFaultContext(MRef *faultmemReturn,
|
|||
}
|
||||
|
||||
|
||||
/* Prmci3StepOverIns -- modify context to step over instruction */
|
||||
/* Prmci6StepOverIns -- modify context to step over instruction */
|
||||
|
||||
void Prmci6StepOverIns(MutatorFaultContext mfc, Size inslen)
|
||||
{
|
||||
|
|
|
|||
78
mps/code/prot.h
Normal file
78
mps/code/prot.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/* prot.h: MEMORY PROTECTION INTERFACE
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/master/code/prot.h#1 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* See <design/prot/> for the design of the generic interface including
|
||||
* the contracts for these functions.
|
||||
*
|
||||
* This interface has several different implementations, typically one
|
||||
* per platform, see <code/prot*.c> for the various implementations,
|
||||
* and <design/prot*> for the corresponding designs.
|
||||
*/
|
||||
|
||||
#ifndef prot_h
|
||||
#define prot_h
|
||||
|
||||
#include "mpmtypes.h"
|
||||
|
||||
|
||||
/* Protection Interface */
|
||||
|
||||
extern void ProtSetup(void);
|
||||
extern Size ProtGranularity(void);
|
||||
extern void ProtSet(Addr base, Addr limit, AccessSet mode);
|
||||
extern void ProtSync(Arena arena);
|
||||
|
||||
|
||||
/* Mutator Fault Context */
|
||||
|
||||
extern Bool ProtCanStepInstruction(MutatorFaultContext context);
|
||||
extern Res ProtStepInstruction(MutatorFaultContext context);
|
||||
extern Addr MutatorFaultContextSP(MutatorFaultContext mfc);
|
||||
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc);
|
||||
|
||||
|
||||
#endif /* prot_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
|
@ -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 @@
|
|||
/* proti3.c: PROTECTION MUTATOR CONTEXT (INTEL 386)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: See <design/prot/> for the generic design of the interface
|
||||
* which is implemented in this module, including the contracts for the
|
||||
|
|
@ -54,6 +54,10 @@
|
|||
|
||||
SRCID(proti3, "$Id$");
|
||||
|
||||
#if !defined(MPS_ARCH_I3)
|
||||
#error "proti3.c is specific to MPS_ARCH_I3"
|
||||
#endif
|
||||
|
||||
|
||||
/* DecodeCB -- Decode an Intel x86 control byte into Hi, Medium & Low fields */
|
||||
|
||||
|
|
@ -243,7 +247,7 @@ Res ProtStepInstruction(MutatorFaultContext context)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* proti6.c: PROTECTION MUTATOR CONTEXT (x64)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: See <design/prot/> for the generic design of the interface
|
||||
* which is implemented in this module, including the contracts for the
|
||||
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
SRCID(proti6, "$Id$");
|
||||
|
||||
#if !defined(MPS_ARCH_I6)
|
||||
#error "proti6.c is specific to MPS_ARCH_I6"
|
||||
#endif
|
||||
|
||||
|
||||
static Bool IsSimpleMov(Size *inslenReturn,
|
||||
MRef *srcReturn,
|
||||
|
|
@ -84,7 +88,7 @@ Res ProtStepInstruction(MutatorFaultContext context)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/* 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
|
||||
* Darwin (OS X), FreeBSD, and Linux.
|
||||
* OS X, FreeBSD, and Linux.
|
||||
*
|
||||
* This file does not contain a signal handler. That's in protsgix.c
|
||||
* (for FreeBSD and Darwin on Intel); in protxcpp.c (for Darwin on
|
||||
* PowerPC); in protlii3.c (for Intel Linux).
|
||||
* This file does not contain a signal handler. That's in protsgix.c for
|
||||
* historical reasons (there used to be separate implementations for the
|
||||
* different flavours of Unix).
|
||||
*
|
||||
*
|
||||
* SOURCES
|
||||
|
|
@ -20,12 +20,11 @@
|
|||
* ASSUMPTIONS
|
||||
*
|
||||
* .assume.mprotect.base: We assume that the first argument to mprotect can
|
||||
* be safely passed as a void *. Single UNIX Specification Version 2
|
||||
* (aka X/OPEN XSH5) says that the parameter is a void *. Some
|
||||
* Unix-likes may declare this parameter as a caddr_t. FreeBSD used to
|
||||
* do this (on the now very obsolete FreeBSD 2.2.x series). The
|
||||
* Darwin man page documents it as caddr_t but it appears to be
|
||||
* implemented correctly as void *. caddr_t is usually char *.
|
||||
* be safely passed as a void *. Single UNIX Specification Version 2 (aka
|
||||
* X/OPEN XSH5) says that the parameter is a void *. Some Unix-likes may
|
||||
* declare this parameter as a caddr_t. FreeBSD used to do this (on the now
|
||||
* very obsolete FreeBSD 2.2.x series), as did OS X, but both now implement
|
||||
* it correctly as void *. caddr_t is usually char *.
|
||||
*
|
||||
* .assume.write-only: More of an anti-assumption really. We
|
||||
* assume that asking the OS for a write-only page (that is, flags =
|
||||
|
|
@ -67,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
|
||||
|
|
@ -123,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,13 +1,10 @@
|
|||
/* protli.c: PROTECTION FOR LINUX (INTEL 386)
|
||||
/* protli.c: PROTECTION FOR LINUX
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* SOURCES
|
||||
*
|
||||
* .source.i486: Intel486 Microprocessor Family Programmer's
|
||||
* Reference Manual
|
||||
*
|
||||
* .source.linux.kernel: Linux kernel source files.
|
||||
*/
|
||||
|
||||
|
|
@ -25,6 +22,9 @@
|
|||
|
||||
SRCID(protli, "$Id$");
|
||||
|
||||
#if !defined(MPS_OS_LI)
|
||||
#error "protli.c is specific to MPS_OS_LI"
|
||||
#endif
|
||||
|
||||
|
||||
/* The previously-installed signal action, as returned by */
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* Would ordinarily be part of protix.c (as the code is common to more
|
||||
* than one Unix-like operating system), but PowerPC Darwin requires a
|
||||
* different implementation of this module.
|
||||
* This implements protection exception handling using POSIX signals.
|
||||
* It is designed to run on any POSIX-compliant Unix, but currently is
|
||||
* only used on FreeBSD, as we have separate implementions for OS X
|
||||
* (see protxc.c) and Linux (see protli.c).
|
||||
*
|
||||
*
|
||||
* SOURCES
|
||||
*
|
||||
|
|
@ -18,11 +20,8 @@
|
|||
|
||||
#include "mpm.h"
|
||||
|
||||
#if !defined(MPS_OS_XC) && !defined(MPS_OS_FR)
|
||||
#error "protsgix.c is Unix-specific, currently for MPS_OS_FR or XC"
|
||||
#endif
|
||||
#if defined(MPS_OS_XC) && defined(MPS_ARCH_PP)
|
||||
#error "protsgix.c does not work on Darwin on PowerPC. Use protxcpp.c"
|
||||
#if !defined(MPS_OS_FR)
|
||||
#error "protsgix.c is Unix-specific, currently for MPS_OS_FR"
|
||||
#endif
|
||||
|
||||
#include <signal.h> /* for many functions */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -304,6 +306,7 @@ Res RootCreateReg(Root *rootReturn, Arena arena,
|
|||
AVERT(Arena, arena);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(Thread, thread);
|
||||
AVER(ThreadArena(thread) == arena);
|
||||
AVER(scan != NULL);
|
||||
|
||||
theUnion.reg.scan = scan;
|
||||
|
|
@ -314,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)
|
||||
|
|
@ -374,9 +384,9 @@ void RootDestroy(Root root)
|
|||
}
|
||||
|
||||
|
||||
/* RootArena -- return the rank of a root
|
||||
/* RootArena -- return the arena of a root
|
||||
*
|
||||
* Must be thread-safe. */
|
||||
* Must be thread-safe. See <design/interface-c/#check.testt> */
|
||||
|
||||
Arena RootArena(Root root)
|
||||
{
|
||||
|
|
@ -548,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 */
|
||||
|
||||
|
|
@ -697,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) ||
|
||||
|
|
@ -1174,7 +1174,7 @@ static void gcSegSetGreyInternal(Seg seg, TraceSet oldGrey, TraceSet grey)
|
|||
if (oldGrey == TraceSetEMPTY) {
|
||||
if (grey != TraceSetEMPTY) {
|
||||
AVER(RankSetIsSingle(seg->rankSet));
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
if (RankSetIsMember(seg->rankSet, rank)) {
|
||||
/* NOTE: We push the segment onto the front of the queue, so that
|
||||
we preserve some locality of scanning, and so that we tend to
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
@ -83,7 +83,7 @@ void (ShieldSuspend)(Arena arena)
|
|||
AVER(arena->insideShield);
|
||||
|
||||
if (!arena->suspended) {
|
||||
ThreadRingSuspend(ArenaThreadRing(arena));
|
||||
ThreadRingSuspend(ArenaThreadRing(arena), ArenaDeadRing(arena));
|
||||
arena->suspended = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -263,7 +266,7 @@ void (ShieldLeave)(Arena arena)
|
|||
/* Ensuring the mutator is running at this point
|
||||
* guarantees inv.outside.running */
|
||||
if (arena->suspended) {
|
||||
ThreadRingResume(ArenaThreadRing(arena));
|
||||
ThreadRingResume(ArenaThreadRing(arena), ArenaDeadRing(arena));
|
||||
arena->suspended = FALSE;
|
||||
}
|
||||
arena->insideShield = FALSE;
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
69
mps/code/sp.h
Normal file
69
mps/code/sp.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* sp.h: STACK PROBE INTERFACE
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/master/code/sp.h#1 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef sp_h
|
||||
#define sp_h
|
||||
|
||||
#include "mpmtypes.h"
|
||||
|
||||
|
||||
/* StackProbe -- probe above the stack to provoke early stack overflow
|
||||
*
|
||||
* This function should check that the stack has at least depth words
|
||||
* available, and if not, then provoke a stack overflow exception or
|
||||
* protection fault. The purpose is to ensure that the exception is
|
||||
* generated before taking the arena lock where it can be handled
|
||||
* safely, rather than at some later point where the arena lock is
|
||||
* held and so handling the exception may cause the MPS to be entered
|
||||
* recursively.
|
||||
*/
|
||||
|
||||
extern void StackProbe(Size depth);
|
||||
|
||||
|
||||
#endif /* sp_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -68,9 +67,9 @@ Bool SplayTreeCheck(SplayTree splay)
|
|||
*/
|
||||
|
||||
void SplayTreeInit(SplayTree splay,
|
||||
TreeCompare compare,
|
||||
TreeKeyMethod nodeKey,
|
||||
SplayUpdateNodeMethod updateNode)
|
||||
TreeCompareFunction compare,
|
||||
TreeKeyFunction nodeKey,
|
||||
SplayUpdateNodeFunction updateNode)
|
||||
{
|
||||
AVER(splay != NULL);
|
||||
AVER(FUNCHECK(compare));
|
||||
|
|
@ -298,7 +297,8 @@ typedef struct SplayStateStruct {
|
|||
*/
|
||||
|
||||
static Compare SplaySplitDown(SplayStateStruct *stateReturn,
|
||||
SplayTree splay, TreeKey key, TreeCompare compare)
|
||||
SplayTree splay, TreeKey key,
|
||||
TreeCompareFunction compare)
|
||||
{
|
||||
TreeStruct sentinel;
|
||||
Tree middle, leftLast, rightFirst, leftPrev, rightNext;
|
||||
|
|
@ -503,7 +503,8 @@ static Tree SplayZagZagRev(Tree middle, Tree *leftLastIO)
|
|||
*/
|
||||
|
||||
static Compare SplaySplitRev(SplayStateStruct *stateReturn,
|
||||
SplayTree splay, TreeKey key, TreeCompare compare)
|
||||
SplayTree splay, TreeKey key,
|
||||
TreeCompareFunction compare)
|
||||
{
|
||||
Tree middle, leftLast, rightFirst;
|
||||
Compare cmp;
|
||||
|
|
@ -650,7 +651,8 @@ static void SplayAssembleRev(SplayTree splay, SplayState state)
|
|||
/* SplaySplit -- call SplaySplitDown or SplaySplitRev as appropriate */
|
||||
|
||||
static Compare SplaySplit(SplayStateStruct *stateReturn,
|
||||
SplayTree splay, TreeKey key, TreeCompare compare)
|
||||
SplayTree splay, TreeKey key,
|
||||
TreeCompareFunction compare)
|
||||
{
|
||||
if (SplayHasUpdate(splay))
|
||||
return SplaySplitRev(stateReturn, splay, key, compare);
|
||||
|
|
@ -688,7 +690,8 @@ static void SplayAssemble(SplayTree splay, SplayState state)
|
|||
* See <design/splay/#impl.splay>.
|
||||
*/
|
||||
|
||||
static Compare SplaySplay(SplayTree splay, TreeKey key, TreeCompare compare)
|
||||
static Compare SplaySplay(SplayTree splay, TreeKey key,
|
||||
TreeCompareFunction compare)
|
||||
{
|
||||
Compare cmp;
|
||||
SplayStateStruct stateStruct;
|
||||
|
|
@ -1020,7 +1023,7 @@ Tree SplayTreeNext(SplayTree splay, TreeKey oldKey) {
|
|||
*/
|
||||
|
||||
static Res SplayNodeDescribe(Tree node, mps_lib_FILE *stream,
|
||||
TreeDescribeMethod nodeDescribe)
|
||||
TreeDescribeFunction nodeDescribe)
|
||||
{
|
||||
Res res;
|
||||
|
||||
|
|
@ -1083,8 +1086,8 @@ static Res SplayNodeDescribe(Tree node, mps_lib_FILE *stream,
|
|||
*/
|
||||
|
||||
typedef struct SplayFindClosureStruct {
|
||||
SplayTestNodeMethod testNode;
|
||||
SplayTestTreeMethod testTree;
|
||||
SplayTestNodeFunction testNode;
|
||||
SplayTestTreeFunction testTree;
|
||||
void *p;
|
||||
Size s;
|
||||
SplayTree splay;
|
||||
|
|
@ -1096,8 +1099,8 @@ static Compare SplayFindFirstCompare(Tree node, TreeKey key)
|
|||
SplayFindClosure closure;
|
||||
void *closureP;
|
||||
Size closureS;
|
||||
SplayTestNodeMethod testNode;
|
||||
SplayTestTreeMethod testTree;
|
||||
SplayTestNodeFunction testNode;
|
||||
SplayTestTreeFunction testTree;
|
||||
SplayTree splay;
|
||||
|
||||
AVERT(Tree, node);
|
||||
|
|
@ -1137,8 +1140,8 @@ static Compare SplayFindLastCompare(Tree node, TreeKey key)
|
|||
SplayFindClosure closure;
|
||||
void *closureP;
|
||||
Size closureS;
|
||||
SplayTestNodeMethod testNode;
|
||||
SplayTestTreeMethod testTree;
|
||||
SplayTestNodeFunction testNode;
|
||||
SplayTestTreeFunction testTree;
|
||||
SplayTree splay;
|
||||
|
||||
AVERT(Tree, node);
|
||||
|
|
@ -1190,8 +1193,8 @@ static Compare SplayFindLastCompare(Tree node, TreeKey key)
|
|||
*/
|
||||
|
||||
Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay,
|
||||
SplayTestNodeMethod testNode,
|
||||
SplayTestTreeMethod testTree,
|
||||
SplayTestNodeFunction testNode,
|
||||
SplayTestTreeFunction testTree,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
SplayFindClosureStruct closureStruct;
|
||||
|
|
@ -1254,8 +1257,8 @@ Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay,
|
|||
/* SplayFindLast -- As SplayFindFirst but in reverse address order */
|
||||
|
||||
Bool SplayFindLast(Tree *nodeReturn, SplayTree splay,
|
||||
SplayTestNodeMethod testNode,
|
||||
SplayTestTreeMethod testTree,
|
||||
SplayTestNodeFunction testNode,
|
||||
SplayTestTreeFunction testTree,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
SplayFindClosureStruct closureStruct;
|
||||
|
|
@ -1362,7 +1365,7 @@ void SplayNodeInit(SplayTree splay, Tree node)
|
|||
*/
|
||||
|
||||
Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, Count depth,
|
||||
TreeDescribeMethod nodeDescribe)
|
||||
TreeDescribeFunction nodeDescribe)
|
||||
{
|
||||
Res res;
|
||||
|
||||
|
|
@ -1398,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 @@
|
|||
/* splay.h: SPLAY TREE HEADER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: <design/splay/>
|
||||
*/
|
||||
|
|
@ -15,21 +15,21 @@
|
|||
|
||||
typedef struct SplayTreeStruct *SplayTree;
|
||||
|
||||
typedef Bool (*SplayTestNodeMethod)(SplayTree splay, Tree node,
|
||||
void *closureP, Size closureS);
|
||||
typedef Bool (*SplayTestTreeMethod)(SplayTree splay, Tree node,
|
||||
void *closureP, Size closureS);
|
||||
typedef Bool (*SplayTestNodeFunction)(SplayTree splay, Tree node,
|
||||
void *closureP, Size closureS);
|
||||
typedef Bool (*SplayTestTreeFunction)(SplayTree splay, Tree node,
|
||||
void *closureP, Size closureS);
|
||||
|
||||
typedef void (*SplayUpdateNodeMethod)(SplayTree splay, Tree node);
|
||||
typedef void (*SplayUpdateNodeFunction)(SplayTree splay, Tree node);
|
||||
extern void SplayTrivUpdate(SplayTree splay, Tree node);
|
||||
|
||||
#define SplayTreeSig ((Sig)0x5195B1A1) /* SIGnature SPLAY */
|
||||
|
||||
typedef struct SplayTreeStruct {
|
||||
Sig sig;
|
||||
TreeCompare compare;
|
||||
TreeKeyMethod nodeKey;
|
||||
SplayUpdateNodeMethod updateNode;
|
||||
TreeCompareFunction compare;
|
||||
TreeKeyFunction nodeKey;
|
||||
SplayUpdateNodeFunction updateNode;
|
||||
Tree root;
|
||||
} SplayTreeStruct;
|
||||
|
||||
|
|
@ -38,9 +38,9 @@ typedef struct SplayTreeStruct {
|
|||
|
||||
extern Bool SplayTreeCheck(SplayTree splay);
|
||||
extern void SplayTreeInit(SplayTree splay,
|
||||
TreeCompare compare,
|
||||
TreeKeyMethod nodeKey,
|
||||
SplayUpdateNodeMethod updateNode);
|
||||
TreeCompareFunction compare,
|
||||
TreeKeyFunction nodeKey,
|
||||
SplayUpdateNodeFunction updateNode);
|
||||
extern void SplayTreeFinish(SplayTree splay);
|
||||
|
||||
extern Bool SplayTreeInsert(SplayTree splay, Tree node);
|
||||
|
|
@ -55,24 +55,24 @@ extern Bool SplayTreeNeighbours(Tree *leftReturn,
|
|||
extern Tree SplayTreeFirst(SplayTree splay);
|
||||
extern Tree SplayTreeNext(SplayTree splay, TreeKey oldKey);
|
||||
|
||||
typedef Bool (*SplayFindMethod)(Tree *nodeReturn, SplayTree splay,
|
||||
SplayTestNodeMethod testNode,
|
||||
SplayTestTreeMethod testTree,
|
||||
void *closureP, Size closureS);
|
||||
typedef Bool (*SplayFindFunction)(Tree *nodeReturn, SplayTree splay,
|
||||
SplayTestNodeFunction testNode,
|
||||
SplayTestTreeFunction testTree,
|
||||
void *closureP, Size closureS);
|
||||
extern Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay,
|
||||
SplayTestNodeMethod testNode,
|
||||
SplayTestTreeMethod testTree,
|
||||
SplayTestNodeFunction testNode,
|
||||
SplayTestTreeFunction testTree,
|
||||
void *closureP, Size closureS);
|
||||
extern Bool SplayFindLast(Tree *nodeReturn, SplayTree splay,
|
||||
SplayTestNodeMethod testNode,
|
||||
SplayTestTreeMethod testTree,
|
||||
SplayTestNodeFunction testNode,
|
||||
SplayTestTreeFunction testTree,
|
||||
void *closureP, Size closureS);
|
||||
|
||||
extern void SplayNodeRefresh(SplayTree splay, Tree node);
|
||||
extern void SplayNodeInit(SplayTree splay, Tree node);
|
||||
|
||||
extern Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream,
|
||||
Count depth, TreeDescribeMethod nodeDescribe);
|
||||
Count depth, TreeDescribeFunction nodeDescribe);
|
||||
|
||||
extern void SplayDebugUpdate(SplayTree splay, Tree tree);
|
||||
extern Count SplayDebugCount(SplayTree splay);
|
||||
|
|
@ -83,7 +83,7 @@ extern Count SplayDebugCount(SplayTree splay);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
/* spw3i6.c: STACK PROBE FOR 64-BIT WINDOWS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* The function StackProbe ensures that the stack has at least depth
|
||||
* words available. It achieves this by exploiting an obscure but
|
||||
* documented feature of Microsoft's function _alloca: "A stack
|
||||
* overflow exception is generated if the space cannot be allocated."
|
||||
* _alloca: http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
|
||||
*
|
||||
* The purpose of this function to ensure that the stack overflow
|
||||
* exception is generated here (before taking the arena lock) where it
|
||||
* can be handled safely rather than at some later point where the
|
||||
* arena lock is held and so handling the exception may cause the MPS
|
||||
* to be entered recursively.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* _alloca */
|
||||
|
|
@ -28,7 +22,7 @@ void StackProbe(Size depth)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
/* ssixi6.c: UNIX/x64 STACK SCANNING
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This scans the stack and fixes the registers which may contain
|
||||
* roots. See <design/thread-manager/>
|
||||
*
|
||||
* This code was branched from ssixi3.c (32-bit Intel) initially for the
|
||||
* port to W3I6LL (Mac OS X on x86_64 with Clang).
|
||||
* port to XCI6LL (Mac OS X on x86_64 with Clang).
|
||||
*
|
||||
* This code is common to more than one Unix implementation on
|
||||
* Intel hardware (but is not portable Unix code). According to Wikipedia,
|
||||
|
|
@ -68,7 +68,7 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "mpstd.h"
|
||||
#include "mps.h"
|
||||
|
||||
#include <math.h> /* pow */
|
||||
#include <stdio.h> /* fflush, printf, putchar, stdout */
|
||||
|
||||
#define testArenaSIZE ((size_t)((size_t)64 << 20))
|
||||
|
|
@ -43,22 +44,6 @@ static mps_gen_param_s testChain[genCOUNT] = {
|
|||
{gen3SIZE, gen3MORTALITY},
|
||||
};
|
||||
|
||||
/* run the test several times, calling mps_arena_step at a different
|
||||
* frequency each time. When we call it often, tracing is never done
|
||||
* during allocation. When we call it never, tracing is always done
|
||||
* during allocation.
|
||||
*/
|
||||
|
||||
static unsigned long step_frequencies[] = {
|
||||
1000,
|
||||
5000,
|
||||
10000,
|
||||
1000000000, /* one billion */
|
||||
};
|
||||
|
||||
static unsigned test_number = 0;
|
||||
|
||||
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED))
|
||||
|
||||
|
|
@ -295,9 +280,8 @@ static void test_step(mps_arena_t arena, double multiplier)
|
|||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
static void test(mps_arena_t arena, unsigned long step_period)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_root_t exactRoot, ambigRoot;
|
||||
|
|
@ -310,9 +294,6 @@ static void *test(void *arg, size_t s)
|
|||
double total_mps_time, total_time;
|
||||
double t1;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
|
||||
die(dylan_fmt(&format, arena), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
|
||||
|
|
@ -336,8 +317,7 @@ static void *test(void *arg, size_t s)
|
|||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
|
||||
printf("Stepping every %lu allocations.\n",
|
||||
(unsigned long)step_frequencies[test_number]);
|
||||
printf("Stepping every %lu allocations.\n", step_period);
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
|
||||
|
|
@ -376,7 +356,7 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
++objs;
|
||||
|
||||
if (objs % step_frequencies[test_number] == 0)
|
||||
if (objs % step_period == 0)
|
||||
test_step(arena, 0.0);
|
||||
|
||||
if (objs % multiStepFREQ == 0)
|
||||
|
|
@ -484,33 +464,19 @@ static void *test(void *arg, size_t s)
|
|||
mps_pool_destroy(pool);
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(format);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
prepare_clock();
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
while (test_number < NELEMS(step_frequencies)) {
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
void *r;
|
||||
|
||||
set_clock_timing();
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(),
|
||||
testArenaSIZE),
|
||||
"arena_create");
|
||||
mps_arena_clamp(arena);
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
++ test_number;
|
||||
}
|
||||
|
||||
set_clock_timing();
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create");
|
||||
mps_arena_clamp(arena);
|
||||
test(arena, (unsigned long)pow(10, rnd() % 10));
|
||||
mps_arena_destroy(arena);
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,8 +222,8 @@ Res TableGrow(Table table, Count extraCapacity)
|
|||
|
||||
extern Res TableCreate(Table *tableReturn,
|
||||
Count length,
|
||||
TableAllocMethod tableAlloc,
|
||||
TableFreeMethod tableFree,
|
||||
TableAllocFunction tableAlloc,
|
||||
TableFreeFunction tableFree,
|
||||
void *allocClosure,
|
||||
Word unusedKey,
|
||||
Word deletedKey)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* table.h: Interface for a dictionary
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
|
@ -15,8 +15,8 @@ typedef struct TableStruct *Table;
|
|||
|
||||
#define TableSig ((Sig)0x5192AB13) /* SIGnature TABLE */
|
||||
|
||||
typedef void *(*TableAllocMethod)(void *closure, size_t size);
|
||||
typedef void (*TableFreeMethod)(void *closure, void *p, size_t size);
|
||||
typedef void *(*TableAllocFunction)(void *closure, size_t size);
|
||||
typedef void (*TableFreeFunction)(void *closure, void *p, size_t size);
|
||||
|
||||
typedef struct TableEntryStruct {
|
||||
Word key;
|
||||
|
|
@ -28,8 +28,8 @@ typedef struct TableStruct {
|
|||
Count length; /* Number of slots in the array */
|
||||
Count count; /* Active entries in the table */
|
||||
TableEntry array; /* Array of table slots */
|
||||
TableAllocMethod alloc;
|
||||
TableFreeMethod free;
|
||||
TableAllocFunction alloc;
|
||||
TableFreeFunction free;
|
||||
void *allocClosure;
|
||||
Word unusedKey; /* key marking unused (undefined) entries */
|
||||
Word deletedKey; /* key marking deleted entries */
|
||||
|
|
@ -37,8 +37,8 @@ typedef struct TableStruct {
|
|||
|
||||
extern Res TableCreate(Table *tableReturn,
|
||||
Count length,
|
||||
TableAllocMethod tableAlloc,
|
||||
TableFreeMethod tableFree,
|
||||
TableAllocFunction tableAlloc,
|
||||
TableFreeFunction tableFree,
|
||||
void *allocClosure,
|
||||
Word unusedKey,
|
||||
Word deletedKey);
|
||||
|
|
@ -60,7 +60,7 @@ extern Res TableGrow(Table table, Count extraCapacity);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue