1
Fork 0
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:
Richard Brooksby 2016-01-20 11:04:09 +00:00
commit 5dccd2e006
526 changed files with 8326 additions and 5227 deletions

View file

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

View file

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

View file

@ -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) {

View file

@ -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.
*

View file

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

View file

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

View file

@ -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

View file

@ -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);

View file

@ -41,6 +41,7 @@ Bool ArenaGrainSizeCheck(Size size)
static void ArenaTrivCompact(Arena arena, Trace trace);
static void arenaFreePage(Arena arena, Addr base, Pool pool);
static void arenaFreeLandFinish(Arena arena);
/* ArenaTrivDescribe -- produce trivial description of an arena */
@ -85,7 +86,6 @@ DEFINE_CLASS(AbstractArenaClass, class)
class->varargs = ArgTrivVarargs;
class->init = NULL;
class->finish = NULL;
class->reserved = NULL;
class->purgeSpare = ArenaNoPurgeSpare;
class->extend = ArenaNoExtend;
class->grow = ArenaNoGrow;
@ -113,7 +113,6 @@ Bool ArenaClassCheck(ArenaClass class)
CHECKL(FUNCHECK(class->varargs));
CHECKL(FUNCHECK(class->init));
CHECKL(FUNCHECK(class->finish));
CHECKL(FUNCHECK(class->reserved));
CHECKL(FUNCHECK(class->purgeSpare));
CHECKL(FUNCHECK(class->extend));
CHECKL(FUNCHECK(class->grow));
@ -142,9 +141,12 @@ Bool ArenaCheck(Arena arena)
CHECKD(Reservoir, &arena->reservoirStruct);
}
/* Can't check that limit>=size because we may call ArenaCheck */
/* while the size is being adjusted. */
/* .reserved.check: Would like to check that arena->committed <=
* arena->reserved, but that isn't always true in the VM arena.
* Memory is committed early on when VMChunkCreate calls vmArenaMap
* (to provide a place for the chunk struct) but is not recorded as
* reserved until ChunkInit calls ArenaChunkInsert.
*/
CHECKL(arena->committed <= arena->commitLimit);
CHECKL(arena->spareCommitted <= arena->committed);
@ -206,6 +208,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
arena->class = class;
arena->reserved = (Size)0;
arena->committed = (Size)0;
/* commitLimit may be overridden by init (but probably not */
/* as there's not much point) */
@ -236,10 +239,11 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
arena->sig = ArenaSig;
AVERT(Arena, arena);
/* Initialise a pool to hold the arena's CBS blocks. This pool can't be
allowed to extend itself using ArenaAlloc because it is used during
ArenaAlloc, so MFSExtendSelf is set to FALSE. Failures to extend are
handled where the Land is used. */
/* Initialise a pool to hold the CBS blocks for the arena's free
* land. This pool can't be allowed to extend itself using
* ArenaAlloc because it is used to implement ArenaAlloc, so
* MFSExtendSelf is set to FALSE. Failures to extend are handled
* where the free land is used: see arenaFreeLandInsertExtend. */
MPS_ARGS_BEGIN(piArgs) {
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSZonedBlockStruct));
@ -251,18 +255,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
if (res != ResOK)
goto failMFSInit;
/* Initialise the freeLand. */
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
res = LandInit(ArenaFreeLand(arena), CBSZonedLandClassGet(), arena,
ArenaGrainSize(arena), arena, liArgs);
} MPS_ARGS_END(liArgs);
AVER(res == ResOK); /* no allocation, no failure expected */
if (res != ResOK)
goto failLandInit;
/* Note that although freeLand is initialised, it doesn't have any memory
for its blocks, so hasFreeLand remains FALSE until later. */
/* initialize the reservoir, <design/reservoir/> */
res = ReservoirInit(&arena->reservoirStruct, arena);
if (res != ResOK)
@ -272,8 +264,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
return ResOK;
failReservoirInit:
LandFinish(ArenaFreeLand(arena));
failLandInit:
PoolFinish(ArenaCBSBlockPool(arena));
failMFSInit:
GlobalsFinish(ArenaGlobals(arena));
@ -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)

View file

@ -81,8 +81,15 @@ static Bool ClientChunkCheck(ClientChunk clChunk)
ATTRIBUTE_UNUSED
static Bool ClientArenaCheck(ClientArena clientArena)
{
Arena arena;
CHECKS(ClientArena, clientArena);
CHECKD(Arena, ClientArena2Arena(clientArena));
arena = ClientArena2Arena(clientArena);
CHECKD(Arena, arena);
/* See <code/arena.c#.reserved.check> */
CHECKL(arena->committed <= arena->reserved);
CHECKL(arena->spareCommitted == 0);
return TRUE;
}
@ -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);

View file

@ -397,7 +397,7 @@ static void testAllocAndIterate(Arena arena, Pool pool,
allocator->free(&offsetRegion);
}
}
LocusPrefExpress(&pref, LocusPrefZoneSet, &zone);
LocusPrefExpress(&pref, LocusPrefZONESET, &zone);
}
}

View file

@ -323,7 +323,8 @@ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
/* Copy VM descriptor into its place in the chunk. */
VMCopy(VMChunkVM(vmChunk), vm);
res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit, boot);
res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit,
VMReserved(VMChunkVM(vmChunk)), boot);
if (res != ResOK)
goto failChunkInit;
@ -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;

View file

@ -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);
}

View file

@ -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

View file

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

View file

@ -1,7 +1,7 @@
/* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .intro: This is a portable implementation of coalescing block
* structures.
@ -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.
*

View file

@ -36,7 +36,6 @@
# NOISY if defined and non-empty, causes commands to be emitted
# MPMPF platform-dependent C sources for the "mpm" part
# MPMS assembler sources for the "mpm" part (.s files)
# MPMPS pre-processor assembler sources for the "mpm" part (.S files)
#
# %%PART: When adding a new part, add a new parameter above for the
# files included in the part.
@ -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

View file

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

View file

@ -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.

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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.
*

View file

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

View file

@ -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;
}

View file

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

View file

@ -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.
#

View file

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

View file

@ -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);

View file

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

View file

@ -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);

View file

@ -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.
*

View file

@ -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.
#

View file

@ -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.
#

View file

@ -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.
#

View file

@ -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.
*

View file

@ -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.
*

View file

@ -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();

View file

@ -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.
*

View file

@ -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.
*

View file

@ -49,7 +49,7 @@ static void inc(unsigned long i)
tmp = shared;
shared = tmp+1;
i--;
LockReleaseMPM(lock);
LockRelease(lock);
}
}

View file

@ -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.
*

View file

@ -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;

View file

@ -1,7 +1,7 @@
/* mpm.c: GENERAL MPM SUPPORT
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .purpose: Miscellaneous support for the implementation of the MPM
* and pool classes.
@ -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.
*

View file

@ -1,7 +1,7 @@
/* mpm.h: MEMORY POOL MANAGER DEFINITIONS
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2002 Global Graphics Software.
*
* .trans.bufferinit: The Buffer data structure has an Init field and
@ -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.
*

View file

@ -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");

View file

@ -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>) */

View file

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

View file

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

View file

@ -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);

View file

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

View file

@ -1,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.
*

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -1,14 +1,14 @@
/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (c) 2002 Global Graphics Software.
*
* .purpose: This code bridges between the MPS interface to C,
* <code/mps.h>, and the internal MPM interfaces, as defined by
* <code/mpm.h>. .purpose.check: It performs checking of the C client's
* usage of the MPS Interface. .purpose.thread: It excludes multiple
* threads from the MPM by locking the Arena (see .thread-safety).
* threads from the MPM by locking the Arena (see <design/thread-safety/>).
*
* .design: <design/interface-c/>
*
@ -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.
*

View file

@ -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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/* pool.c: POOL IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2001 Global Graphics Software.
*
* DESIGN
@ -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.
*

View file

@ -1,7 +1,7 @@
/* poolabs.c: ABSTRACT POOL CLASSES
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2002 Global Graphics Software.
*
* PURPOSE
@ -334,7 +334,7 @@ Res PoolNoAccess(Pool pool, Seg seg, Addr addr,
AVERT(Seg, seg);
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
/* can't check AccessSet as there is no Check method */
AVERT(AccessSet, mode);
/* can't check context as there is no Check method */
UNUSED(mode);
UNUSED(context);
@ -360,7 +360,7 @@ Res PoolSegAccess(Pool pool, Seg seg, Addr addr,
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
AVER(SegPool(seg) == pool);
/* can't check AccessSet as there is no Check method */
AVERT(AccessSet, mode);
/* can't check context as there is no Check method */
UNUSED(addr);
@ -396,7 +396,7 @@ Res PoolSingleAccess(Pool pool, Seg seg, Addr addr,
AVER(SegBase(seg) <= addr);
AVER(addr < SegLimit(seg));
AVER(SegPool(seg) == pool);
/* can't check AccessSet as there is no Check method */
AVERT(AccessSet, mode);
/* can't check context as there is no Check method */
arena = PoolArena(pool);
@ -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.
*

View file

@ -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;
}

View file

@ -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 */

View file

@ -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.
*

View file

@ -1,7 +1,7 @@
/* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
*
* DESIGN
@ -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.
*

View file

@ -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));

View file

@ -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);

View file

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

View file

@ -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)
{

View file

@ -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);

View file

@ -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);

View file

@ -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.
*

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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.
*

View file

@ -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)
{

View file

@ -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 */

View file

@ -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
View 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.
*/

View file

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

View file

@ -1,7 +1,7 @@
/* 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.
*

View file

@ -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.
*

View file

@ -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.
*

View file

@ -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 */

View file

@ -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 */

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/* root.c: ROOT IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .purpose: This is the implementation of the root datatype.
*
@ -139,7 +139,7 @@ Bool RootCheck(Root root)
CHECKL(root->protBase != (Addr)0);
CHECKL(root->protLimit != (Addr)0);
CHECKL(root->protBase < root->protLimit);
/* there is no AccessSetCheck */
CHECKL(AccessSetCheck(root->pm));
} else {
CHECKL(root->protBase == (Addr)0);
CHECKL(root->protLimit == (Addr)0);
@ -263,7 +263,9 @@ Res RootCreateTable(Root *rootReturn, Arena arena,
AVERT(Arena, arena);
AVERT(Rank, rank);
AVER(base != 0);
AVER(base < limit);
AVER(AddrIsAligned(base, sizeof(Word)));
AVER(base < limit);
AVER(AddrIsAligned(limit, sizeof(Word)));
theUnion.table.base = base;
theUnion.table.limit = limit;
@ -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.
*

View file

@ -1,7 +1,7 @@
/* seg.c: SEGMENTS
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .design: The design for this module is <design/seg/>.
*
@ -529,7 +529,7 @@ Bool SegNextOfRing(Seg *segReturn, Arena arena, Pool pool, Ring next)
AVER_CRITICAL(segReturn != NULL); /* .seg.critical */
AVERT_CRITICAL(Arena, arena);
AVERT_CRITICAL(Pool, pool);
AVER_CRITICAL(RingCheck(next));
AVERT_CRITICAL(Ring, next);
if (next == PoolSegRing(pool)) {
if (!PoolNext(&pool, arena, pool) ||
@ -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.
*

View file

@ -1,7 +1,7 @@
/* shield.c: SHIELD IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* See: idea.shield, design.mps.shield.
*
@ -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
View 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.
*/

View file

@ -1,7 +1,7 @@
/* splay.c: SPLAY TREE IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
*
* .purpose: Splay trees are used to manage potentially unbounded
* collections of ordered things. In the MPS these are usually
@ -9,10 +9,9 @@
*
* .source: <design/splay>
*
* .note.stack: It's important that the MPS have a bounded stack
* size, and this is a problem for tree algorithms. Basically,
* we have to avoid recursion. TODO: Design documentation for this
* requirement, meanwhile see job003651 and job003640.
* .note.stack: It's important that the MPS have a bounded stack size,
* and this is a problem for tree algorithms. Basically, we have to
* avoid recursion. See design.mps.sp.sol.depth.no-recursion.
*/
@ -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.
*

View file

@ -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.
*

View file

@ -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.
*

View file

@ -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.
*

View file

@ -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;
}

View file

@ -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)

View file

@ -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