mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-23 07:12:12 -07:00
Catch-up merge from the master sources.
Copied from Perforce Change: 192170 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
baf2277b30
113 changed files with 1182 additions and 847 deletions
|
|
@ -71,7 +71,7 @@ make-install-dirs:
|
|||
install: @INSTALL_TARGET@
|
||||
|
||||
test-make-build:
|
||||
$(MAKE) $(TARGET_OPTS) testci testratio
|
||||
$(MAKE) $(TARGET_OPTS) testci testratio testscheme
|
||||
$(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 testpollnone
|
||||
|
||||
|
|
|
|||
|
|
@ -120,13 +120,17 @@ typedef struct closure_s {
|
|||
static void *kid_thread(void *arg)
|
||||
{
|
||||
void *marker = ▮
|
||||
mps_thr_t thread;
|
||||
mps_thr_t thread1, thread2;
|
||||
mps_root_t reg_root;
|
||||
mps_ap_t ap;
|
||||
closure_t cl = arg;
|
||||
|
||||
die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg");
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
/* Register the thread twice to check this is supported -- see
|
||||
* <design/thread-manager/#req.register.multi>
|
||||
*/
|
||||
die(mps_thread_reg(&thread1, arena), "thread_reg");
|
||||
die(mps_thread_reg(&thread2, arena), "thread_reg");
|
||||
die(mps_root_create_thread(®_root, arena, thread1, marker),
|
||||
"root_create");
|
||||
|
||||
die(mps_ap_create(&ap, cl->pool, mps_rank_exact()), "BufferCreate(fooey)");
|
||||
|
|
@ -136,7 +140,8 @@ static void *kid_thread(void *arg)
|
|||
mps_ap_destroy(ap);
|
||||
|
||||
mps_root_destroy(reg_root);
|
||||
mps_thread_dereg(thread);
|
||||
mps_thread_dereg(thread2);
|
||||
mps_thread_dereg(thread1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* apss.c: AP MANUAL ALLOC STRESS TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
|
@ -77,11 +77,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
|||
|
||||
/* allocate a load of objects */
|
||||
for (i=0; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i, align);
|
||||
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
res = make(&obj, ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
ps[i] = obj;
|
||||
allocated += ss[i] + debugOverhead;
|
||||
if (ss[i] >= sizeof(ps[i]))
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
|
|
@ -121,10 +122,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
|||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i, align);
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
res = make(&obj, ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
ps[i] = obj;
|
||||
allocated += ss[i] + debugOverhead;
|
||||
}
|
||||
check_allocated_size(pool, ap, allocated);
|
||||
|
|
@ -227,7 +230,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
arena_grain_size = rnd_grain(2 * testArenaSIZE);
|
||||
arena_grain_size = rnd_grain(testArenaSIZE);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size);
|
||||
|
|
@ -259,7 +262,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ static Res vmArenaChunkSize(Size *chunkSizeReturn, VMArena vmArena, Size size)
|
|||
overhead = 0;
|
||||
do {
|
||||
chunkSize = size + overhead;
|
||||
AVER(SizeIsAligned(chunkSize, grainSize));
|
||||
|
||||
/* See .overhead.chunk-struct. */
|
||||
overhead = SizeAlignUp(sizeof(VMChunkStruct), MPS_PF_ALIGN);
|
||||
|
|
@ -632,15 +633,18 @@ static Res VMArenaCreate(Arena *arenaReturn, ArgList args)
|
|||
goto failChunkCreate;
|
||||
|
||||
#if defined(AVER_AND_CHECK_ALL)
|
||||
/* Check that the computation of the chunk size in vmArenaChunkSize
|
||||
* was correct, now that we have the actual chunk for comparison. */
|
||||
/* Check the computation of the chunk size in vmArenaChunkSize, now
|
||||
* that we have the actual chunk for comparison. Note that
|
||||
* vmArenaChunkSize computes the smallest size with a given number
|
||||
* of usable bytes -- the actual chunk may be one grain larger. */
|
||||
{
|
||||
Size usableSize, computedChunkSize;
|
||||
usableSize = AddrOffset(PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
res = vmArenaChunkSize(&computedChunkSize, vmArena, usableSize);
|
||||
AVER(res == ResOK);
|
||||
AVER(computedChunkSize == ChunkSize(chunk));
|
||||
AVER(computedChunkSize == ChunkSize(chunk)
|
||||
|| computedChunkSize + grainSize == ChunkSize(chunk));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -119,54 +119,46 @@ Bool BufferCheck(Buffer buffer)
|
|||
*
|
||||
* See <code/mpmst.h> for structure definitions. */
|
||||
|
||||
Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth)
|
||||
static Res BufferAbsDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
BufferClass klass;
|
||||
|
||||
if (!TESTC(Buffer, buffer))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
klass = ClassOfPoly(Buffer, buffer);
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"Buffer $P ($U) {\n",
|
||||
(WriteFP)buffer, (WriteFU)buffer->serial,
|
||||
" class $P (\"$S\")\n",
|
||||
(WriteFP)klass, (WriteFS)ClassName(klass),
|
||||
" Arena $P\n", (WriteFP)buffer->arena,
|
||||
" Pool $P\n", (WriteFP)buffer->pool,
|
||||
" ", buffer->isMutator ? "Mutator" : "Internal", " Buffer\n",
|
||||
" mode $C$C$C$C (TRANSITION, LOGGED, FLIPPED, ATTACHED)\n",
|
||||
(WriteFC)((buffer->mode & BufferModeTRANSITION) ? 't' : '_'),
|
||||
(WriteFC)((buffer->mode & BufferModeLOGGED) ? 'l' : '_'),
|
||||
(WriteFC)((buffer->mode & BufferModeFLIPPED) ? 'f' : '_'),
|
||||
(WriteFC)((buffer->mode & BufferModeATTACHED) ? 'a' : '_'),
|
||||
" fillSize $UKb\n", (WriteFU)(buffer->fillSize / 1024),
|
||||
" emptySize $UKb\n", (WriteFU)(buffer->emptySize / 1024),
|
||||
" alignment $W\n", (WriteFW)buffer->alignment,
|
||||
" base $A\n", (WriteFA)buffer->base,
|
||||
" initAtFlip $A\n", (WriteFA)buffer->initAtFlip,
|
||||
" init $A\n", (WriteFA)buffer->ap_s.init,
|
||||
" alloc $A\n", (WriteFA)buffer->ap_s.alloc,
|
||||
" limit $A\n", (WriteFA)buffer->ap_s.limit,
|
||||
" poolLimit $A\n", (WriteFA)buffer->poolLimit,
|
||||
" alignment $W\n", (WriteFW)buffer->alignment,
|
||||
" rampCount $U\n", (WriteFU)buffer->rampCount,
|
||||
NULL);
|
||||
res = InstDescribe(CouldBeA(Inst, buffer), stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = Method(Buffer, buffer, describe)(buffer, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
return WriteF(stream, depth + 2,
|
||||
"serial $U\n", (WriteFU)buffer->serial,
|
||||
"Arena $P\n", (WriteFP)buffer->arena,
|
||||
"Pool $P\n", (WriteFP)buffer->pool,
|
||||
buffer->isMutator ? "Mutator" : "Internal", " Buffer\n",
|
||||
"mode $C$C$C$C (TRANSITION, LOGGED, FLIPPED, ATTACHED)\n",
|
||||
(WriteFC)((buffer->mode & BufferModeTRANSITION) ? 't' : '_'),
|
||||
(WriteFC)((buffer->mode & BufferModeLOGGED) ? 'l' : '_'),
|
||||
(WriteFC)((buffer->mode & BufferModeFLIPPED) ? 'f' : '_'),
|
||||
(WriteFC)((buffer->mode & BufferModeATTACHED) ? 'a' : '_'),
|
||||
"fillSize $UKb\n", (WriteFU)(buffer->fillSize / 1024),
|
||||
"emptySize $UKb\n", (WriteFU)(buffer->emptySize / 1024),
|
||||
"alignment $W\n", (WriteFW)buffer->alignment,
|
||||
"base $A\n", (WriteFA)buffer->base,
|
||||
"initAtFlip $A\n", (WriteFA)buffer->initAtFlip,
|
||||
"init $A\n", (WriteFA)buffer->ap_s.init,
|
||||
"alloc $A\n", (WriteFA)buffer->ap_s.alloc,
|
||||
"limit $A\n", (WriteFA)buffer->ap_s.limit,
|
||||
"poolLimit $A\n", (WriteFA)buffer->poolLimit,
|
||||
"alignment $W\n", (WriteFW)buffer->alignment,
|
||||
"rampCount $U\n", (WriteFU)buffer->rampCount,
|
||||
NULL);
|
||||
}
|
||||
|
||||
res = WriteF(stream, depth, "} Buffer $P ($U)\n",
|
||||
(WriteFP)buffer, (WriteFU)buffer->serial,
|
||||
NULL);
|
||||
return res;
|
||||
Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
return Method(Buffer, buffer, describe)(buffer, stream, depth);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -493,7 +485,7 @@ Res BufferReserve(Addr *pReturn, Buffer buffer, Size size)
|
|||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, BufferPool(buffer)->alignment));
|
||||
AVER(BufferIsReady(buffer));
|
||||
AVER(BufferIsReady(buffer)); /* <design/check/#.common> */
|
||||
|
||||
/* Is there enough room in the unallocated portion of the buffer to */
|
||||
/* satisfy the request? If so, just increase the alloc marker and */
|
||||
|
|
@ -1006,20 +998,6 @@ static void bufferNoReassignSeg(Buffer buffer, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* bufferTrivDescribe -- basic Buffer describe method */
|
||||
|
||||
static Res bufferTrivDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
if (!TESTT(Buffer, buffer))
|
||||
return ResFAIL;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
UNUSED(depth);
|
||||
/* dispatching function does it all */
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* BufferClassCheck -- check the consistency of a BufferClass */
|
||||
|
||||
Bool BufferClassCheck(BufferClass klass)
|
||||
|
|
@ -1059,7 +1037,7 @@ DEFINE_CLASS(Buffer, Buffer, klass)
|
|||
klass->finish = BufferAbsFinish;
|
||||
klass->attach = bufferTrivAttach;
|
||||
klass->detach = bufferTrivDetach;
|
||||
klass->describe = bufferTrivDescribe;
|
||||
klass->describe = BufferAbsDescribe;
|
||||
klass->seg = bufferNoSeg;
|
||||
klass->rankSet = bufferTrivRankSet;
|
||||
klass->setRankSet = bufferNoSetRankSet;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .intro: This is a portable implementation of coalescing block
|
||||
* structures.
|
||||
|
|
@ -441,6 +441,9 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block)
|
|||
*
|
||||
* .insert.alloc: Will only allocate a block if the range does not
|
||||
* abut an existing range.
|
||||
*
|
||||
* .insert.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
static Res cbsInsert(Range rangeReturn, Land land, Range range)
|
||||
|
|
@ -454,9 +457,9 @@ static Res cbsInsert(Range rangeReturn, Land land, Range range)
|
|||
Bool leftMerge, rightMerge;
|
||||
Size oldSize;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, LandAlignment(land)));
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVERT_CRITICAL(Range, range);
|
||||
AVER_CRITICAL(RangeIsAligned(range, LandAlignment(land)));
|
||||
|
||||
base = RangeBase(range);
|
||||
limit = RangeLimit(range);
|
||||
|
|
@ -526,14 +529,14 @@ static Res cbsInsert(Range rangeReturn, Land land, Range range)
|
|||
cbsBlockInsert(cbs, block);
|
||||
}
|
||||
|
||||
AVER(newBase <= base);
|
||||
AVER(newLimit >= limit);
|
||||
AVER_CRITICAL(newBase <= base);
|
||||
AVER_CRITICAL(newLimit >= limit);
|
||||
RangeInit(rangeReturn, newBase, newLimit);
|
||||
|
||||
return ResOK;
|
||||
|
||||
fail:
|
||||
AVER(res != ResOK);
|
||||
AVER_CRITICAL(res != ResOK);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1163,7 +1166,7 @@ DEFINE_CLASS(Land, CBSZoned, klass)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ endif
|
|||
# EXTRA TARGETS
|
||||
#
|
||||
# Don't build mpseventsql by default (might not have sqlite3 installed),
|
||||
# but do build mpseventcnv and mpseventtxt.
|
||||
# but do build mpseventcnv, mpseventpy and mpseventtxt.
|
||||
|
||||
EXTRA_TARGETS ?= mpseventcnv mpseventtxt
|
||||
EXTRA_TARGETS ?= mpseventcnv mpseventpy mpseventtxt
|
||||
|
||||
|
||||
#
|
||||
|
|
@ -332,8 +332,7 @@ RATIO=$$(awk "BEGIN{print int(100 * $$TIME_HOT / $$TIME_RASH)}"); \
|
|||
printf "Performance ratio (hot/rash) for $(2): %d%%\n" $$RATIO
|
||||
endef
|
||||
|
||||
.PHONY: testratio
|
||||
testratio:
|
||||
testratio: phony
|
||||
$(MAKE) -f $(PFM).gmk VARIETY=hot djbench gcbench
|
||||
$(MAKE) -f $(PFM).gmk VARIETY=rash djbench gcbench
|
||||
$(call ratio,gcbench,amc)
|
||||
|
|
@ -354,6 +353,12 @@ $(PFM)/$(VARIETY)/testmmqa:
|
|||
(cd ../test && $(MMQA) runset testsets/passing)
|
||||
|
||||
|
||||
# == Toy Scheme interpreter ==
|
||||
|
||||
testscheme: phony
|
||||
$(MAKE) -C ../example/scheme test
|
||||
|
||||
|
||||
# These convenience targets allow one to type "make foo" to build target
|
||||
# foo in selected varieties (or none, for the latter rule).
|
||||
|
||||
|
|
@ -572,6 +577,9 @@ $(PFM)/$(VARIETY)/zmess: $(PFM)/$(VARIETY)/zmess.o \
|
|||
$(PFM)/$(VARIETY)/mpseventcnv: $(PFM)/$(VARIETY)/eventcnv.o \
|
||||
$(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/mpseventpy: $(PFM)/$(VARIETY)/eventpy.o \
|
||||
$(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/mpseventtxt: $(PFM)/$(VARIETY)/eventtxt.o \
|
||||
$(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
|
|
@ -315,6 +315,9 @@ $(PFM)\$(VARIETY)\ztfm.exe: $(PFM)\$(VARIETY)\ztfm.obj \
|
|||
$(PFM)\$(VARIETY)\mpseventcnv.exe: $(PFM)\$(VARIETY)\eventcnv.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib
|
||||
|
||||
$(PFM)\$(VARIETY)\mpseventpy.exe: $(PFM)\$(VARIETY)\eventpy.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib
|
||||
|
||||
$(PFM)\$(VARIETY)\mpseventtxt.exe: $(PFM)\$(VARIETY)\eventtxt.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib
|
||||
|
||||
|
|
@ -335,6 +338,9 @@ $(PFM)\$(VARIETY)\replaysw.obj: $(PFM)\$(VARIETY)\replay.obj
|
|||
$(PFM)\$(VARIETY)\mpseventcnv.obj: $(PFM)\$(VARIETY)\eventcnv.obj
|
||||
copy $** $@ >nul:
|
||||
|
||||
$(PFM)\$(VARIETY)\mpseventpy.obj: $(PFM)\$(VARIETY)\eventpy.obj
|
||||
copy $** $@ >nul:
|
||||
|
||||
$(PFM)\$(VARIETY)\mpseventtxt.obj: $(PFM)\$(VARIETY)\eventtxt.obj
|
||||
copy $** $@ >nul:
|
||||
|
||||
|
|
@ -385,7 +391,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ TEST_TARGETS=\
|
|||
# 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
|
||||
EXTRA_TARGETS=mpseventcnv.exe mpseventpy.exe mpseventtxt.exe
|
||||
OPTIONAL_TARGETS=mpseventsql.exe
|
||||
|
||||
# This target records programs that we were once able to build but
|
||||
|
|
|
|||
|
|
@ -610,6 +610,29 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* POSIX thread extensions configuration -- see <code/pthrdext.c> */
|
||||
|
||||
#if defined(MPS_OS_LI) || defined(MPS_OS_FR)
|
||||
|
||||
/* PTHREADEXT_SIGSUSPEND -- signal used to suspend a thread
|
||||
* See <design/pthreadext/#impl.signals>
|
||||
*/
|
||||
#if defined(CONFIG_PTHREADEXT_SIGSUSPEND)
|
||||
#define PTHREADEXT_SIGSUSPEND CONFIG_PTHREADEXT_SIGSUSPEND
|
||||
#else
|
||||
#define PTHREADEXT_SIGSUSPEND SIGXFSZ
|
||||
#endif
|
||||
|
||||
/* PTHREADEXT_SIGRESUME -- signal used to resume a thread
|
||||
* See <design/pthreadext/#impl.signals>
|
||||
*/
|
||||
#if defined(CONFIG_PTHREADEXT_SIGRESUME)
|
||||
#define PTHREADEXT_SIGRESUME CONFIG_PTHREADEXT_SIGRESUME
|
||||
#else
|
||||
#define PTHREADEXT_SIGRESUME SIGXCPU
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Tracer Configuration -- see <code/trace.c> */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* dbgpool.c: POOL DEBUG MIXIN
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .source: design.mps.object-debug
|
||||
|
|
@ -523,7 +523,7 @@ static void fenceFree(PoolDebugMixin debug,
|
|||
{
|
||||
Size alignedFenceSize, alignedSize;
|
||||
|
||||
ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free");
|
||||
ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free"); /* <design/check/#.common> */
|
||||
|
||||
alignedFenceSize = SizeAlignUp(debug->fenceSize, PoolAlignment(pool));
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
|
|
@ -738,7 +738,7 @@ void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit)
|
|||
AVERT(PoolDebugMixin, debug);
|
||||
if (debug->freeSize != 0)
|
||||
ASSERT(freeCheck(debug, pool, base, limit),
|
||||
"free space corrupted on release");
|
||||
"free space corrupted on release"); /* <design/check/#.common> */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -784,7 +784,7 @@ void PoolClassMixInDebug(PoolClass klass)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
103
mps/code/eventpy.c
Normal file
103
mps/code/eventpy.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* eventpy.c: GENERATE PYTHON INTERFACE TO EVENTS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This command-line program emits Python data structures that can be
|
||||
* used to parse an event stream in text format (as output by the
|
||||
* mpseventcnv program).
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* printf, puts */
|
||||
|
||||
#include "event.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
|
||||
puts("from collections import namedtuple");
|
||||
|
||||
printf("__version__ = %d, %d, %d\n", EVENT_VERSION_MAJOR,
|
||||
EVENT_VERSION_MEDIAN, EVENT_VERSION_MINOR);
|
||||
|
||||
puts("EventKind = namedtuple('EventKind', 'name code doc')");
|
||||
puts("class kind:");
|
||||
#define ENUM(_, NAME, DOC) \
|
||||
printf(" " #NAME " = EventKind('" #NAME "', %d, \"%s\")\n", \
|
||||
EventKind ## NAME, DOC);
|
||||
EventKindENUM(ENUM, _);
|
||||
#undef ENUM
|
||||
|
||||
puts("kinds = {");
|
||||
#define ENUM(_, NAME, _1) \
|
||||
printf(" %d: kind." #NAME ",\n", EventKind ## NAME);
|
||||
EventKindENUM(ENUM, _);
|
||||
#undef ENUM
|
||||
puts("}");
|
||||
|
||||
puts("EventParam = namedtuple('EventParam', 'sort, name')");
|
||||
puts("Event = namedtuple('Event', 'name code always kind params')");
|
||||
puts("class event:");
|
||||
#define EVENT_PARAM(X, INDEX, SORT, NAME) \
|
||||
puts(" EventParam('" #SORT "', '" #NAME "'),");
|
||||
#define EVENT_DEFINE(X, NAME, CODE, ALWAYS, KIND) \
|
||||
printf(" " #NAME " = Event('" #NAME "', %d, %s, kind." #KIND ", [\n", \
|
||||
CODE, ALWAYS ? "True" : "False"); \
|
||||
EVENT_ ## NAME ## _PARAMS(EVENT_PARAM, X); \
|
||||
puts(" ]);");
|
||||
EVENT_LIST(EVENT_DEFINE, 0);
|
||||
#undef EVENT
|
||||
|
||||
puts("events = {");
|
||||
#define EVENT_ITEM(X, NAME, CODE, ALWAYS, KIND) \
|
||||
printf(" %d: event." #NAME ",\n", CODE);
|
||||
EVENT_LIST(EVENT_ITEM, 0);
|
||||
#undef EVENT
|
||||
puts("}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* format.c: OBJECT FORMATS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
|
|
@ -168,7 +168,7 @@ Res FormatCreate(Format *formatReturn, Arena arena, ArgList args)
|
|||
void FormatDestroy(Format format)
|
||||
{
|
||||
AVERT(Format, format);
|
||||
AVER(format->poolCount == 0);
|
||||
AVER(format->poolCount == 0); /* <design/check/#.common> */
|
||||
|
||||
RingRemove(&format->arenaRing);
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* fotest.c: FAIL-OVER TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* This tests fail-over behaviour in low memory situations. The MVFF
|
||||
|
|
@ -10,9 +10,8 @@
|
|||
* request due to running out of memory, they fall back to a Freelist
|
||||
* (which has zero memory overhead, at some cost in performance).
|
||||
*
|
||||
* This is a white box test: it patches the class of the CBS's
|
||||
* internal block pool (MFS) with a pointer to a dummy class whose
|
||||
* alloc() method always returns ResMEMORY.
|
||||
* This is a white box test: it monkey-patches the MFS pool's alloc
|
||||
* method with a method that always returns a memory error code.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -36,40 +35,6 @@
|
|||
#define testLOOPS 10
|
||||
|
||||
|
||||
/* Accessors for the CBS used to implement a pool. */
|
||||
|
||||
extern Land _mps_mvff_cbs(Pool);
|
||||
extern Land _mps_mvt_cbs(Pool);
|
||||
|
||||
|
||||
/* "OOM" pool class -- dummy alloc/free pool class whose alloc()
|
||||
* method always fails and whose free method does nothing. */
|
||||
|
||||
static Res oomAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
UNUSED(pReturn);
|
||||
UNUSED(pool);
|
||||
UNUSED(size);
|
||||
switch (rnd() % 3) {
|
||||
case 0:
|
||||
return ResRESOURCE;
|
||||
case 1:
|
||||
return ResMEMORY;
|
||||
default:
|
||||
return ResCOMMIT_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_CLASS(Pool, OOMPool, AbstractPool);
|
||||
DEFINE_CLASS(Pool, OOMPool, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, OOMPool, AbstractPool);
|
||||
klass->alloc = oomAlloc;
|
||||
klass->free = PoolTrivFree;
|
||||
klass->size = sizeof(PoolStruct);
|
||||
}
|
||||
|
||||
|
||||
/* make -- allocate one object */
|
||||
|
||||
static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
||||
|
|
@ -86,19 +51,44 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
|||
}
|
||||
|
||||
|
||||
/* set_oom -- set blockPool of CBS to OOM or MFS according to argument. */
|
||||
/* The original alloc method on the MFS pool. */
|
||||
static PoolAllocMethod mfs_alloc;
|
||||
|
||||
static void set_oom(Land land, int oom)
|
||||
|
||||
/* oomAlloc -- allocation function that always fails
|
||||
*
|
||||
* Returns a randomly chosen memory error code.
|
||||
*/
|
||||
|
||||
static Res oomAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
CBS cbs = MustBeA(CBS, land);
|
||||
SetClassOfPoly(cbs->blockPool, oom ? CLASS(OOMPool) : PoolClassMFS());
|
||||
MFS mfs = MustBeA(MFSPool, pool);
|
||||
UNUSED(pReturn);
|
||||
UNUSED(size);
|
||||
if (mfs->extendSelf) {
|
||||
/* This is the MFS block pool belonging to the CBS belonging to
|
||||
* the MVFF or MVT pool under test, so simulate a failure to
|
||||
* enforce the fail-over behaviour. */
|
||||
switch (rnd() % 3) {
|
||||
case 0:
|
||||
return ResRESOURCE;
|
||||
case 1:
|
||||
return ResMEMORY;
|
||||
default:
|
||||
return ResCOMMIT_LIMIT;
|
||||
}
|
||||
} else {
|
||||
/* This is the MFS block pool belonging to the arena's free land,
|
||||
* so succeed here (see job004041). */
|
||||
return mfs_alloc(pReturn, pool, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* stress -- create an allocation point and allocate in it */
|
||||
|
||||
static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t),
|
||||
mps_align_t alignment, mps_pool_t pool, Land cbs)
|
||||
mps_align_t alignment, mps_pool_t pool)
|
||||
{
|
||||
mps_res_t res = MPS_RES_OK;
|
||||
mps_ap_t ap;
|
||||
|
|
@ -110,11 +100,12 @@ static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t),
|
|||
|
||||
/* allocate a load of objects */
|
||||
for (i=0; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i, alignment);
|
||||
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
res = make(&obj, ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
ps[i] = obj;
|
||||
if (ss[i] >= sizeof(ps[i]))
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
}
|
||||
|
|
@ -140,15 +131,17 @@ static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t),
|
|||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i, alignment);
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
res = make(&obj, ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
ps[i] = obj;
|
||||
}
|
||||
|
||||
set_oom(cbs, rnd() % 2);
|
||||
CLASS_STATIC(MFSPool).alloc = rnd() % 2 ? mfs_alloc : oomAlloc;
|
||||
}
|
||||
set_oom(cbs, 0);
|
||||
CLASS_STATIC(MFSPool).alloc = mfs_alloc;
|
||||
|
||||
allocFail:
|
||||
mps_ap_destroy(ap);
|
||||
|
|
@ -177,6 +170,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
mfs_alloc = CLASS_STATIC(MFSPool).alloc;
|
||||
alignment = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, (64 + rnd() % 64) * 1024);
|
||||
|
|
@ -187,10 +181,7 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, rnd() % 2);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_mvff(), args), "create MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
{
|
||||
die(stress(randomSizeAligned, alignment, pool, _mps_mvff_cbs(pool)),
|
||||
"stress MVFF");
|
||||
}
|
||||
die(stress(randomSizeAligned, alignment, pool), "stress MVFF");
|
||||
mps_pool_destroy(pool);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
@ -206,10 +197,7 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVT_FRAG_LIMIT, (rnd() % 101) / 100.0);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_mvt(), args), "create MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
{
|
||||
die(stress(randomSizeAligned, alignment, pool, _mps_mvt_cbs(pool)),
|
||||
"stress MVT");
|
||||
}
|
||||
die(stress(randomSizeAligned, alignment, pool), "stress MVT");
|
||||
mps_pool_destroy(pool);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
@ -220,7 +208,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* global.c: ARENA-GLOBAL INTERFACES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: See <design/arena/>. design.mps.thread-safety is relevant
|
||||
|
|
@ -188,7 +188,8 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKL(RingCheck(&arenaRing));
|
||||
|
||||
CHECKL(BoolCheck(arena->emergency));
|
||||
/* There can only be an emergency when a trace is busy. */
|
||||
/* .emergency.invariant: There can only be an emergency when a trace
|
||||
* is busy. */
|
||||
CHECKL(!arena->emergency || arena->busyTraces != TraceSetEMPTY);
|
||||
|
||||
if (arenaGlobals->defaultChain != NULL)
|
||||
|
|
@ -463,12 +464,12 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
* and so RingCheck dereferences a pointer into that unmapped memory
|
||||
* and we get a crash instead of an assertion. See job000652.
|
||||
*/
|
||||
AVER(RingIsSingle(&arena->formatRing));
|
||||
AVER(RingIsSingle(&arena->chainRing));
|
||||
AVER(RingIsSingle(&arena->formatRing)); /* <design/check/#.common> */
|
||||
AVER(RingIsSingle(&arena->chainRing)); /* <design/check/#.common> */
|
||||
AVER(RingIsSingle(&arena->messageRing));
|
||||
AVER(RingIsSingle(&arena->threadRing));
|
||||
AVER(RingIsSingle(&arena->threadRing)); /* <design/check/#.common> */
|
||||
AVER(RingIsSingle(&arena->deadRing));
|
||||
AVER(RingIsSingle(&arenaGlobals->rootRing));
|
||||
AVER(RingIsSingle(&arenaGlobals->rootRing)); /* <design/check/#.common> */
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
AVER(RingIsSingle(&arena->greyRing[rank]));
|
||||
|
||||
|
|
@ -478,7 +479,7 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
* 2. arena->controlPoolStruct.blockPoolStruct
|
||||
* 3. arena->controlPoolStruct.spanPoolStruct
|
||||
*/
|
||||
AVER(RingLength(&arenaGlobals->poolRing) == 4);
|
||||
AVER(RingLength(&arenaGlobals->poolRing) == 4); /* <design/check/#.common> */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1066,7 +1067,7 @@ Bool ArenaEmergency(Arena arena)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* land.c: LAND (COLLECTION OF ADDRESS RANGES) IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2014-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2014-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: <design/land/>
|
||||
*/
|
||||
|
|
@ -190,12 +190,15 @@ void LandFinish(Land land)
|
|||
/* LandSize -- return the total size of ranges in land
|
||||
*
|
||||
* See <design/land/#function.size>
|
||||
*
|
||||
* .size.critical: In manual-allocation-bound programs using MVFF this
|
||||
* is on the critical path.
|
||||
*/
|
||||
|
||||
Size LandSize(Land land)
|
||||
{
|
||||
/* .enter-leave.simple */
|
||||
AVERC(Land, land);
|
||||
AVERC_CRITICAL(Land, land);
|
||||
|
||||
return Method(Land, land, sizeMethod)(land);
|
||||
}
|
||||
|
|
@ -204,17 +207,20 @@ Size LandSize(Land land)
|
|||
/* LandInsert -- insert range of addresses into land
|
||||
*
|
||||
* See <design/land/#function.insert>
|
||||
*
|
||||
* .insert.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
Res LandInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERC(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, land->alignment));
|
||||
AVER(!RangeIsEmpty(range));
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVERT_CRITICAL(Range, range);
|
||||
AVER_CRITICAL(RangeIsAligned(range, land->alignment));
|
||||
AVER_CRITICAL(!RangeIsEmpty(range));
|
||||
landEnter(land);
|
||||
|
||||
res = Method(Land, land, insert)(rangeReturn, land, range);
|
||||
|
|
@ -249,13 +255,16 @@ Res LandDelete(Range rangeReturn, Land land, Range range)
|
|||
/* LandIterate -- iterate over isolated ranges of addresses in land
|
||||
*
|
||||
* See <design/land/#function.iterate>
|
||||
*
|
||||
* .iterate.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
Bool LandIterate(Land land, LandVisitor visitor, void *closure)
|
||||
{
|
||||
Bool b;
|
||||
AVERC(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVER_CRITICAL(FUNCHECK(visitor));
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, iterate)(land, visitor, closure);
|
||||
|
|
@ -274,8 +283,8 @@ Bool LandIterate(Land land, LandVisitor visitor, void *closure)
|
|||
Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure)
|
||||
{
|
||||
Bool b;
|
||||
AVERC(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVER_CRITICAL(FUNCHECK(visitor));
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, iterateAndDelete)(land, visitor, closure);
|
||||
|
|
@ -426,12 +435,15 @@ static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
|||
/* LandFlush -- move ranges from src to dest
|
||||
*
|
||||
* See <design/land/#function.flush>
|
||||
*
|
||||
* .flush.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
Bool LandFlush(Land dest, Land src)
|
||||
{
|
||||
AVERC(Land, dest);
|
||||
AVERC(Land, src);
|
||||
AVERC_CRITICAL(Land, dest);
|
||||
AVERC_CRITICAL(Land, src);
|
||||
|
||||
return LandIterateAndDelete(src, landFlushVisitor, dest);
|
||||
}
|
||||
|
|
@ -594,7 +606,7 @@ DEFINE_CLASS(Land, Land, klass)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2014-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2014-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockix.c: RECURSIVE LOCKS FOR POSIX SYSTEMS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 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.
|
||||
|
|
@ -122,7 +122,7 @@ void (LockClaim)(Lock lock)
|
|||
|
||||
res = pthread_mutex_lock(&lock->mut);
|
||||
/* pthread_mutex_lock will error if we own the lock already. */
|
||||
AVER(res == 0);
|
||||
AVER(res == 0); /* <design/check/#.common> */
|
||||
|
||||
/* This should be the first claim. Now we own the mutex */
|
||||
/* it is ok to check this. */
|
||||
|
|
@ -245,7 +245,7 @@ void (LockReleaseGlobal)(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockli.c: RECURSIVE LOCKS FOR POSIX SYSTEMS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .linux: This implementation currently just supports LinuxThreads
|
||||
* (platform MPS_OS_LI), Single Unix i/f.
|
||||
|
|
@ -136,7 +136,7 @@ void (LockClaim)(Lock lock)
|
|||
|
||||
res = pthread_mutex_lock(&lock->mut);
|
||||
/* pthread_mutex_lock will error if we own the lock already. */
|
||||
AVER(res == 0);
|
||||
AVER(res == 0); /* <design/check/#.common> */
|
||||
|
||||
/* This should be the first claim. Now we own the mutex */
|
||||
/* it is ok to check this. */
|
||||
|
|
@ -259,7 +259,7 @@ void (LockReleaseGlobal)(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* lockw3.c: RECURSIVE LOCKS IN WIN32
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: These are implemented using critical sections.
|
||||
* See the section titled "Synchronization functions" in the Groups
|
||||
|
|
@ -75,7 +75,7 @@ void (LockClaim)(Lock lock)
|
|||
EnterCriticalSection(&lock->cs);
|
||||
/* This should be the first claim. Now we are inside the
|
||||
* critical section it is ok to check this. */
|
||||
AVER(lock->claims == 0);
|
||||
AVER(lock->claims == 0); /* <design/check/#.common> */
|
||||
lock->claims = 1;
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ void (LockReleaseGlobal)(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void ChainDestroy(Chain chain)
|
|||
size_t i;
|
||||
|
||||
AVERT(Chain, chain);
|
||||
AVER(chain->activeTraces == TraceSetEMPTY);
|
||||
AVER(chain->activeTraces == TraceSetEMPTY); /* <design/check/#.common> */
|
||||
|
||||
arena = chain->arena;
|
||||
genCount = chain->genCount;
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ extern void PoolNoBufferEmpty(Pool pool, Buffer buffer,
|
|||
Addr init, Addr limit);
|
||||
extern void PoolTrivBufferEmpty(Pool pool, Buffer buffer,
|
||||
Addr init, Addr limit);
|
||||
extern Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream, Count depth);
|
||||
extern Res PoolAbsDescribe(Pool pool, mps_lib_FILE *stream, Count depth);
|
||||
extern Res PoolNoTraceBegin(Pool pool, Trace trace);
|
||||
extern Res PoolTrivTraceBegin(Pool pool, Trace trace);
|
||||
extern Res PoolNoAccess(Pool pool, Seg seg, Addr addr,
|
||||
|
|
@ -669,6 +669,7 @@ extern void SegSetRankSet(Seg seg, RankSet rankSet);
|
|||
extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary);
|
||||
extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi);
|
||||
extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at);
|
||||
extern Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth);
|
||||
extern Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth);
|
||||
extern void SegSetSummary(Seg seg, RefSet summary);
|
||||
extern Bool SegHasBuffer(Seg seg);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpmss.c: MPM STRESS TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
|
@ -57,11 +57,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
|||
|
||||
/* allocate a load of objects */
|
||||
for (i=0; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i);
|
||||
|
||||
res = mps_alloc((mps_addr_t *)&ps[i], pool, ss[i]);
|
||||
res = mps_alloc(&obj, pool, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
ps[i] = obj;
|
||||
allocated += alignUp(ss[i], align) + debugOverhead;
|
||||
if (ss[i] >= sizeof(ps[i]))
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
|
|
@ -93,10 +94,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
|||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i);
|
||||
res = mps_alloc((mps_addr_t *)&ps[i], pool, ss[i]);
|
||||
res = mps_alloc(&obj, pool, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
ps[i] = obj;
|
||||
allocated += alignUp(ss[i], align) + debugOverhead;
|
||||
}
|
||||
check_allocated_size(pool, allocated);
|
||||
|
|
@ -241,7 +244,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -696,7 +696,9 @@ typedef struct SortStruct {
|
|||
|
||||
typedef struct ShieldStruct {
|
||||
Sig sig; /* design.mps.sig */
|
||||
Bool inside; /* design.mps.shield.def.inside */
|
||||
BOOLFIELD(inside); /* design.mps.shield.def.inside */
|
||||
BOOLFIELD(suspended); /* mutator suspended? */
|
||||
BOOLFIELD(queuePending); /* queue insertion pending? */
|
||||
Seg *queue; /* queue of unsynced segs */
|
||||
Count length; /* number of elements in shield queue */
|
||||
Index next; /* next free element in shield queue */
|
||||
|
|
@ -704,7 +706,6 @@ typedef struct ShieldStruct {
|
|||
Count depth; /* sum of depths of all segs */
|
||||
Count unsynced; /* number of unsynced segments */
|
||||
Count holds; /* number of holds */
|
||||
Bool suspended; /* mutator suspended? */
|
||||
SortStruct sortStruct; /* workspace for queue sort */
|
||||
} ShieldStruct;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 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,
|
||||
|
|
@ -745,16 +745,16 @@ mps_res_t mps_alloc(mps_addr_t *p_o, mps_pool_t pool, size_t size)
|
|||
Addr p;
|
||||
Res res;
|
||||
|
||||
AVER(TESTT(Pool, pool));
|
||||
AVER_CRITICAL(TESTT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
ArenaPoll(ArenaGlobals(arena)); /* .poll */
|
||||
|
||||
AVER(p_o != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER_CRITICAL(p_o != NULL);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVER_CRITICAL(size > 0);
|
||||
/* Note: class may allow unaligned size, see */
|
||||
/* <design/class-interface/#alloc.size.align>. */
|
||||
/* Rest ignored, see .varargs. */
|
||||
|
|
@ -787,13 +787,13 @@ void mps_free(mps_pool_t pool, mps_addr_t p, size_t size)
|
|||
{
|
||||
Arena arena;
|
||||
|
||||
AVER(TESTT(Pool, pool));
|
||||
AVER_CRITICAL(TESTT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVER_CRITICAL(size > 0);
|
||||
/* Note: class may allow unaligned size, see */
|
||||
/* <design/class-interface/#alloc.size.align>. */
|
||||
|
||||
|
|
@ -1060,7 +1060,7 @@ mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size)
|
|||
AVER(p_o != NULL);
|
||||
AVERT(Buffer, buf);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, BufferPool(buf)->alignment));
|
||||
AVER(SizeIsAligned(size, BufferPool(buf)->alignment)); /* <design/check/#.common> */
|
||||
|
||||
res = BufferFill(&p, buf, size);
|
||||
|
||||
|
|
@ -2141,7 +2141,7 @@ void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i,
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpsicv.c: MPSI COVERAGE TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
|
@ -338,7 +338,8 @@ static void *test(void *arg, size_t s)
|
|||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_root_t exactRoot, ambigRoot, singleRoot, fmtRoot;
|
||||
mps_root_t exactAreaRoot, exactTableRoot, ambigAreaRoot, ambigTableRoot,
|
||||
singleRoot, fmtRoot;
|
||||
unsigned long i;
|
||||
/* Leave arena clamped until we have allocated this many objects.
|
||||
is 0 when arena has not been clamped. */
|
||||
|
|
@ -386,14 +387,29 @@ static void *test(void *arg, size_t s)
|
|||
ambigRoots[j] = rnd_addr();
|
||||
}
|
||||
|
||||
die(mps_root_create_table_masked(&exactRoot, arena,
|
||||
die(mps_root_create_area_tagged(&exactAreaRoot, arena,
|
||||
mps_rank_exact(), (mps_rm_t)0,
|
||||
&exactRoots[0],
|
||||
&exactRoots[exactRootsCOUNT / 2],
|
||||
mps_scan_area_tagged,
|
||||
MPS_WORD_CONST(1), 0),
|
||||
"root_create_area_tagged(exact)");
|
||||
die(mps_root_create_table_masked(&exactTableRoot, arena,
|
||||
mps_rank_exact(), (mps_rm_t)0,
|
||||
&exactRoots[0], exactRootsCOUNT,
|
||||
&exactRoots[exactRootsCOUNT / 2],
|
||||
(exactRootsCOUNT + 1) / 2,
|
||||
MPS_WORD_CONST(1)),
|
||||
"root_create_table(exact)");
|
||||
die(mps_root_create_table(&ambigRoot, arena,
|
||||
"root_create_table_masked(exact)");
|
||||
die(mps_root_create_area(&ambigAreaRoot, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
&ambigRoots[0],
|
||||
&ambigRoots[ambigRootsCOUNT / 2],
|
||||
mps_scan_area, NULL),
|
||||
"root_create_area(ambig)");
|
||||
die(mps_root_create_table(&ambigTableRoot, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
&ambigRoots[ambigRootsCOUNT / 2],
|
||||
(ambigRootsCOUNT + 1) / 2),
|
||||
"root_create_table(ambig)");
|
||||
|
||||
obj = objNULL;
|
||||
|
|
@ -519,8 +535,10 @@ static void *test(void *arg, size_t s)
|
|||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(fmtRoot);
|
||||
mps_root_destroy(singleRoot);
|
||||
mps_root_destroy(exactRoot);
|
||||
mps_root_destroy(ambigRoot);
|
||||
mps_root_destroy(exactAreaRoot);
|
||||
mps_root_destroy(exactTableRoot);
|
||||
mps_root_destroy(ambigAreaRoot);
|
||||
mps_root_destroy(ambigTableRoot);
|
||||
mps_pool_destroy(amcpool);
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(format);
|
||||
|
|
@ -551,15 +569,25 @@ int main(int argc, char *argv[])
|
|||
} MPS_ARGS_END(args);
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
|
||||
if (rnd() % 2) {
|
||||
switch (rnd() % 3) {
|
||||
default:
|
||||
case 0:
|
||||
die(mps_root_create_reg(®_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread, &mps_stack_scan_ambig,
|
||||
marker, (size_t)0),
|
||||
"root_create_reg");
|
||||
} else {
|
||||
break;
|
||||
case 1:
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create_thread");
|
||||
break;
|
||||
case 2:
|
||||
die(mps_root_create_thread_scanned(®_root, arena, mps_rank_ambig(),
|
||||
(mps_rm_t)0, thread, mps_scan_area,
|
||||
NULL, marker),
|
||||
"root_create_thread");
|
||||
break;
|
||||
}
|
||||
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
|
|
@ -574,7 +602,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mv2test.c: POOLMVT STRESS TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
|
@ -102,13 +102,15 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
|
||||
/* allocate a load of objects */
|
||||
for(i=0; i<TEST_SET_SIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i);
|
||||
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i], align);
|
||||
if(res != MPS_RES_OK)
|
||||
res = make(&obj, ap, ss[i], align);
|
||||
if (res != MPS_RES_OK) {
|
||||
ss[i] = 0;
|
||||
else
|
||||
} else {
|
||||
ps[i]= obj;
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
if (i && i%4==0)
|
||||
|
|
@ -146,10 +148,12 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
}
|
||||
/* allocate some new objects */
|
||||
for(i=x; i<TEST_SET_SIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
size_t s = (*size)(i);
|
||||
res = make((mps_addr_t *)&ps[i], ap, s, align);
|
||||
res = make(&obj, ap, s, align);
|
||||
if(res != MPS_RES_OK)
|
||||
break;
|
||||
ps[i] = obj;
|
||||
ss[i] = s;
|
||||
|
||||
if (verbose) {
|
||||
|
|
@ -218,7 +222,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -227,22 +227,24 @@ BufferClass PoolDefaultBufferClass(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* PoolAlloc -- allocate a block of memory from a pool */
|
||||
/* PoolAlloc -- allocate a block of memory from a pool
|
||||
*
|
||||
* .alloc.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
|
||||
Res PoolAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVER_CRITICAL(pReturn != NULL);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVER_CRITICAL(size > 0);
|
||||
|
||||
res = Method(Pool, pool, alloc)(pReturn, pool, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
/* Make sure that the allocated address was in the pool's memory. */
|
||||
/* .hasaddr.critical: The PoolHasAddr check is expensive, and in */
|
||||
/* allocation-bound programs this is on the critical path. */
|
||||
AVER_CRITICAL(PoolHasAddr(pool, *pReturn));
|
||||
/* All allocations should be aligned to the pool's alignment */
|
||||
AVER_CRITICAL(AddrIsAligned(*pReturn, pool->alignment));
|
||||
|
|
@ -257,16 +259,20 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size)
|
|||
}
|
||||
|
||||
|
||||
/* PoolFree -- deallocate a block of memory allocated from the pool */
|
||||
/* PoolFree -- deallocate a block of memory allocated from the pool
|
||||
*
|
||||
* .free.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
|
||||
void PoolFree(Pool pool, Addr old, Size size)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(old != NULL);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVER_CRITICAL(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)));
|
||||
AVER_CRITICAL(size > 0);
|
||||
AVER_CRITICAL(AddrIsAligned(old, pool->alignment));
|
||||
AVER_CRITICAL(PoolHasRange(pool, old, AddrAdd(old, size)));
|
||||
|
||||
Method(Pool, pool, free)(pool, old, size);
|
||||
|
||||
|
|
@ -490,51 +496,7 @@ Size PoolFreeSize(Pool pool)
|
|||
|
||||
Res PoolDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
Ring node, nextNode;
|
||||
PoolClass klass;
|
||||
|
||||
if (!TESTC(AbstractPool, pool))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
klass = ClassOfPoly(Pool, pool);
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"Pool $P ($U) {\n", (WriteFP)pool, (WriteFU)pool->serial,
|
||||
" class $P (\"$S\")\n",
|
||||
(WriteFP)klass, (WriteFS)ClassName(klass),
|
||||
" arena $P ($U)\n",
|
||||
(WriteFP)pool->arena, (WriteFU)pool->arena->serial,
|
||||
" alignment $W\n", (WriteFW)pool->alignment,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
if (NULL != pool->format) {
|
||||
res = FormatDescribe(pool->format, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = Method(Pool, pool, describe)(pool, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
RING_FOR(node, &pool->bufferRing, nextNode) {
|
||||
Buffer buffer = RING_ELT(Buffer, poolRing, node);
|
||||
res = BufferDescribe(buffer, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"} Pool $P ($U)\n", (WriteFP)pool, (WriteFU)pool->serial,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
return ResOK;
|
||||
return Method(Pool, pool, describe)(pool, stream, depth);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -640,8 +602,8 @@ Bool PoolHasRange(Pool pool, Addr base, Addr limit)
|
|||
Arena arena;
|
||||
Bool managed;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(base < limit);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVER_CRITICAL(base < limit);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
managed = PoolOfRange(&rangePool, arena, base, limit);
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ DEFINE_CLASS(Pool, AbstractPool, klass)
|
|||
klass->walk = PoolNoWalk;
|
||||
klass->freewalk = PoolTrivFreeWalk;
|
||||
klass->bufferClass = PoolNoBufferClass;
|
||||
klass->describe = PoolTrivDescribe;
|
||||
klass->describe = PoolAbsDescribe;
|
||||
klass->debugMixin = PoolNoDebugMixin;
|
||||
klass->totalSize = PoolNoSize;
|
||||
klass->freeSize = PoolNoSize;
|
||||
|
|
@ -353,13 +353,43 @@ void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
Res PoolAbsDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(stream != NULL);
|
||||
return WriteF(stream, depth,
|
||||
"No class-specific description available.\n",
|
||||
NULL);
|
||||
Res res;
|
||||
Ring node, nextNode;
|
||||
|
||||
if (!TESTC(AbstractPool, pool))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
res = InstDescribe(CouldBeA(Inst, pool), stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"serial $U\n", (WriteFU)pool->serial,
|
||||
"arena $P ($U)\n",
|
||||
(WriteFP)pool->arena, (WriteFU)pool->arena->serial,
|
||||
"alignment $W\n", (WriteFW)pool->alignment,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
if (pool->format != NULL) {
|
||||
res = FormatDescribe(pool->format, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
RING_FOR(node, &pool->bufferRing, nextNode) {
|
||||
Buffer buffer = RING_ELT(Buffer, poolRing, node);
|
||||
res = BufferDescribe(buffer, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -235,8 +235,8 @@ static void AMCSegSketch(Seg seg, char *pbSketch, size_t cbSketch)
|
|||
*/
|
||||
static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
amcSeg amcseg = CouldBeA(amcSeg, seg);
|
||||
Res res;
|
||||
Pool pool;
|
||||
Addr i, p, base, limit, init;
|
||||
Align step;
|
||||
|
|
@ -244,14 +244,14 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
char abzSketch[5];
|
||||
Buffer buffer;
|
||||
|
||||
if(!TESTC(amcSeg, amcseg))
|
||||
if (!TESTC(amcSeg, amcseg))
|
||||
return ResPARAM;
|
||||
if(stream == NULL)
|
||||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
/* Describe the superclass fields first via next-method call */
|
||||
res = NextMethod(Seg, amcSeg, describe)(seg, stream, depth);
|
||||
if(res != ResOK)
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
pool = SegPool(seg);
|
||||
|
|
@ -262,16 +262,9 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
p = AddrAdd(base, pool->format->headerSize);
|
||||
limit = SegLimit(seg);
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"AMC seg $P [$A,$A){\n",
|
||||
(WriteFP)seg, (WriteFA)base, (WriteFA)limit,
|
||||
NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
if(amcSegHasNailboard(seg)) {
|
||||
if (amcSegHasNailboard(seg)) {
|
||||
res = WriteF(stream, depth + 2, "Boarded\n", NULL);
|
||||
} else if(SegNailed(seg) == TraceSetEMPTY) {
|
||||
} else if (SegNailed(seg) == TraceSetEMPTY) {
|
||||
res = WriteF(stream, depth + 2, "Mobile\n", NULL);
|
||||
} else {
|
||||
res = WriteF(stream, depth + 2, "Stuck\n", NULL);
|
||||
|
|
@ -281,7 +274,7 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"Map: *===:object @+++:nails bbbb:buffer\n", NULL);
|
||||
if(res != ResOK)
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
if (SegBuffer(&buffer, seg))
|
||||
|
|
@ -289,24 +282,24 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
else
|
||||
init = limit;
|
||||
|
||||
for(i = base; i < limit; i = AddrAdd(i, row)) {
|
||||
for (i = base; i < limit; i = AddrAdd(i, row)) {
|
||||
Addr j;
|
||||
char c;
|
||||
|
||||
res = WriteF(stream, depth + 2, "$A ", (WriteFA)i, NULL);
|
||||
if(res != ResOK)
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
/* @@@@ This misses a header-sized pad at the end. */
|
||||
for(j = i; j < AddrAdd(i, row); j = AddrAdd(j, step)) {
|
||||
if(j >= limit)
|
||||
for (j = i; j < AddrAdd(i, row); j = AddrAdd(j, step)) {
|
||||
if (j >= limit)
|
||||
c = ' '; /* if seg is not a whole number of print rows */
|
||||
else if(j >= init)
|
||||
else if (j >= init)
|
||||
c = 'b';
|
||||
else {
|
||||
Bool nailed = amcSegHasNailboard(seg)
|
||||
&& NailboardGet(amcSegNailboard(seg), j);
|
||||
if(j == p) {
|
||||
if (j == p) {
|
||||
c = (nailed ? '@' : '*');
|
||||
p = (pool->format->skip)(p);
|
||||
} else {
|
||||
|
|
@ -314,12 +307,12 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
}
|
||||
}
|
||||
res = WriteF(stream, 0, "$C", (WriteFC)c, NULL);
|
||||
if(res != ResOK)
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = WriteF(stream, 0, "\n", NULL);
|
||||
if(res != ResOK)
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -328,10 +321,6 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth, "} AMC Seg $P\n", (WriteFP)seg, NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
@ -1971,6 +1960,7 @@ static Size AMCFreeSize(Pool pool)
|
|||
*
|
||||
* See <design/poolamc/#describe>.
|
||||
*/
|
||||
|
||||
static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -1978,17 +1968,13 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
Ring node, nextNode;
|
||||
const char *rampmode;
|
||||
|
||||
if(!TESTC(AMCZPool, amc))
|
||||
if (!TESTC(AMCZPool, amc))
|
||||
return ResPARAM;
|
||||
if(stream == NULL)
|
||||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
(amc->rankSet == RankSetEMPTY) ? "AMCZ" : "AMC",
|
||||
" $P {\n", (WriteFP)amc, " pool $P ($U)\n",
|
||||
(WriteFP)pool, (WriteFU)pool->serial,
|
||||
NULL);
|
||||
if(res != ResOK)
|
||||
res = NextMethod(Pool, AMCZPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
switch(amc->rampMode) {
|
||||
|
|
@ -2015,7 +2001,7 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
return res;
|
||||
}
|
||||
|
||||
if(0) {
|
||||
if (0) {
|
||||
/* SegDescribes */
|
||||
RING_FOR(node, &pool->segRing, nextNode) {
|
||||
Seg seg = RING_ELT(Seg, poolRing, node);
|
||||
|
|
@ -2025,10 +2011,6 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
}
|
||||
}
|
||||
|
||||
res = WriteF(stream, depth, "} AMC $P\n", (WriteFP)amc, NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -524,19 +524,16 @@ failCreateTablesLo:
|
|||
|
||||
static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
AMSSeg amsseg = CouldBeA(AMSSeg, seg);
|
||||
Res res;
|
||||
AMSSeg amsseg;
|
||||
Buffer buffer;
|
||||
Bool hasBuffer;
|
||||
Index i;
|
||||
|
||||
if (!TESTT(Seg, seg))
|
||||
return ResFAIL;
|
||||
if (!TESTC(AMSSeg, amsseg))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
if (!TESTT(AMSSeg, amsseg))
|
||||
return ResFAIL;
|
||||
return ResPARAM;
|
||||
|
||||
/* Describe the superclass fields first via next-method call */
|
||||
res = NextMethod(Seg, AMSSeg, describe)(seg, stream, depth);
|
||||
|
|
@ -545,13 +542,13 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
hasBuffer = SegBuffer(&buffer, seg);
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
" AMS $P\n", (WriteFP)amsseg->ams,
|
||||
" grains $W\n", (WriteFW)amsseg->grains,
|
||||
" freeGrains $W\n", (WriteFW)amsseg->freeGrains,
|
||||
" buffferedGrains $W\n", (WriteFW)amsseg->bufferedGrains,
|
||||
" newGrains $W\n", (WriteFW)amsseg->newGrains,
|
||||
" oldGrains $W\n", (WriteFW)amsseg->oldGrains,
|
||||
res = WriteF(stream, depth + 2,
|
||||
"AMS $P\n", (WriteFP)amsseg->ams,
|
||||
"grains $W\n", (WriteFW)amsseg->grains,
|
||||
"freeGrains $W\n", (WriteFW)amsseg->freeGrains,
|
||||
"buffferedGrains $W\n", (WriteFW)amsseg->bufferedGrains,
|
||||
"newGrains $W\n", (WriteFW)amsseg->newGrains,
|
||||
"oldGrains $W\n", (WriteFW)amsseg->oldGrains,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1493,7 +1490,7 @@ static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
case RankFINAL:
|
||||
case RankWEAK:
|
||||
AVER_CRITICAL(AddrIsAligned(base, PoolAlignment(pool)));
|
||||
AVER_CRITICAL(AMS_ALLOCED(seg, i));
|
||||
AVER_CRITICAL(AMS_ALLOCED(seg, i)); /* <design/check/#.common> */
|
||||
if (AMS_IS_WHITE(seg, i)) {
|
||||
ss->wasMarked = FALSE;
|
||||
if (ss->rank == RankWEAK) { /* then splat the reference */
|
||||
|
|
@ -1698,25 +1695,24 @@ static Size AMSFreeSize(Pool pool)
|
|||
*
|
||||
* Iterates over the segments, describing all of them.
|
||||
*/
|
||||
|
||||
static Res AMSDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
AMS ams;
|
||||
AMS ams = CouldBeA(AMSPool, pool);
|
||||
Ring node, nextNode;
|
||||
Res res;
|
||||
|
||||
if (!TESTT(Pool, pool))
|
||||
return ResFAIL;
|
||||
ams = PoolAMS(pool);
|
||||
if (!TESTT(AMS, ams))
|
||||
return ResFAIL;
|
||||
if (!TESTC(AMSPool, ams))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
return ResPARAM;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"AMS $P {\n", (WriteFP)ams,
|
||||
" pool $P ($U)\n",
|
||||
(WriteFP)pool, (WriteFU)pool->serial,
|
||||
" grain shift $U\n", (WriteFU)ams->grainShift,
|
||||
res = NextMethod(Pool, AMSPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"grain shift $U\n", (WriteFU)ams->grainShift,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1735,10 +1731,6 @@ static Res AMSDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
return res;
|
||||
}
|
||||
|
||||
res = WriteF(stream, depth, "} AMS $P\n",(WriteFP)ams, NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmfs.c: MANUAL FIXED SMALL UNIT POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is the implementation of the MFS pool class.
|
||||
*
|
||||
|
|
@ -39,10 +39,6 @@
|
|||
SRCID(poolmfs, "$Id$");
|
||||
|
||||
|
||||
typedef MFS MFSPool;
|
||||
DECLARE_CLASS(Pool, MFSPool, AbstractPool);
|
||||
|
||||
|
||||
/* ROUND -- Round up
|
||||
*
|
||||
* Rounds n up to the nearest multiple of unit.
|
||||
|
|
@ -316,20 +312,20 @@ static Res MFSDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"unroundedUnitSize $W\n", (WriteFW)mfs->unroundedUnitSize,
|
||||
"extendBy $W\n", (WriteFW)mfs->extendBy,
|
||||
"extendSelf $S\n", WriteFYesNo(mfs->extendSelf),
|
||||
"unitSize $W\n", (WriteFW)mfs->unitSize,
|
||||
"freeList $P\n", (WriteFP)mfs->freeList,
|
||||
"total $W\n", (WriteFW)mfs->total,
|
||||
"free $W\n", (WriteFW)mfs->free,
|
||||
"tractList $P\n", (WriteFP)mfs->tractList,
|
||||
NULL);
|
||||
res = NextMethod(Pool, MFSPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
return ResOK;
|
||||
return WriteF(stream, depth + 2,
|
||||
"unroundedUnitSize $W\n", (WriteFW)mfs->unroundedUnitSize,
|
||||
"extendBy $W\n", (WriteFW)mfs->extendBy,
|
||||
"extendSelf $S\n", WriteFYesNo(mfs->extendSelf),
|
||||
"unitSize $W\n", (WriteFW)mfs->unitSize,
|
||||
"freeList $P\n", (WriteFP)mfs->freeList,
|
||||
"total $W\n", (WriteFW)mfs->total,
|
||||
"free $W\n", (WriteFW)mfs->free,
|
||||
"tractList $P\n", (WriteFP)mfs->tractList,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -386,7 +382,7 @@ Bool MFSCheck(MFS mfs)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* The MFS pool is used to manage small fixed-size chunks of memory. It
|
||||
* stores control structures in the memory it manages, rather than to one
|
||||
|
|
@ -32,6 +32,8 @@
|
|||
#include "mpscmfs.h"
|
||||
|
||||
typedef struct MFSStruct *MFS;
|
||||
typedef MFS MFSPool;
|
||||
DECLARE_CLASS(Pool, MFSPool, AbstractPool);
|
||||
|
||||
#define MFSPool(mfs) (&(mfs)->poolStruct)
|
||||
|
||||
|
|
@ -55,7 +57,7 @@ extern void MFSFinishTracts(Pool pool, MFSTractVisitor visitor,
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -770,6 +770,7 @@ Res MRGDeregister(Pool pool, Ref obj)
|
|||
* This could be improved by implementing MRGSegDescribe
|
||||
* and having MRGDescribe iterate over all the pool's segments.
|
||||
*/
|
||||
|
||||
static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
MRG mrg = CouldBeA(MRGPool, pool);
|
||||
|
|
@ -783,20 +784,25 @@ static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
res = NextMethod(Pool, MRGPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2, "extendBy $W\n", (WriteFW)mrg->extendBy, NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2, "Entry queue:\n", NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
arena = PoolArena(pool);
|
||||
res = WriteF(stream, depth, "extendBy $W\n", (WriteFW)mrg->extendBy, NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
res = WriteF(stream, depth, "Entry queue:\n", NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
RING_FOR(node, &mrg->entryRing, nextNode) {
|
||||
Bool outsideShield = !ArenaShield(arena)->inside;
|
||||
refPart = MRGRefPartOfLink(linkOfRing(node), arena);
|
||||
if (outsideShield) {
|
||||
ShieldEnter(arena);
|
||||
}
|
||||
res = WriteF(stream, depth, "at $A Ref $A\n",
|
||||
res = WriteF(stream, depth + 2, "at $A Ref $A\n",
|
||||
(WriteFA)refPart, (WriteFA)MRGRefPartRef(arena, refPart),
|
||||
NULL);
|
||||
if (outsideShield) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmv.c: MANUAL VARIABLE POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 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
|
||||
|
|
@ -733,44 +733,45 @@ static Size MVTotalSize(Pool pool)
|
|||
|
||||
static Size MVFreeSize(Pool pool)
|
||||
{
|
||||
MV mv;
|
||||
Size size = 0;
|
||||
Ring node, next;
|
||||
MV mv = MustBeA(MVPool, pool);
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolMV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
RING_FOR(node, &mv->spans, next) {
|
||||
MVSpan span = RING_ELT(MVSpan, spans, node);
|
||||
AVERT(MVSpan, span);
|
||||
size += span->free;
|
||||
#if defined(AVER_AND_CHECK_ALL)
|
||||
{
|
||||
Size size = 0;
|
||||
Ring node, next;
|
||||
RING_FOR(node, &mv->spans, next) {
|
||||
MVSpan span = RING_ELT(MVSpan, spans, node);
|
||||
AVERT(MVSpan, span);
|
||||
size += span->free;
|
||||
}
|
||||
AVER(size == mv->free);
|
||||
}
|
||||
#endif
|
||||
|
||||
AVER(size == mv->free + mv->lost);
|
||||
return size;
|
||||
return mv->free + mv->lost;
|
||||
}
|
||||
|
||||
|
||||
static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
MV mv = CouldBeA(MVPool, pool);
|
||||
Res res;
|
||||
MV mv;
|
||||
MVSpan span;
|
||||
Align step;
|
||||
Size length;
|
||||
char c;
|
||||
Ring spans, node = NULL, nextNode; /* gcc whinge stop */
|
||||
|
||||
if (!TESTT(Pool, pool))
|
||||
return ResFAIL;
|
||||
mv = PoolMV(pool);
|
||||
if (!TESTT(MV, mv))
|
||||
return ResFAIL;
|
||||
if (!TESTC(MVPool, mv))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
return ResPARAM;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
res = NextMethod(Pool, MVPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"blockPool $P ($U)\n",
|
||||
(WriteFP)mvBlockPool(mv), (WriteFU)mvBlockPool(mv)->serial,
|
||||
"spanPool $P ($U)\n",
|
||||
|
|
@ -781,7 +782,8 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
"free $W\n", (WriteFP)mv->free,
|
||||
"lost $W\n", (WriteFP)mv->lost,
|
||||
NULL);
|
||||
if(res != ResOK) return res;
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
step = pool->alignment;
|
||||
length = 0x40 * step;
|
||||
|
|
@ -791,11 +793,11 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
Addr i, j;
|
||||
MVBlock block;
|
||||
span = RING_ELT(MVSpan, spans, node);
|
||||
res = WriteF(stream, depth, "MVSpan $P {\n", (WriteFP)span, NULL);
|
||||
res = WriteF(stream, depth + 2, "MVSpan $P {\n", (WriteFP)span, NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
res = WriteF(stream, depth + 4,
|
||||
"span $P\n", (WriteFP)span,
|
||||
"tract $P\n", (WriteFP)span->tract,
|
||||
"free $W\n", (WriteFW)span->free,
|
||||
|
|
@ -815,7 +817,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
block = span->blocks;
|
||||
|
||||
for(i = span->base.base; i < span->limit.limit; i = AddrAdd(i, length)) {
|
||||
res = WriteF(stream, depth + 2, "$A ", (WriteFA)i, NULL);
|
||||
res = WriteF(stream, depth + 4, "$A ", (WriteFA)i, NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -847,7 +849,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
res = WriteF(stream, depth, "} MVSpan $P\n", (WriteFP)span, NULL);
|
||||
res = WriteF(stream, depth + 2, "} MVSpan $P\n", (WriteFP)span, NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
@ -927,7 +929,7 @@ Bool MVCheck(MV mv)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmv2.c: MANUAL VARIABLE-SIZED TEMPORAL POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: A manual-variable pool designed to take advantage of
|
||||
* placement according to predicted deathtime.
|
||||
|
|
@ -1025,34 +1025,34 @@ static Size MVTFreeSize(Pool pool)
|
|||
|
||||
static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
MVT mvt = CouldBeA(MVTPool, pool);
|
||||
Res res;
|
||||
MVT mvt;
|
||||
|
||||
if (!TESTT(Pool, pool))
|
||||
return ResFAIL;
|
||||
mvt = PoolMVT(pool);
|
||||
if (!TESTT(MVT, mvt))
|
||||
return ResFAIL;
|
||||
if (!TESTC(MVTPool, mvt))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"MVT $P {\n", (WriteFP)mvt,
|
||||
" minSize: $U\n", (WriteFU)mvt->minSize,
|
||||
" meanSize: $U\n", (WriteFU)mvt->meanSize,
|
||||
" maxSize: $U\n", (WriteFU)mvt->maxSize,
|
||||
" fragLimit: $U\n", (WriteFU)mvt->fragLimit,
|
||||
" reuseSize: $U\n", (WriteFU)mvt->reuseSize,
|
||||
" fillSize: $U\n", (WriteFU)mvt->fillSize,
|
||||
" availLimit: $U\n", (WriteFU)mvt->availLimit,
|
||||
" abqOverflow: $S\n", WriteFYesNo(mvt->abqOverflow),
|
||||
" splinter: $S\n", WriteFYesNo(mvt->splinter),
|
||||
" splinterBase: $A\n", (WriteFA)mvt->splinterBase,
|
||||
" splinterLimit: $A\n", (WriteFU)mvt->splinterLimit,
|
||||
" size: $U\n", (WriteFU)mvt->size,
|
||||
" allocated: $U\n", (WriteFU)mvt->allocated,
|
||||
" available: $U\n", (WriteFU)mvt->available,
|
||||
" unavailable: $U\n", (WriteFU)mvt->unavailable,
|
||||
res = NextMethod(Pool, MVTPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"minSize: $U\n", (WriteFU)mvt->minSize,
|
||||
"meanSize: $U\n", (WriteFU)mvt->meanSize,
|
||||
"maxSize: $U\n", (WriteFU)mvt->maxSize,
|
||||
"fragLimit: $U\n", (WriteFU)mvt->fragLimit,
|
||||
"reuseSize: $U\n", (WriteFU)mvt->reuseSize,
|
||||
"fillSize: $U\n", (WriteFU)mvt->fillSize,
|
||||
"availLimit: $U\n", (WriteFU)mvt->availLimit,
|
||||
"abqOverflow: $S\n", WriteFYesNo(mvt->abqOverflow),
|
||||
"splinter: $S\n", WriteFYesNo(mvt->splinter),
|
||||
"splinterBase: $A\n", (WriteFA)mvt->splinterBase,
|
||||
"splinterLimit: $A\n", (WriteFU)mvt->splinterLimit,
|
||||
"size: $U\n", (WriteFU)mvt->size,
|
||||
"allocated: $U\n", (WriteFU)mvt->allocated,
|
||||
"available: $U\n", (WriteFU)mvt->available,
|
||||
"unavailable: $U\n", (WriteFU)mvt->unavailable,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1103,8 +1103,7 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
METER_WRITE(mvt->exceptionSplinters, stream, depth + 2);
|
||||
METER_WRITE(mvt->exceptionReturns, stream, depth + 2);
|
||||
|
||||
res = WriteF(stream, depth, "} MVT $P\n", (WriteFP)mvt, NULL);
|
||||
return res;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1353,23 +1352,9 @@ static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena)
|
|||
}
|
||||
|
||||
|
||||
/* Return the CBS of an MVT pool for the benefit of fotest.c. */
|
||||
|
||||
extern Land _mps_mvt_cbs(Pool);
|
||||
Land _mps_mvt_cbs(Pool pool) {
|
||||
MVT mvt;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvt = PoolMVT(pool);
|
||||
AVERT(MVT, mvt);
|
||||
|
||||
return MVTFreePrimary(mvt);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmvff.c: First Fit Manual Variable Pool
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This is a pool class for manually managed objects of
|
||||
|
|
@ -297,7 +297,11 @@ static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size,
|
|||
}
|
||||
|
||||
|
||||
/* MVFFAlloc -- Allocate a block */
|
||||
/* MVFFAlloc -- Allocate a block
|
||||
*
|
||||
* .alloc.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
|
||||
static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size)
|
||||
{
|
||||
|
|
@ -307,11 +311,11 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size)
|
|||
LandFindMethod findMethod;
|
||||
FindDelete findDelete;
|
||||
|
||||
AVER(aReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER_CRITICAL(aReturn != NULL);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
AVERT_CRITICAL(MVFF, mvff);
|
||||
AVER_CRITICAL(size > 0);
|
||||
|
||||
size = SizeAlignUp(size, PoolAlignment(pool));
|
||||
findMethod = mvff->firstFit ? LandFindFirst : LandFindLast;
|
||||
|
|
@ -321,13 +325,17 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
AVER(RangeSize(&range) == size);
|
||||
AVER_CRITICAL(RangeSize(&range) == size);
|
||||
*aReturn = RangeBase(&range);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* MVFFFree -- free the given block */
|
||||
/* MVFFFree -- free the given block
|
||||
*
|
||||
* .free.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
|
||||
static void MVFFFree(Pool pool, Addr old, Size size)
|
||||
{
|
||||
|
|
@ -335,18 +343,18 @@ static void MVFFFree(Pool pool, Addr old, Size size)
|
|||
RangeStruct range, coalescedRange;
|
||||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
AVERT_CRITICAL(MVFF, mvff);
|
||||
|
||||
AVER(old != (Addr)0);
|
||||
AVER(AddrIsAligned(old, PoolAlignment(pool)));
|
||||
AVER(size > 0);
|
||||
AVER_CRITICAL(old != (Addr)0);
|
||||
AVER_CRITICAL(AddrIsAligned(old, PoolAlignment(pool)));
|
||||
AVER_CRITICAL(size > 0);
|
||||
|
||||
RangeInitSize(&range, old, SizeAlignUp(size, PoolAlignment(pool)));
|
||||
res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &range);
|
||||
/* Insertion must succeed because it fails over to a Freelist. */
|
||||
AVER(res == ResOK);
|
||||
AVER_CRITICAL(res == ResOK);
|
||||
MVFFReduce(mvff);
|
||||
}
|
||||
|
||||
|
|
@ -673,26 +681,24 @@ static Size MVFFFreeSize(Pool pool)
|
|||
|
||||
static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
MVFF mvff = CouldBeA(MVFFPool, pool);
|
||||
Res res;
|
||||
MVFF mvff;
|
||||
|
||||
if (!TESTT(Pool, pool))
|
||||
return ResFAIL;
|
||||
mvff = PoolMVFF(pool);
|
||||
if (!TESTT(MVFF, mvff))
|
||||
return ResFAIL;
|
||||
if (!TESTC(MVFFPool, mvff))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
return ResPARAM;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"MVFF $P {\n", (WriteFP)mvff,
|
||||
" pool $P ($U)\n",
|
||||
(WriteFP)pool, (WriteFU)pool->serial,
|
||||
" extendBy $W\n", (WriteFW)mvff->extendBy,
|
||||
" avgSize $W\n", (WriteFW)mvff->avgSize,
|
||||
" firstFit $U\n", (WriteFU)mvff->firstFit,
|
||||
" slotHigh $U\n", (WriteFU)mvff->slotHigh,
|
||||
" spare $D\n", (WriteFD)mvff->spare,
|
||||
res = NextMethod(Pool, MVFFPool, describe)(pool, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"extendBy $W\n", (WriteFW)mvff->extendBy,
|
||||
"avgSize $W\n", (WriteFW)mvff->avgSize,
|
||||
"firstFit $U\n", (WriteFU)mvff->firstFit,
|
||||
"slotHigh $U\n", (WriteFU)mvff->slotHigh,
|
||||
"spare $D\n", (WriteFD)mvff->spare,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -716,8 +722,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth, "} MVFF $P\n", (WriteFP)mvff, NULL);
|
||||
return res;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -799,23 +804,9 @@ static Bool MVFFCheck(MVFF mvff)
|
|||
}
|
||||
|
||||
|
||||
/* Return the CBS of an MVFF pool for the benefit of fotest.c. */
|
||||
|
||||
extern Land _mps_mvff_cbs(Pool);
|
||||
Land _mps_mvff_cbs(Pool pool) {
|
||||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return MVFFFreePrimary(mvff);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -565,7 +565,7 @@ static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame)
|
|||
arena = PoolArena(pool);
|
||||
addr = (Addr)frame;
|
||||
foundSeg = SegOfAddr(&seg, arena, addr);
|
||||
AVER(foundSeg);
|
||||
AVER(foundSeg); /* <design/check/#.common> */
|
||||
AVER(SegPool(seg) == pool);
|
||||
|
||||
if (SegBuffer(&segBuf, seg) && segBuf == buf) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* protxc.c: PROTECTION EXCEPTION HANDLER FOR OS X MACH
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2013-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is the protection exception handling code for OS X using the
|
||||
* Mach interface (not pthreads).
|
||||
|
|
@ -292,7 +292,7 @@ static void *protCatchThread(void *p) {
|
|||
extern void ProtThreadRegister(Bool setup)
|
||||
{
|
||||
kern_return_t kr;
|
||||
mach_msg_type_number_t old_exception_count;
|
||||
mach_msg_type_number_t old_exception_count = 1;
|
||||
exception_mask_t old_exception_masks;
|
||||
exception_behavior_t behavior;
|
||||
mach_port_t old_exception_ports;
|
||||
|
|
@ -338,7 +338,8 @@ extern void ProtThreadRegister(Bool setup)
|
|||
mach_error("ERROR: MPS thread_swap_exception_ports", kr); /* .trans.must */
|
||||
AVER(old_exception_masks == EXC_MASK_BAD_ACCESS);
|
||||
AVER(old_exception_count == 1);
|
||||
AVER(old_exception_ports == MACH_PORT_NULL); /* .assume.only-port */
|
||||
AVER(old_exception_ports == MACH_PORT_NULL
|
||||
|| old_exception_ports == protExcPort); /* .assume.only-port */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -401,7 +402,7 @@ void ProtSetup(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* pthreadext.c: POSIX THREAD EXTENSIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: Provides extension to Pthreads.
|
||||
*
|
||||
|
|
@ -28,15 +28,6 @@
|
|||
SRCID(pthreadext, "$Id$");
|
||||
|
||||
|
||||
/* PTHREADEXT_SIGSUSPEND, PTHREADEXT_SIGRESUME -- signals used
|
||||
*
|
||||
* See <design/pthreadext/#impl.signals>
|
||||
*/
|
||||
|
||||
#define PTHREADEXT_SIGSUSPEND SIGXFSZ
|
||||
#define PTHREADEXT_SIGRESUME SIGXCPU
|
||||
|
||||
|
||||
/* Static data initialized on first use of the module
|
||||
* See <design/pthreadext/#impl.static>.*
|
||||
*/
|
||||
|
|
@ -366,7 +357,7 @@ unlock:
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -129,6 +129,14 @@ Bool RootCheck(Root root)
|
|||
scan. */
|
||||
break;
|
||||
|
||||
case RootTHREAD:
|
||||
CHECKD_NOSIG(Thread, root->the.thread.thread); /* <design/check/#hidden-type> */
|
||||
CHECKL(FUNCHECK(root->the.thread.scan_area));
|
||||
/* Can't check anything about closure as it could mean anything to
|
||||
scan_area. */
|
||||
/* Can't check anything about stackCold. */
|
||||
break;
|
||||
|
||||
case RootTHREAD_TAGGED:
|
||||
CHECKD_NOSIG(Thread, root->the.thread.thread); /* <design/check/#hidden-type> */
|
||||
CHECKL(FUNCHECK(root->the.thread.scan_area));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* sacss.c: SAC MANUAL ALLOC STRESS TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
|
@ -74,11 +74,12 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
|
||||
/* allocate a load of objects */
|
||||
for (i = 0; i < testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i);
|
||||
|
||||
res = make((mps_addr_t *)&ps[i], sac, ss[i]);
|
||||
res = make(&obj, sac, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
ps[i] = obj;
|
||||
if (ss[i] >= sizeof(ps[i]))
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
}
|
||||
|
|
@ -113,17 +114,19 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
mps_addr_t obj;
|
||||
ss[i] = (*size)(i);
|
||||
switch (k % 2) {
|
||||
case 0:
|
||||
res = make((mps_addr_t *)&ps[i], sac, ss[i]);
|
||||
res = make(&obj, sac, ss[i]);
|
||||
break;
|
||||
default:
|
||||
res = mps_sac_alloc((mps_addr_t *)&ps[i], sac, ss[i], FALSE);
|
||||
res = mps_sac_alloc(&obj, sac, ss[i], FALSE);
|
||||
break;
|
||||
}
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
ps[i] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +249,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
104
mps/code/seg.c
104
mps/code/seg.c
|
|
@ -391,61 +391,57 @@ Addr SegBufferScanLimit(Seg seg)
|
|||
|
||||
/* SegDescribe -- describe a segment */
|
||||
|
||||
Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
Pool pool;
|
||||
SegClass klass;
|
||||
|
||||
if (!TESTC(Seg, seg))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResPARAM;
|
||||
|
||||
pool = SegPool(seg);
|
||||
klass = ClassOfPoly(Seg, seg);
|
||||
res = InstDescribe(CouldBeA(Inst, seg), stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"Segment $P [$A,$A) {\n", (WriteFP)seg,
|
||||
(WriteFA)SegBase(seg), (WriteFA)SegLimit(seg),
|
||||
" class $P (\"$S\")\n",
|
||||
(WriteFP)klass, (WriteFS)ClassName(klass),
|
||||
" pool $P ($U)\n",
|
||||
(WriteFP)pool, (WriteFU)pool->serial,
|
||||
" depth $U\n", seg->depth,
|
||||
" pm",
|
||||
pool = SegPool(seg);
|
||||
|
||||
res = WriteF(stream, depth + 2,
|
||||
"base $A\n", (WriteFA)SegBase(seg),
|
||||
"limit $A\n", (WriteFA)SegLimit(seg),
|
||||
"pool $P ($U)\n", (WriteFP)pool, (WriteFU)pool->serial,
|
||||
"depth $U\n", seg->depth,
|
||||
"pm",
|
||||
seg->pm == AccessSetEMPTY ? " EMPTY" : "",
|
||||
seg->pm & AccessREAD ? " READ" : "",
|
||||
seg->pm & AccessWRITE ? " WRITE" : "",
|
||||
"\n",
|
||||
" sm",
|
||||
"sm",
|
||||
seg->sm == AccessSetEMPTY ? " EMPTY" : "",
|
||||
seg->sm & AccessREAD ? " READ" : "",
|
||||
seg->sm & AccessWRITE ? " WRITE" : "",
|
||||
"\n",
|
||||
" grey $B\n", (WriteFB)seg->grey,
|
||||
" white $B\n", (WriteFB)seg->white,
|
||||
" nailed $B\n", (WriteFB)seg->nailed,
|
||||
" rankSet",
|
||||
"grey $B\n", (WriteFB)seg->grey,
|
||||
"white $B\n", (WriteFB)seg->white,
|
||||
"nailed $B\n", (WriteFB)seg->nailed,
|
||||
"rankSet",
|
||||
seg->rankSet == RankSetEMPTY ? " EMPTY" : "",
|
||||
BS_IS_MEMBER(seg->rankSet, RankAMBIG) ? " AMBIG" : "",
|
||||
BS_IS_MEMBER(seg->rankSet, RankEXACT) ? " EXACT" : "",
|
||||
BS_IS_MEMBER(seg->rankSet, RankFINAL) ? " FINAL" : "",
|
||||
BS_IS_MEMBER(seg->rankSet, RankWEAK) ? " WEAK" : "",
|
||||
"\n",
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = Method(Seg, seg, describe)(seg, stream, depth + 2);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
res = WriteF(stream, 0, "\n", NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth, "} Segment $P\n", (WriteFP)seg, NULL);
|
||||
return res;
|
||||
Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
return Method(Seg, seg, describe)(seg, stream, depth);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1037,39 +1033,6 @@ static Res segTrivSplit(Seg seg, Seg segHi,
|
|||
}
|
||||
|
||||
|
||||
/* segTrivDescribe -- Basic Seg description method */
|
||||
|
||||
static Res segTrivDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
|
||||
if (!TESTT(Seg, seg))
|
||||
return ResFAIL;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"shield depth $U\n", (WriteFU)seg->depth,
|
||||
"protection mode: ",
|
||||
(SegPM(seg) & AccessREAD) ? "" : "!", "READ", " ",
|
||||
(SegPM(seg) & AccessWRITE) ? "" : "!", "WRITE", "\n",
|
||||
"shield mode: ",
|
||||
(SegSM(seg) & AccessREAD) ? "" : "!", "READ", " ",
|
||||
(SegSM(seg) & AccessWRITE) ? "" : "!", "WRITE", "\n",
|
||||
"ranks:",
|
||||
RankSetIsMember(seg->rankSet, RankAMBIG) ? " ambiguous" : "",
|
||||
RankSetIsMember(seg->rankSet, RankEXACT) ? " exact" : "",
|
||||
RankSetIsMember(seg->rankSet, RankFINAL) ? " final" : "",
|
||||
RankSetIsMember(seg->rankSet, RankWEAK) ? " weak" : "",
|
||||
"\n",
|
||||
"white $B\n", (WriteFB)seg->white,
|
||||
"grey $B\n", (WriteFB)seg->grey,
|
||||
"nailed $B\n", (WriteFB)seg->nailed,
|
||||
NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Class GCSeg -- Segment class with GC support
|
||||
*/
|
||||
|
||||
|
|
@ -1149,7 +1112,7 @@ static void gcSegFinish(Seg seg)
|
|||
gcseg->sig = SigInvalid;
|
||||
|
||||
/* Don't leave a dangling buffer allocating into hyperspace. */
|
||||
AVER(gcseg->buffer == NULL);
|
||||
AVER(gcseg->buffer == NULL); /* <design/check/#.common> */
|
||||
|
||||
RingFinish(&gcseg->greyRing);
|
||||
|
||||
|
|
@ -1593,32 +1556,29 @@ failSuper:
|
|||
|
||||
static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
GCSeg gcseg = CouldBeA(GCSeg, seg);
|
||||
Res res;
|
||||
GCSeg gcseg;
|
||||
|
||||
if (!TESTT(Seg, seg))
|
||||
return ResFAIL;
|
||||
if (!TESTC(GCSeg, gcseg))
|
||||
return ResPARAM;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
gcseg = SegGCSeg(seg);
|
||||
if (!TESTT(GCSeg, gcseg))
|
||||
return ResFAIL;
|
||||
return ResPARAM;
|
||||
|
||||
/* Describe the superclass fields first via next-method call */
|
||||
res = NextMethod(Seg, GCSeg, describe)(seg, stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
res = WriteF(stream, depth + 2,
|
||||
"summary $W\n", (WriteFW)gcseg->summary,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
if (gcseg->buffer == NULL) {
|
||||
res = WriteF(stream, depth, "buffer: NULL\n", NULL);
|
||||
res = WriteF(stream, depth + 2, "buffer: NULL\n", NULL);
|
||||
} else {
|
||||
res = BufferDescribe(gcseg->buffer, stream, depth);
|
||||
res = BufferDescribe(gcseg->buffer, stream, depth + 2);
|
||||
}
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1670,7 +1630,7 @@ DEFINE_CLASS(Seg, Seg, klass)
|
|||
klass->setRankSummary = segNoSetRankSummary;
|
||||
klass->merge = segTrivMerge;
|
||||
klass->split = segTrivSplit;
|
||||
klass->describe = segTrivDescribe;
|
||||
klass->describe = SegAbsDescribe;
|
||||
klass->sig = SegClassSig;
|
||||
AVERT(SegClass, klass);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ SRCID(shield, "$Id$");
|
|||
void ShieldInit(Shield shield)
|
||||
{
|
||||
shield->inside = FALSE;
|
||||
shield->suspended = FALSE;
|
||||
shield->queuePending = FALSE;
|
||||
shield->queue = NULL;
|
||||
shield->length = 0;
|
||||
shield->next = 0;
|
||||
|
|
@ -25,7 +27,6 @@ void ShieldInit(Shield shield)
|
|||
shield->depth = 0;
|
||||
shield->unsynced = 0;
|
||||
shield->holds = 0;
|
||||
shield->suspended = FALSE;
|
||||
shield->sig = ShieldSig;
|
||||
}
|
||||
|
||||
|
|
@ -64,11 +65,10 @@ static Bool SegIsSynced(Seg seg);
|
|||
Bool ShieldCheck(Shield shield)
|
||||
{
|
||||
CHECKS(Shield, shield);
|
||||
CHECKL(BoolCheck(shield->inside));
|
||||
/* Can't check Boolean bitfields <design/type/#bool.bitfield.check> */
|
||||
CHECKL(shield->queue == NULL || shield->length > 0);
|
||||
CHECKL(shield->limit <= shield->length);
|
||||
CHECKL(shield->next <= shield->limit);
|
||||
CHECKL(BoolCheck(shield->suspended));
|
||||
|
||||
/* The mutator is not suspended while outside the shield
|
||||
(design.mps.shield.inv.outside.running). */
|
||||
|
|
@ -78,9 +78,6 @@ Bool ShieldCheck(Shield shield)
|
|||
(design.mps.shield.inv.unsynced.suspended). */
|
||||
CHECKL(shield->unsynced == 0 || shield->suspended);
|
||||
|
||||
/* If any segment is exposed, the mutator is suspended. */
|
||||
CHECKL(shield->depth == 0 || shield->suspended);
|
||||
|
||||
/* The total depth is zero while outside the shield
|
||||
(design.mps.shield.inv.outside.depth). */
|
||||
CHECKL(shield->inside || shield->depth == 0);
|
||||
|
|
@ -90,7 +87,7 @@ Bool ShieldCheck(Shield shield)
|
|||
|
||||
/* Every unsynced segment should be on the queue, because we have to
|
||||
remember to sync it before we return to the mutator. */
|
||||
CHECKL(shield->limit >= shield->unsynced);
|
||||
CHECKL(shield->limit + shield->queuePending >= shield->unsynced);
|
||||
|
||||
/* The mutator is suspeneded if there are any holds. */
|
||||
CHECKL(shield->holds == 0 || shield->suspended);
|
||||
|
|
@ -100,18 +97,15 @@ Bool ShieldCheck(Shield shield)
|
|||
16. */
|
||||
#if defined(AVER_AND_CHECK_ALL)
|
||||
{
|
||||
Count depth = 0;
|
||||
Count unsynced = 0;
|
||||
Index i;
|
||||
for (i = 0; i < shield->limit; ++i) {
|
||||
Seg seg = shield->queue[i];
|
||||
CHECKD(Seg, seg);
|
||||
depth += SegDepth(seg);
|
||||
if (!SegIsSynced(seg))
|
||||
++unsynced;
|
||||
}
|
||||
CHECKL(depth == shield->depth);
|
||||
CHECKL(unsynced == shield->unsynced);
|
||||
CHECKL(unsynced + shield->queuePending == shield->unsynced);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -539,9 +533,14 @@ static void shieldQueue(Arena arena, Seg seg)
|
|||
|
||||
void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode)
|
||||
{
|
||||
Shield shield;
|
||||
|
||||
SHIELD_AVERT(Arena, arena);
|
||||
SHIELD_AVERT(Seg, seg);
|
||||
AVERT(AccessSet, mode);
|
||||
shield = ArenaShield(arena);
|
||||
AVER(!shield->queuePending);
|
||||
shield->queuePending = TRUE;
|
||||
|
||||
/* design.mps.shield.inv.prot.shield preserved */
|
||||
shieldSetSM(ArenaShield(arena), seg, BS_UNION(SegSM(seg), mode));
|
||||
|
|
@ -549,6 +548,7 @@ void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode)
|
|||
/* Ensure design.mps.shield.inv.unsynced.suspended and
|
||||
design.mps.shield.inv.unsynced.depth */
|
||||
shieldQueue(arena, seg);
|
||||
shield->queuePending = FALSE;
|
||||
|
||||
/* Check queue and segment consistency. */
|
||||
AVERT(Arena, arena);
|
||||
|
|
@ -619,6 +619,7 @@ static void shieldDebugCheck(Arena arena)
|
|||
Shield shield;
|
||||
Seg seg;
|
||||
Count queued = 0;
|
||||
Count depth = 0;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
shield = ArenaShield(arena);
|
||||
|
|
@ -626,6 +627,7 @@ static void shieldDebugCheck(Arena arena)
|
|||
|
||||
if (SegFirst(&seg, arena))
|
||||
do {
|
||||
depth += SegDepth(seg);
|
||||
if (shield->limit == 0) {
|
||||
AVER(!seg->queued);
|
||||
AVER(SegIsSynced(seg));
|
||||
|
|
@ -638,6 +640,7 @@ static void shieldDebugCheck(Arena arena)
|
|||
}
|
||||
} while(SegNext(&seg, arena, seg));
|
||||
|
||||
AVER(depth == shield->depth);
|
||||
AVER(queued == shield->limit);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* splay.c: SPLAY TREE IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 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
|
||||
|
|
@ -509,9 +509,9 @@ static Compare SplaySplitRev(SplayStateStruct *stateReturn,
|
|||
Tree middle, leftLast, rightFirst;
|
||||
Compare cmp;
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVER(FUNCHECK(compare));
|
||||
AVER(!SplayTreeIsEmpty(splay));
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVER_CRITICAL(FUNCHECK(compare));
|
||||
AVER_CRITICAL(!SplayTreeIsEmpty(splay));
|
||||
|
||||
leftLast = TreeEMPTY;
|
||||
rightFirst = TreeEMPTY;
|
||||
|
|
@ -633,8 +633,8 @@ static void SplayAssembleRev(SplayTree splay, SplayState state)
|
|||
{
|
||||
Tree left, right;
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVER(state->middle != TreeEMPTY);
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVER_CRITICAL(state->middle != TreeEMPTY);
|
||||
|
||||
left = TreeLeft(state->middle);
|
||||
left = SplayUpdateRightSpine(splay, state->leftLast, left);
|
||||
|
|
@ -1394,7 +1394,7 @@ Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, Count depth,
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -846,12 +846,14 @@ void TraceDestroyFinished(Trace trace)
|
|||
|
||||
EVENT1(TraceDestroy, trace);
|
||||
|
||||
/* Hopefully the trace reclaimed some memory, so clear any emergency.
|
||||
* Do this before removing the trace from busyTraces, to avoid
|
||||
* violating <code/global.c#emergency.invariant>. */
|
||||
ArenaSetEmergency(trace->arena, FALSE);
|
||||
|
||||
trace->sig = SigInvalid;
|
||||
trace->arena->busyTraces = TraceSetDel(trace->arena->busyTraces, trace);
|
||||
trace->arena->flippedTraces = TraceSetDel(trace->arena->flippedTraces, trace);
|
||||
|
||||
/* Hopefully the trace reclaimed some memory, so clear any emergency. */
|
||||
ArenaSetEmergency(trace->arena, FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1176,7 +1178,7 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg)
|
|||
/* .verify.segsummary: were the seg contents, as found by this
|
||||
* scan, consistent with the recorded SegSummary?
|
||||
*/
|
||||
AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg)));
|
||||
AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))); /* <design/check/#.common> */
|
||||
|
||||
/* Write barrier deferral -- see design.mps.write-barrier.deferral. */
|
||||
/* Did the segment refer to the white set? */
|
||||
|
|
@ -1371,7 +1373,7 @@ mps_res_t _mps_fix2(mps_ss_t mps_ss, mps_addr_t *mps_ref_io)
|
|||
if (!BTGet(chunk->allocTable, i)) {
|
||||
/* Reference points into a chunk but not to an allocated tract.
|
||||
* See <design/trace/#exact.legal> */
|
||||
AVER_CRITICAL(ss->rank < RankEXACT);
|
||||
AVER_CRITICAL(ss->rank < RankEXACT); /* <design/check/#.common> */
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* tract.c: PAGE TABLES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .ullagepages: Pages whose page index is < allocBase are recorded as
|
||||
* free but never allocated as alloc starts searching after the tables.
|
||||
|
|
@ -60,8 +60,8 @@ Bool TractCheck(Tract tract)
|
|||
|
||||
void TractInit(Tract tract, Pool pool, Addr base)
|
||||
{
|
||||
AVER(tract != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER_CRITICAL(tract != NULL);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
|
||||
tract->pool.pool = pool;
|
||||
tract->base = base;
|
||||
|
|
@ -456,11 +456,11 @@ void PageAlloc(Chunk chunk, Index pi, Pool pool)
|
|||
Addr base;
|
||||
Page page;
|
||||
|
||||
AVERT(Chunk, chunk);
|
||||
AVER(pi >= chunk->allocBase);
|
||||
AVER(pi < chunk->pages);
|
||||
AVER(!BTGet(chunk->allocTable, pi));
|
||||
AVERT(Pool, pool);
|
||||
AVERT_CRITICAL(Chunk, chunk);
|
||||
AVER_CRITICAL(pi >= chunk->allocBase);
|
||||
AVER_CRITICAL(pi < chunk->pages);
|
||||
AVER_CRITICAL(!BTGet(chunk->allocTable, pi));
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
|
||||
page = ChunkPage(chunk, pi);
|
||||
tract = PageTract(page);
|
||||
|
|
@ -476,9 +476,9 @@ void PageInit(Chunk chunk, Index pi)
|
|||
{
|
||||
Page page;
|
||||
|
||||
AVERT(Chunk, chunk);
|
||||
AVER(pi < chunk->pages);
|
||||
|
||||
AVERT_CRITICAL(Chunk, chunk);
|
||||
AVER_CRITICAL(pi < chunk->pages);
|
||||
|
||||
page = ChunkPage(chunk, pi);
|
||||
|
||||
BTRes(chunk->allocTable, pi);
|
||||
|
|
@ -504,7 +504,7 @@ void PageFree(Chunk chunk, Index pi)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -567,9 +567,10 @@ _`.ld`: The ``historyStruct`` contains fields used to maintain a
|
|||
history of garbage collection and in particular object motion in order
|
||||
to implement location dependency.
|
||||
|
||||
_`.ld.epoch`: The ``epoch`` is the "current epoch". This is the
|
||||
number of 'flips' of traces in the arena since the arena was created.
|
||||
From the mutator's point of view locations change atomically at flip.
|
||||
_`.ld.epoch`: The ``epoch`` is the "current epoch". This is the number
|
||||
of "flips" of traces, in which objects might have moved, in the arena
|
||||
since it was created. From the mutator's point of view, locations
|
||||
change atomically at flip.
|
||||
|
||||
_`.ld.history`: The ``history`` is a circular buffer of
|
||||
``LDHistoryLENGTH`` elements of type ``RefSet``. These are the
|
||||
|
|
@ -619,7 +620,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
Copyright © 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
All rights reserved. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,18 @@ reference this tag. The structure could be considered for addition to
|
|||
``mpmst.h``.
|
||||
|
||||
|
||||
Common assertions
|
||||
-----------------
|
||||
|
||||
_`.common`: Some assertions are commonly triggered by mistakes in the
|
||||
:term:`client program`. These are listed in the section "Common
|
||||
assertions and their causes" in the MPS Reference, together with an
|
||||
explanation of their likely cause, and advice for fixing the problem.
|
||||
To assist with keeping the MPS Reference up to date, these assertions
|
||||
are marked with a cross-reference to this tag. When you update the
|
||||
assertion, you must also update the MPS Reference.
|
||||
|
||||
|
||||
Document History
|
||||
----------------
|
||||
|
||||
|
|
@ -138,7 +150,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
Copyright © 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
All rights reserved. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -550,6 +550,16 @@ happen if requested explicitly via ``mps_arena_collect()`` or
|
|||
``mps_arena_step()``, but it also means that protection is not needed,
|
||||
and so shield operations can be replaced with no-ops in ``mpm.h``.
|
||||
|
||||
_`.opt.signal.suspend`: ``CONFIG_PTHREADEXT_SIGSUSPEND`` names the
|
||||
signal used to suspend a thread, on platforms using the POSIX thread
|
||||
extensions module. See design.pthreadext.impl.signals_.
|
||||
|
||||
.. _design.pthreadext.impl.signals: pthreadext#impl.signals
|
||||
|
||||
_`.opt.signal.resume`: ``CONFIG_PTHREADEXT_SIGRESUME`` names the
|
||||
signal used to resume a thread, on platforms using the POSIX thread
|
||||
extensions module. See design.pthreadext.impl.signals_.
|
||||
|
||||
|
||||
To document
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ write-protected segment. See ``TraceSegAccess()``.)
|
|||
Design
|
||||
------
|
||||
|
||||
_`.sol.sync`: If memory protection is not available, only way to meet
|
||||
`.req.consistent`_, is ensure that no protection is required,
|
||||
essentially by running the collector until it has no more incremental
|
||||
work to do. (This makes it impossible to meet real-time requirements
|
||||
on pause times, but may be the best that can be done.)
|
||||
_`.sol.sync`: If memory protection is not available, the only way to
|
||||
meet `.req.consistent`_ is to ensure that no protection is required,
|
||||
by running the collector until it has no more incremental work to do.
|
||||
(This makes it impossible to meet real-time requirements on pause
|
||||
times, but may be the best that can be done.)
|
||||
|
||||
_`.sol.fault.handle`: The protection module handles protection faults
|
||||
by decoding the context of the fault (see
|
||||
|
|
@ -165,7 +165,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
Copyright © 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
All rights reserved. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ describes it, like this::
|
|||
|
||||
_`.overview.prefix`: We make use of the fact that we can cast between
|
||||
structures with common prefixes, or between structures and their first
|
||||
members, to provide dynamic typing and subtyping (see [K&R_1998]_,
|
||||
A.8.3).
|
||||
members, to provide dynamic typing and subtyping (see
|
||||
[Kernighan_1988]_, A.8.3).
|
||||
|
||||
_`.overview.method`: The ``InstClassStruct`` it itself at the start of
|
||||
a class structure contains pointers to functions that can be called to
|
||||
|
|
@ -575,6 +575,8 @@ level. The level is statically defined using enum constants, and the
|
|||
id is the address of the canonical class object, so the test is fast
|
||||
and simple.
|
||||
|
||||
.. _RB: http://www.ravenbrook.com/consultants/rb/
|
||||
|
||||
|
||||
A. References
|
||||
-------------
|
||||
|
|
@ -582,14 +584,14 @@ A. References
|
|||
.. [Cohen_1991] "Type-Extension Type Tests Can Be Performed In
|
||||
Constant Time"; Norman H Cohen; IBM Thomas J Watson Research
|
||||
Center; ACM Transactions on Programming Languages and Systems,
|
||||
Vol. 13 No. 4, pp626-629; 1991-10.
|
||||
Vol. 13 No. 4, pp. 626-629; 1991-10.
|
||||
|
||||
.. [Gibbs_2004] "Fast Dynamic Casting"; Michael Gibbs, Bjarne
|
||||
Stroustrup; 2004;
|
||||
<http://www.stroustrup.com/fast_dynamic_casting.pdf>.
|
||||
|
||||
.. [K&R_1988] "The C Programming language 2nd Edition";
|
||||
Brian W. Kernighan, Dennis M. Ritchie; 1998.
|
||||
.. [Kernighan_1988] "The C Programming language 2nd Edition"; Brian W.
|
||||
Kernighan, Dennis M. Ritchie; 1988.
|
||||
|
||||
|
||||
B. Document History
|
||||
|
|
@ -612,7 +614,6 @@ B. Document History
|
|||
|
||||
- 2016-04-19 RB_ Miscellaneous clean-up in response to review by GDR_.
|
||||
|
||||
.. _RB: http://www.ravenbrook.com/consultants/rb/
|
||||
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -324,10 +324,17 @@ likely to be generated and/or handled by other parts of the
|
|||
application and so should not be used (for example, ``SIGSEGV``). Some
|
||||
implementations of PThreads use some signals for themselves, so they
|
||||
may not be used; for example, LinuxThreads uses ``SIGUSR1`` and
|
||||
``SIGUSR2`` for its own purposes. The design abstractly names the
|
||||
signals ``PTHREADEXT_SIGSUSPEND`` and ``PTHREAD_SIGRESUME``, so that
|
||||
they may be easily mapped to appropriate real signal values. Candidate
|
||||
choices are ``SIGXFSZ`` and ``SIGPWR``.
|
||||
``SIGUSR2`` for its own purposes, and so do popular tools like
|
||||
Valgrind that we would like to be compatible with the MPS. The design
|
||||
therefore abstractly names the signals ``PTHREADEXT_SIGSUSPEND`` and
|
||||
``PTHREAD_SIGRESUME``, so that they may be easily mapped to
|
||||
appropriate real signal values. Candidate choices are ``SIGXFSZ`` and
|
||||
``SIGXCPU``.
|
||||
|
||||
_`.impl.signals.config`: The identity of the signals used to suspend
|
||||
and resume threads can be configured at compilation time using the
|
||||
preprocessor constants ``CONFIG_PTHREADEXT_SIGSUSPEND`` and
|
||||
``CONFIG_PTHREADEXT_SIGRESUME`` respectively.
|
||||
|
||||
|
||||
Attachments
|
||||
|
|
@ -368,7 +375,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
Copyright © 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
All rights reserved. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -549,11 +549,13 @@ clock time when the MPS was entered; ``moreWork`` and ``tracedWork``
|
|||
are the results of the last call to ``TracePoll()``.
|
||||
|
||||
_`.policy.poll.impl`: The implementation keep doing work until either
|
||||
the maximum pause time is exceeded (see design.mps.arena.pause-time_),
|
||||
the maximum pause time is exceeded (see `design.mps.arena.pause-time`_),
|
||||
or there is no more work to do. Then it schedules the next collection
|
||||
so that there is approximately one call to ``TracePoll()`` for every
|
||||
``ArenaPollALLOCTIME`` bytes of allocation.
|
||||
|
||||
.. _design.mps.arena.pause-time: arena#pause-time
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
|
|
|
|||
|
|
@ -136,17 +136,16 @@ well:
|
|||
Platform OS Architecture Compiler Makefile
|
||||
========== ========= ============= ============ =================
|
||||
``fri3gc`` FreeBSD IA-32 GCC ``fri3gc.gmk``
|
||||
``fri6gc`` FreeBSD x86_64 GCC ``fri6gc.gmk``
|
||||
``fri3ll`` FreeBSD IA-32 Clang ``fri3ll.gmk``
|
||||
``fri6gc`` FreeBSD x86_64 GCC ``fri6gc.gmk``
|
||||
``fri6ll`` FreeBSD x86_64 Clang ``fri6ll.gmk``
|
||||
``lii3gc`` Linux IA-32 GCC ``lii3gc.gmk``
|
||||
``lii6gc`` Linux x86_64 GCC ``lii6gc.gmk``
|
||||
``lii6ll`` Linux x86_64 Clang ``lii6ll.gmk``
|
||||
``xci3ll`` Mac OS X IA-32 Clang ``mps.xcodeproj``
|
||||
``xci6ll`` Mac OS X x86_64 Clang ``mps.xcodeproj``
|
||||
``xci3gc`` Mac OS X IA-32 GCC (legacy) ``xci3gc.gmk``
|
||||
``w3i3mv`` Windows IA-32 Microsoft C ``w3i3mv.nmk``
|
||||
``w3i6mv`` Windows x86_64 Microsoft C ``w3i6mv.nmk``
|
||||
``xci3ll`` Mac OS X IA-32 Clang ``mps.xcodeproj``
|
||||
``xci6ll`` Mac OS X x86_64 Clang ``mps.xcodeproj``
|
||||
========== ========= ============= ============ =================
|
||||
|
||||
Historically, the MPS worked on a much wider variety of platforms, and
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ TYPES = '''
|
|||
|
||||
mode = re.compile(r'\.\. mode: .*\n')
|
||||
prefix = re.compile(r'^:Tag: ([a-z][a-z.0-9-]*[a-z0-9])$', re.MULTILINE)
|
||||
rst_tag = re.compile(r'^:(?:Author|Date|Status|Revision|Copyright|Organization|Format|Index terms):.*?$\n', re.MULTILINE | re.IGNORECASE)
|
||||
rst_tag = re.compile(r'^:(?:Author|Date|Status|Revision|Copyright|Organization|Format|Index terms|Readership):.*?$\n', re.MULTILINE | re.IGNORECASE)
|
||||
mps_tag = re.compile(r'_`\.([a-z][A-Za-z.0-9_-]*[A-Za-z0-9])`:')
|
||||
mps_ref = re.compile(r'`(\.[a-z][A-Za-z.0-9_-]*[A-Za-z0-9])`_(?: )?')
|
||||
funcdef = re.compile(r'^``([^`]*\([^`]*\))``$', re.MULTILINE)
|
||||
|
|
@ -61,10 +61,10 @@ def secnum_sub(m):
|
|||
# .. [THVV_1995] Tom Van Vleck. 1995. "`Structure Marking <http://www.multicians.org/thvv/marking.html>`__".
|
||||
citation = re.compile(
|
||||
r'''
|
||||
^\.\.\s+(?P<ref>\[.*?\])\s*
|
||||
"(?P<title>[^"]*?)"\s*
|
||||
;\s*(?P<author>[^;]*?)\s*
|
||||
(?:;\s*(?P<organization>[^;]*?)\s*)?
|
||||
^\.\.\s+(?P<ref>\[[^\n\]]+\])\s*
|
||||
"(?P<title>[^"]+?)"\s*
|
||||
;\s*(?P<author>[^;]+?)\s*
|
||||
(?:;\s*(?P<organization>[^;]+?)\s*)?
|
||||
;\s*(?P<date>[0-9-]+)\s*
|
||||
(?:;\s*<\s*(?P<url>[^>]*?)\s*>\s*)?
|
||||
\.
|
||||
|
|
@ -72,21 +72,19 @@ citation = re.compile(
|
|||
re.VERBOSE | re.MULTILINE | re.IGNORECASE | re.DOTALL
|
||||
)
|
||||
def citation_sub(m):
|
||||
groups = m.groupdict()
|
||||
for key in groups:
|
||||
if groups[key]:
|
||||
groups[key] = re.sub(r'\s+', ' ', groups[key])
|
||||
result = '.. {ref} {author}.'.format(**groups)
|
||||
if groups.get('organization'):
|
||||
result += ' {organization}.'.format(**groups)
|
||||
result += ' {date}.'.format(**groups)
|
||||
if groups.get('url'):
|
||||
result += ' "`{title} <{url}>`__".'.format(**groups)
|
||||
groups = {k: re.sub(r'\s+', ' ', v) for k, v in m.groupdict().items() if v}
|
||||
fmt = '.. {ref} {author}.'
|
||||
if 'organization' in groups:
|
||||
fmt += ' {organization}.'
|
||||
fmt += ' {date}.'
|
||||
if 'url' in groups:
|
||||
fmt += ' "`{title} <{url}>`__".'
|
||||
else:
|
||||
result += ' "{title}".'.format(**groups)
|
||||
return result
|
||||
fmt += ' "{title}".'
|
||||
return fmt.format(**groups)
|
||||
|
||||
index = re.compile(r'^:Index\s+terms:(.*$\n(?:[ \t]+.*$\n)*)', re.MULTILINE | re.IGNORECASE)
|
||||
index = re.compile(r'^:Index\s+terms:(.*$\n(?:[ \t]+.*$\n)*)',
|
||||
re.MULTILINE | re.IGNORECASE)
|
||||
|
||||
# <http://sphinx-doc.org/markup/misc.html#directive-index>
|
||||
index_term = re.compile(r'^\s*(\w+):\s*(.*?)\s*$', re.MULTILINE)
|
||||
|
|
|
|||
|
|
@ -141,9 +141,9 @@ releasing the resource (here, the Scheme function
|
|||
|
||||
But this raises the possibility that a port will be closed twice: once
|
||||
via ``close-input-port`` and a second time via finalization. So it's
|
||||
necessary to make ports robust against be closed multiple times. The
|
||||
toy Scheme interpreter does so by setting ``stream`` to ``NULL``: this
|
||||
ensures that the file handle won't be closed more than once.
|
||||
necessary to make ports robust against being closed multiple times.
|
||||
The toy Scheme interpreter does so by setting ``stream`` to ``NULL``:
|
||||
this ensures that the file handle won't be closed more than once.
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 6
|
||||
|
|
|
|||
|
|
@ -15,10 +15,20 @@ Interface changes
|
|||
|
||||
#. Allocation frames are no longer deprecated. See :ref:`topic-frame`.
|
||||
|
||||
#. On Linux and FreeBSD, it is now possible to configure the signals
|
||||
used to suspend and resume threads. See :ref:`topic-thread-signal`.
|
||||
|
||||
|
||||
Other changes
|
||||
.............
|
||||
|
||||
#. It is now possible to register a thread with the MPS multiple times
|
||||
on OS X, thus supporting the use case where a program that does not
|
||||
use the MPS is calling into MPS-using code from multiple threads.
|
||||
(This was already supported on other platforms.) See job003559_.
|
||||
|
||||
.. _job003559: https://www.ravenbrook.com/project/mps/issue/job003559/
|
||||
|
||||
#. Objects in :ref:`pool-snc` pools are no longer scanned after their
|
||||
:term:`allocation frame` is popped, and so do not keep objects in
|
||||
automatically managed pools alive. See job003883_.
|
||||
|
|
@ -36,6 +46,20 @@ Other changes
|
|||
|
||||
.. _job004011: https://www.ravenbrook.com/project/mps/issue/job004011/
|
||||
|
||||
#. Roots created by :c:func:`mps_root_create_thread_scanned` no longer
|
||||
cause an assertion failure. See job004036_.
|
||||
|
||||
.. _job004036: https://www.ravenbrook.com/project/mps/issue/job004036/
|
||||
|
||||
#. The MPS test suite now compiles and passes with GCC 6.1. See job004037_.
|
||||
|
||||
.. _job004037: https://www.ravenbrook.com/project/mps/issue/job004037/
|
||||
|
||||
#. The MPS no longer passes an uninitialized variable to
|
||||
:c:func:`thread_swap_exception_ports` on OS X. See job004040_.
|
||||
|
||||
.. _job004040: https://www.ravenbrook.com/project/mps/issue/job004040/
|
||||
|
||||
|
||||
.. _release-notes-1.115:
|
||||
|
||||
|
|
@ -112,6 +136,14 @@ Interface changes
|
|||
#. The :ref:`pool-snc` pool class now implements
|
||||
:c:func:`mps_pool_total_size` and :c:func:`mps_pool_free_size`.
|
||||
|
||||
#. The (undocumented) reservoir functions
|
||||
:c:func:`mps_ap_fill_with_reservoir_permit`,
|
||||
:c:func:`mps_reservoir_available`, :c:func:`mps_reservoir_limit`,
|
||||
:c:func:`mps_reservoir_limit_set`, and
|
||||
:c:func:`mps_reserve_with_reservoir_permit`, together with the
|
||||
``has_reservoir_permit`` arguments to :c:func:`mps_sac_alloc` and
|
||||
:c:func:`MPS_SAC_ALLOC_FAST` are now deprecated.
|
||||
|
||||
|
||||
Other changes
|
||||
.............
|
||||
|
|
|
|||
|
|
@ -45,6 +45,20 @@ Manual allocation
|
|||
unaligned, it will be rounded up to the pool's :term:`alignment`
|
||||
(unless the pool documentation says otherwise).
|
||||
|
||||
.. note::
|
||||
|
||||
It is tempting to call :c:func:`mps_alloc` with a cast from
|
||||
the desired pointer type to ``mps_addr_t *``, like this::
|
||||
|
||||
my_object *obj;
|
||||
res = mps_alloc((mps_addr_t *)&obj, pool, sizeof *obj);
|
||||
if (res != MPS_RES_OK)
|
||||
error(...);
|
||||
|
||||
but this is :term:`type punning`, and its behaviour is not
|
||||
defined in ANSI/ISO Standard C. See :ref:`topic-interface-pun`
|
||||
for more details.
|
||||
|
||||
|
||||
.. c:function:: void mps_free(mps_pool_t pool, mps_addr_t addr, size_t size)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ An arena is an object that encapsulates the state of the Memory Pool
|
|||
System, and tells it where to get the memory it manages. You typically
|
||||
start a session with the MPS by creating an arena with
|
||||
:c:func:`mps_arena_create_k` and end the session by destroying it with
|
||||
:c:func:`mps_arena_destroy`. The only function you might need to call
|
||||
before making an arena is :c:func:`mps_telemetry_control`.
|
||||
:c:func:`mps_arena_destroy`. The only functions you might need to call
|
||||
before making an arena are :term:`telemetry system` functions like
|
||||
:c:func:`mps_telemetry_set` and the :term:`plinth` function
|
||||
:c:func:`mps_lib_assert_fail_install`.
|
||||
|
||||
Before destroying an arena, you must first destroy all objects and
|
||||
data in it, as usual for abstract data types in the MPS. If you can't
|
||||
|
|
@ -470,8 +472,8 @@ Arena properties
|
|||
When the pause time is short, the MPS needs to take more slices of
|
||||
time in order to make :term:`garbage collection` progress, and
|
||||
make more use of :term:`barriers (1)` to support
|
||||
:term:`incremental collection`. This increases time overheads,
|
||||
and especially operating system overheads.
|
||||
:term:`incremental garbage collection`. This increases time
|
||||
overheads, and especially operating system overheads.
|
||||
|
||||
The pause time may be set to zero, in which case the MPS returns
|
||||
as soon as it can, without regard for overall efficiency. This
|
||||
|
|
@ -485,7 +487,7 @@ Arena properties
|
|||
The pause time may be set to infinity, in which case the MPS
|
||||
completes all outstanding :term:`garbage collection` work before
|
||||
returning from an operation. The consequence is that the MPS will
|
||||
be able to save on the overheads due to :term:`incremental
|
||||
be able to save on the overheads due to :term:`incremental garbage
|
||||
collection`, leading to lower total time spent in collection. This
|
||||
value is suitable for non-interactive applications where total
|
||||
time is important.
|
||||
|
|
|
|||
|
|
@ -285,26 +285,34 @@ Allocation interface
|
|||
|
||||
.. note::
|
||||
|
||||
There's also a macro :c:func:`MPS_SAC_ALLOC_FAST` that does
|
||||
the same thing. The macro is faster, but generates more code
|
||||
and does less checking.
|
||||
1. There's also a macro :c:func:`MPS_SAC_ALLOC_FAST` that does
|
||||
the same thing. The macro is faster, but generates more
|
||||
code and does less checking.
|
||||
|
||||
.. note::
|
||||
2. The :term:`client program` is responsible for synchronizing
|
||||
the access to the cache, but if the cache decides to access
|
||||
the pool, the MPS will properly synchronize with any other
|
||||
:term:`threads` that might be accessing the same pool.
|
||||
|
||||
The :term:`client program` is responsible for synchronizing
|
||||
the access to the cache, but if the cache decides to access
|
||||
the pool, the MPS will properly synchronize with any other
|
||||
:term:`threads` that might be accessing the same
|
||||
pool.
|
||||
3. Blocks allocated through a segregated allocation cache
|
||||
should only be freed through a segregated allocation cache
|
||||
with the same class structure. Calling :c:func:`mps_free`
|
||||
on them can cause :term:`memory leaks`, because the size of
|
||||
the block might be larger than you think. Naturally, the
|
||||
cache must also be attached to the same pool.
|
||||
|
||||
.. note::
|
||||
4. It is tempting to call :c:func:`mps_sac_alloc` with a cast
|
||||
from the desired pointer type to ``mps_addr_t *``, like
|
||||
this::
|
||||
|
||||
Blocks allocated through a segregated allocation cache should
|
||||
only be freed through a segregated allocation cache with the
|
||||
same class structure. Calling :c:func:`mps_free` on them can
|
||||
cause :term:`memory leaks`, because the size of
|
||||
the block might be larger than you think. Naturally, the cache
|
||||
must also be attached to the same pool.
|
||||
my_object *obj;
|
||||
res = mps_alloc((mps_addr_t *)&obj, sac, sizeof *obj, 0);
|
||||
if (res != MPS_RES_OK)
|
||||
error(...);
|
||||
|
||||
but this is :term:`type punning`, and its behaviour is not
|
||||
defined in ANSI/ISO Standard C. See
|
||||
:ref:`topic-interface-pun` for more details.
|
||||
|
||||
|
||||
.. c:function:: MPS_SAC_ALLOC_FAST(mps_res_t res_v, mps_addr_t *p_v, mps_sac_t sac, size_t size, mps_bool_t has_reservoir_permit)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,15 @@ supported interface.
|
|||
Deprecated in version 1.115
|
||||
...........................
|
||||
|
||||
.. c:function:: mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Identical to :c:func:`mps_ap_fill`, which should be used
|
||||
instead. Formerly, this function gave the MPS permission to
|
||||
draw on the ‘low-memory reservoir’, but this no longer exists.
|
||||
|
||||
|
||||
.. c:type:: typedef mps_pool_class_t mps_class_t
|
||||
|
||||
.. deprecated::
|
||||
|
|
@ -118,6 +127,41 @@ Deprecated in version 1.115
|
|||
is the sum of allocated space and free space.
|
||||
|
||||
|
||||
.. c:function:: mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Identical to :c:func:`mps_reserve`, which should be used
|
||||
instead. Formerly, this function gave the MPS permission to
|
||||
draw on the ‘low-memory reservoir’, but this no longer
|
||||
exists.
|
||||
|
||||
|
||||
.. c:function:: void mps_reservoir_limit_set(mps_arena_t arena, size_t size)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Has no effect. Formerly, it updated the recommended size of
|
||||
the ‘low-memory reservoir’, but this no longer exists.
|
||||
|
||||
|
||||
.. c:function:: size_t mps_reservoir_limit(mps_arena_t arena)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Returns zero. Formerly, it returned the recommended size of
|
||||
the ‘low-memory reservoir’, but this no longer exists.
|
||||
|
||||
|
||||
.. c:function:: size_t mps_reservoir_available(mps_arena_t arena)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Returns zero. Formerly, it returned the size of the available
|
||||
memory in the ‘low-memory reservoir’, but this no longer
|
||||
exists.
|
||||
|
||||
|
||||
.. c:function:: mps_res_t mps_root_create_reg(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_reg_scan_t reg_scan, void *p, size_t s)
|
||||
|
||||
.. deprecated::
|
||||
|
|
@ -275,16 +319,15 @@ Deprecated in version 1.115
|
|||
|
||||
.. deprecated::
|
||||
|
||||
This function is equivalent to::
|
||||
Use :c:func:`mps_root_create_area_tagged` instead, passing
|
||||
zero for the ``pattern`` argument. This function is equivalent
|
||||
to::
|
||||
|
||||
mps_root_create_area_tagged(root_o, arena, rank, rm,
|
||||
base, base + size,
|
||||
mps_scan_area_tagged,
|
||||
mask, 0)
|
||||
|
||||
Use :c:func:`mps_root_create_area_masked` instead, passing
|
||||
zero for the ``pattern`` argument.
|
||||
|
||||
Register a :term:`root` that consists of a vector of :term:`tagged
|
||||
references` whose pattern is zero.
|
||||
|
||||
|
|
@ -323,18 +366,12 @@ Deprecated in version 1.115
|
|||
|
||||
:ref:`topic-scanning`.
|
||||
|
||||
.. note::
|
||||
|
||||
:term:`Client programs` are not expected to
|
||||
write scanning functions of this type. The built-in MPS
|
||||
function :c:func:`mps_stack_scan_ambig` must be used.
|
||||
|
||||
|
||||
.. c:function:: mps_reg_scan_t mps_stack_scan_ambig
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Use :c:func:`mps_root_create_thread` instead, passing
|
||||
Use :c:func:`mps_root_create_thread_tagged` instead, passing
|
||||
``sizeof(mps_word_t) - 1`` for the ``mask`` argument, and
|
||||
``0`` for the ``pattern`` argument.
|
||||
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ this documentation.
|
|||
It is necessary to call :c:func:`mps_fmt_destroy` first.
|
||||
|
||||
|
||||
``global.c: RingIsSingle(&arena->rootRing)``
|
||||
``global.c: RingIsSingle(&arenaGlobals->rootRing)``
|
||||
|
||||
The client program called :c:func:`mps_arena_destroy` without
|
||||
destroying all the :term:`roots` belonging to the arena.
|
||||
|
|
@ -300,7 +300,7 @@ this documentation.
|
|||
It is necessary to call :c:func:`mps_thread_dereg` first.
|
||||
|
||||
|
||||
``global.c: RingLength(&arenaGlobals->poolRing) == 5``
|
||||
``global.c: RingLength(&arenaGlobals->poolRing) == 4``
|
||||
|
||||
The client program called :c:func:`mps_arena_destroy` without
|
||||
destroying all the :term:`pools` belonging to the arena.
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ Cautions
|
|||
are finalized is to maintain a table of :term:`weak
|
||||
references (1)` to all such objects. The weak references don't
|
||||
prevent the objects from being finalized, but you can iterate
|
||||
over the list at an appropriate point and finalize any
|
||||
over the table at an appropriate point and finalize any
|
||||
remaining objects yourself.
|
||||
|
||||
#. Not all :term:`pool classes` support finalization. In general, only
|
||||
|
|
|
|||
|
|
@ -243,11 +243,12 @@ Cautions
|
|||
|
||||
a. call library code;
|
||||
|
||||
b. perform a non-local exit (for example, by calling ``longjmp``);
|
||||
b. perform a non-local exit (for example, by throwing an exception,
|
||||
or calling :c:func:`longjmp`);
|
||||
|
||||
c. call any functions in the MPS other than the fix functions
|
||||
(:c:func:`mps_fix`, :c:func:`MPS_FIX1`, :c:func:`MPS_FIX12`, and
|
||||
:c:func:`MPS_FIX2`).
|
||||
c. call any functions or macros in the MPS other than the fix
|
||||
macros :c:func:`MPS_FIX1`, :c:func:`MPS_FIX12`, and
|
||||
:c:func:`MPS_FIX2`.
|
||||
|
||||
It's permissible to call other functions in the client program, but
|
||||
see :c:func:`MPS_FIX_CALL` for a restriction on passing the
|
||||
|
|
@ -368,7 +369,7 @@ Format methods
|
|||
object format has a non-zero
|
||||
:c:macro:`MPS_KEY_FMT_HEADER_SIZE`.
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
The MPS will ask for padding objects of any size aligned to
|
||||
the pool alignment, no matter what size objects the pool
|
||||
|
|
|
|||
|
|
@ -30,4 +30,4 @@ Reference
|
|||
platform
|
||||
porting
|
||||
deprecated
|
||||
|
||||
security
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ the function :c:func:`mps_ld_reset`.
|
|||
|
||||
.. note::
|
||||
|
||||
This means that it is not possible to statically create a location
|
||||
dependency that has been reset.
|
||||
It is not possible to statically create a location dependency that
|
||||
has been reset.
|
||||
|
||||
You can call :c:func:`mps_ld_reset` at any later point to clear all
|
||||
dependencies from the structure. For example, this is normally done
|
||||
|
|
|
|||
|
|
@ -142,14 +142,7 @@ Platform interface
|
|||
IA-32 processor architecture, and the GCC compiler.
|
||||
|
||||
|
||||
.. c:macro:: MPS_PF_FRI6GC
|
||||
|
||||
A :term:`C` preprocessor macro that indicates, if defined, that
|
||||
the :term:`platform` consists of the FreeBSD operating system, the
|
||||
x86-64 processor architecture, and the GCC compiler.
|
||||
|
||||
|
||||
.. c:macro:: MPS_PF_FRI3GC
|
||||
.. c:macro:: MPS_PF_FRI3LL
|
||||
|
||||
A :term:`C` preprocessor macro that indicates, if defined, that
|
||||
the :term:`platform` consists of the FreeBSD operating system, the
|
||||
|
|
@ -158,6 +151,13 @@ Platform interface
|
|||
|
||||
.. c:macro:: MPS_PF_FRI6GC
|
||||
|
||||
A :term:`C` preprocessor macro that indicates, if defined, that
|
||||
the :term:`platform` consists of the FreeBSD operating system, the
|
||||
x86-64 processor architecture, and the GCC compiler.
|
||||
|
||||
|
||||
.. c:macro:: MPS_PF_FRI6LL
|
||||
|
||||
A :term:`C` preprocessor macro that indicates, if defined, that
|
||||
the :term:`platform` consists of the FreeBSD operating system, the
|
||||
x86-64 processor architecture, and the Clang/LLVM compiler.
|
||||
|
|
@ -220,6 +220,13 @@ Platform interface
|
|||
IA-32 processor architecture, and the Clang/LLVM compiler.
|
||||
|
||||
|
||||
.. c:macro:: MPS_PF_XCI6GC
|
||||
|
||||
A :term:`C` preprocessor macro that indicates, if defined, that
|
||||
the :term:`platform` consists of the OS X operating system, the
|
||||
x86-64 processor architecture, and the GCC compiler.
|
||||
|
||||
|
||||
.. c:macro:: MPS_PF_XCI6LL
|
||||
|
||||
A :term:`C` preprocessor macro that indicates, if defined, that
|
||||
|
|
@ -373,6 +380,7 @@ Platform Status
|
|||
``w3ppmv`` *Not supported*
|
||||
``xci3gc`` *Not supported*
|
||||
``xci3ll`` Supported
|
||||
``xci6gc`` *Not supported*
|
||||
``xci6ll`` Supported
|
||||
``xcppgc`` *Not supported*
|
||||
========== =======================
|
||||
|
|
|
|||
|
|
@ -468,8 +468,8 @@ Library module
|
|||
|
||||
A :term:`plinth` function to supply a default value for the
|
||||
:term:`telemetry filter` from the environment. See
|
||||
:c:func:`mps_telemetry_control` for more information on the
|
||||
significant of the value.
|
||||
:envvar:`MPS_TELEMETRY_CONTROL` for more information on the
|
||||
significance of the value.
|
||||
|
||||
Returns the default value of the telemetry filter, as derived from
|
||||
the environment. It is recommended that the environment be
|
||||
|
|
|
|||
|
|
@ -66,9 +66,8 @@ usable.
|
|||
|
||||
There is a generic implementation in ``protan.c``, which can't
|
||||
provide memory protection, so it forces memory to be scanned until
|
||||
that there is no further need to protect it. This means it can't
|
||||
support incremental collection, and has no control over pause
|
||||
times.
|
||||
there is no further need to protect it. This means it can't support
|
||||
incremental collection, and has no control over pause times.
|
||||
|
||||
#. The **protection mutator context** module figures out what the
|
||||
:term:`mutator` was doing when it caused a :term:`protection
|
||||
|
|
|
|||
64
mps/manual/source/topic/security.rst
Normal file
64
mps/manual/source/topic/security.rst
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
.. index::
|
||||
single: security issues
|
||||
|
||||
.. _topic-security:
|
||||
|
||||
Security issues
|
||||
===============
|
||||
|
||||
This chapter describes security issues that may be present when using
|
||||
the MPS.
|
||||
|
||||
|
||||
.. index::
|
||||
pair: security issues; predictable address space layout
|
||||
single: address space; predictable layout
|
||||
|
||||
Predictable address space layout
|
||||
--------------------------------
|
||||
|
||||
The MPS acquires :term:`address space` using the operating system's
|
||||
:term:`virtual memory` interface (specifically, :c:func:`mmap` on Unix
|
||||
platforms, and :c:func:`VirtualAlloc` on Windows). None of the
|
||||
supported platforms randomize the allocated regions of address space,
|
||||
which means that the :term:`addresses` of :term:`blocks` allocated by
|
||||
the MPS are predictable: a :term:`client program` that makes an
|
||||
identical series of calls to the MPS gets an identical series of
|
||||
addresses back.
|
||||
|
||||
This means that if a program using the MPS has a buffer overflow, the
|
||||
overflow is more easily exploitable by an attacker than if the program
|
||||
had used :c:func:`malloc` (which has some randomization of the
|
||||
allocated addresses), because it is easier for an attacker to
|
||||
determine the address of allocated structures.
|
||||
|
||||
There is currently no workaround for this issue. If this affects you,
|
||||
please :ref:`contact us <contact>`.
|
||||
|
||||
|
||||
.. index::
|
||||
pair: security issues; telemetry
|
||||
|
||||
Telemetry
|
||||
---------
|
||||
|
||||
In its :term:`hot` and :term:`cool` varieties, the MPS contains a
|
||||
:term:`telemetry system` which can be configured to record a stream of
|
||||
events for later analysis and debugging. When using the default
|
||||
:term:`plinth`, the behaviour of the telemetry system is under the
|
||||
control of the environment variable :envvar:`MPS_TELEMETRY_CONTROL`,
|
||||
and the telemetry stream is written to the file named by the
|
||||
environment variable :envvar:`MPS_TELEMETRY_FILENAME`.
|
||||
|
||||
This means that an attacker who can set arbitrary environment
|
||||
variables when running a program that uses the MPS can cause that
|
||||
program to write a telemetry stream to an arbitrary file. This
|
||||
behaviour might be unexpected, and might enable a data overwriting
|
||||
attack, or a denial-of-service attack, since telemetry streams are
|
||||
typically very large.
|
||||
|
||||
If this is an issue for your program, then you can modify or replace
|
||||
the :ref:`topic-plinth-io` in the :term:`plinth` so that it meets your
|
||||
requirements, or distribute the :term:`rash` variety of the MPS, which
|
||||
omits the :term:`telemetry system` entirely, and use the other
|
||||
varieties only for development and testing.
|
||||
|
|
@ -491,9 +491,10 @@ used in queries, for example:
|
|||
.. note::
|
||||
|
||||
If the ``User`` event category is not turned on in the
|
||||
:term:`telemetry filter` (via :c:func:`mps_telemetry_control`)
|
||||
then the string is not sent to the telemetry stream. A label
|
||||
is still returned in this case, but it is useless.
|
||||
:term:`telemetry filter` (via :c:func:`mps_telemetry_set` or
|
||||
:envvar:`MPS_TELEMETRY_CONTROL`) then the string is not sent
|
||||
to the telemetry stream. A label is still returned in this
|
||||
case, but it is useless.
|
||||
|
||||
|
||||
.. c:function:: void mps_telemetry_label(mps_addr_t addr, mps_label_t label)
|
||||
|
|
@ -512,8 +513,9 @@ used in queries, for example:
|
|||
.. note::
|
||||
|
||||
If the ``User`` event category is not turned on in the
|
||||
:term:`telemetry filter` (via :c:func:`mps_telemetry_control`)
|
||||
then calling this function has no effect.
|
||||
:term:`telemetry filter` (via :c:func:`mps_telemetry_set` or
|
||||
:envvar:`MPS_TELEMETRY_CONTROL`) then calling this function
|
||||
has no effect.
|
||||
|
||||
|
||||
.. index::
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@ access that memory. This means that threads must be registered with
|
|||
the MPS by calling :c:func:`mps_thread_reg` (and thread roots created;
|
||||
see :ref:`topic-root-thread`).
|
||||
|
||||
For simplicity, we recommend that a thread must be registered with an
|
||||
:term:`arena` if:
|
||||
A thread must be registered with an :term:`arena` if:
|
||||
|
||||
* its :term:`control stack` and :term:`registers` form a root (this is
|
||||
enforced by :c:func:`mps_root_create_thread`); or
|
||||
|
|
@ -70,17 +69,30 @@ Signal and exception handling issues
|
|||
|
||||
.. warning::
|
||||
|
||||
On Unix platforms (except OS X), the MPS suspends and resumes
|
||||
threads by sending them signals. There's a shortage of available
|
||||
signals that aren't already dedicated to other purposes (for
|
||||
example, ValGrind uses ``SIGUSR1`` and ``SIGUSR2``), so the MPS uses
|
||||
``SIGXCPU`` and ``SIGXFSZ``. This means that programs must not mask
|
||||
these two signals.
|
||||
On Linux and FreeBSD, the MPS suspends and resumes threads by
|
||||
sending them signals. There's a shortage of available signals that
|
||||
aren't already dedicated to other purposes (for example, ValGrind
|
||||
uses ``SIGUSR1`` and ``SIGUSR2``), so the MPS uses ``SIGXCPU`` and
|
||||
``SIGXFSZ``. This means that programs must not mask or handle
|
||||
either of these signals.
|
||||
|
||||
If your program needs to handle these signals, then it must
|
||||
co-operate with the MPS. At present, there's no documented
|
||||
mechanism for co-operating: if you are in this situation, please
|
||||
:ref:`contact us <contact>`.
|
||||
If your program needs to mask or handle either of these signals,
|
||||
then you can configure the MPS to use another pair of signals of
|
||||
your choosing, by defining these preprocessor constants:
|
||||
|
||||
.. c:macro:: CONFIG_PTHREADEXT_SIGSUSPEND
|
||||
|
||||
If this preprocessor constant is defined, its definition names
|
||||
the signal used to suspend a thread. For example::
|
||||
|
||||
cc -DCONFIG_PTHREADEXT_SIGSUSPEND=SIGUSR1 -c mps.c
|
||||
|
||||
.. c:macro:: CONFIG_PTHREADEXT_SIGRESUME
|
||||
|
||||
If this preprocessor constant is defined, its definition names
|
||||
the signal used to resume a thread. For example::
|
||||
|
||||
cc -DCONFIG_PTHREADEXT_SIGSUSPEND=SIGUSR2 -c mps.c
|
||||
|
||||
.. warning::
|
||||
|
||||
|
|
|
|||
|
|
@ -43,3 +43,41 @@ From the test directory, build mpslib.a using the Xcode project::
|
|||
perl test/qa -i ../code -l ../code/xc/Debug/libmps.a run function/232.c
|
||||
|
||||
etc. See "Testing on Unix" above.
|
||||
|
||||
|
||||
Testing on Windows
|
||||
------------------
|
||||
|
||||
In a Cygwin shell, from the test directory::
|
||||
|
||||
PLATFORM=w3i6mv # substitute your platform
|
||||
VARIETY=cool # or hot
|
||||
CODE=../code # code directory of the branch you are testing
|
||||
pushd $CODE
|
||||
nmake /f $PLATFORM.nmk VARIETY=$VARIETY $PLATFORM/$VARIETY/mps.obj
|
||||
popd
|
||||
export LANG=C # avoid locale warnings from Perl.
|
||||
alias qa="perl test/qa -i $CODE -l $CODE/$PLATFORM/$VARIETY/mps.obj"
|
||||
qa clib
|
||||
qa run function/5.c
|
||||
qa runset testsets/passing
|
||||
|
||||
The runset command can result in this error::
|
||||
|
||||
LINK : fatal error LNK1168: cannot open test/obj/nt_AMD64__pc/tmp_test.exe for writing
|
||||
|
||||
You may be able to avoid this by running "View Local Services" from
|
||||
the Windows Control Panel, double-clicking the "Application
|
||||
Experience" service, and switching "Startup type" to "Automatic". See
|
||||
the documentation for LNK1168_.
|
||||
|
||||
.. _LNK1168: https://msdn.microsoft.com/en-us/library/hhbdtt6d.aspx
|
||||
|
||||
At present, the easiest way to debug a test case is to edit
|
||||
test/test/script/platform and set::
|
||||
|
||||
$comwrap = "vsjitdebugger \"";
|
||||
|
||||
But see job004020_.
|
||||
|
||||
.. _job004020: https://www.ravenbrook.com/project/mps/issue/job004020/
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ static void test(void) {
|
|||
cdie(mps_pool_create(&pool, arena, mps_class_mv(),
|
||||
1024*32, 1024*16, 1024*256), "pool");
|
||||
|
||||
cdie(mps_alloc(&q, pool, (size_t) -100 * mmqaArenaSIZE), "alloc");
|
||||
cdie(mps_alloc(&q, pool, ((size_t)-1) - 100 * mmqaArenaSIZE), "alloc");
|
||||
|
||||
mps_pool_destroy(pool);
|
||||
mps_arena_destroy(arena);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static void test(void)
|
|||
|
||||
/* cdie(mps_arena_create(&arena, mps_arena_class_vm(), mmqaArenaSIZE), "create arena");
|
||||
*/
|
||||
arena=malloc(64);
|
||||
arena=malloc(4096);
|
||||
|
||||
cdie(
|
||||
mps_pool_create(&pool, arena, mps_class_mv(),
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ TEST_HEADER
|
|||
link = testlib.o
|
||||
OUTPUT_SPEC
|
||||
assert = true
|
||||
assertfile P= poollo.c
|
||||
assertcond = FormatArena(pool->format) == arena
|
||||
assertfile P= poolabs.c
|
||||
assertcond = FormatArena(format) == arena
|
||||
END_HEADER
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ static void test(void)
|
|||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
arena = malloc(64);
|
||||
arena = malloc(4096);
|
||||
mps_arena_destroy(arena);
|
||||
comment("Destroy arena.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ static void test(void)
|
|||
|
||||
cdie(mps_ap_create(&ap, pool), "create ap");
|
||||
|
||||
cdie(mps_reserve(&obj, ap, 152), "reserve");
|
||||
(void)mps_commit(ap, &obj, 152);
|
||||
cdie(mps_reserve(&obj, ap, 256), "reserve");
|
||||
(void)mps_commit(ap, &obj, 256);
|
||||
|
||||
mps_free(pool, obj, 152);
|
||||
mps_free(pool, obj, 256);
|
||||
comment("Freed.");
|
||||
|
||||
mps_free(pool, obj, 152);
|
||||
mps_free(pool, obj, 256);
|
||||
comment("Freed again.");
|
||||
|
||||
mps_pool_destroy(pool);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ TEST_HEADER
|
|||
OUTPUT_SPEC
|
||||
assert = true
|
||||
assertfile P= ld.c
|
||||
assertcond = ld->_epoch <= arena->epoch
|
||||
assertcond = ld->_epoch <= ArenaHistory(arena)->epoch
|
||||
END_HEADER
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ TEST_HEADER
|
|||
OUTPUT_SPEC
|
||||
assert = true
|
||||
assertfile P= ld.c
|
||||
assertcond = ld->_epoch <= arena->epoch
|
||||
assertcond = ld->_epoch <= history->epoch
|
||||
END_HEADER
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ static void test(void)
|
|||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
|
||||
arena=malloc(64);
|
||||
arena=malloc(4096);
|
||||
|
||||
cdie(mps_fmt_create_k(&format, arena, mps_args_none), "create format");
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ static void test(void)
|
|||
mps_fmt_t format;
|
||||
mps_ap_t apamc, apawl;
|
||||
|
||||
unsigned int i, c;
|
||||
mps_word_t i, c;
|
||||
|
||||
cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (60ul*1024*1024)), "create arena");
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ static void do_test(size_t extendBy, size_t avgSize, size_t align,
|
|||
mps_addr_t p;
|
||||
unsigned int i;
|
||||
unsigned long nLargeObjects = 0, nSmallObjects = 0;
|
||||
unsigned long largeObjectSize, smallObjectSize;
|
||||
size_t largeObjectSize, smallObjectSize;
|
||||
|
||||
largeObjectSize = extendBy;
|
||||
smallObjectSize = align;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
|
||||
static void dt(int kind,
|
||||
size_t extendBy, size_t avgSize, size_t align,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
int i, hd;
|
||||
|
|
@ -114,11 +114,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %p (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)",
|
||||
"corrupt at %p (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
commentif(comments, "Free %i at %x, size %x", hd,
|
||||
queue[hd].addr, queue[hd].size);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
|
|
@ -147,16 +147,16 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
int symm;
|
||||
size_t comlimit;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
|
||||
static void dt(int kind,
|
||||
size_t extendBy, size_t avgSize, size_t align,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
int i, hd;
|
||||
|
|
@ -107,11 +107,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %x (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)",
|
||||
"corrupt at %x (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
commentif(comments, "Free %i at %x, size %x", hd,
|
||||
queue[hd].addr, queue[hd].size);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
|
|
@ -140,16 +140,16 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
int symm;
|
||||
size_t comlimit;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static void test(void)
|
|||
mps_pool_t pool;
|
||||
mps_thr_t thread;
|
||||
|
||||
unsigned long com0, com1, com2;
|
||||
size_t com0, com1, com2;
|
||||
|
||||
/* create a VM arena of 40MB with commit limit of 100MB, i.e. let the
|
||||
arena do the limiting. */
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static void test(void)
|
|||
mps_pool_t poolhi, poollo;
|
||||
mps_thr_t thread;
|
||||
|
||||
unsigned long com0, com1;
|
||||
size_t com0, com1;
|
||||
|
||||
/* create a VM arena of 40MB */
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ TEST_HEADER
|
|||
language = c
|
||||
link = testlib.o rankfmt.o
|
||||
harness = 2.1
|
||||
parameters = EXTEND=65536 AVGSIZE=32 BIGSIZE=(5*1024*1024);
|
||||
parameters = EXTEND=65536 AVGSIZE=32 BIGSIZE=5*1024*1024
|
||||
OUTPUT_SPEC
|
||||
completed = yes
|
||||
failed = no
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
|
||||
static void dt(int kind,
|
||||
size_t extendBy, size_t avgSize, size_t maxSize,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
int i, hd;
|
||||
|
|
@ -101,10 +101,10 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %x (%s: %x, %x, %x, %x, %x, %i, %i)",
|
||||
"corrupt at %x (%s: %x, %x, %x, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) maxSize,
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
}
|
||||
size = ranrange(mins, maxs);
|
||||
|
|
@ -126,15 +126,15 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) maxSize,
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
|
||||
cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*50)), "create arena");
|
||||
cdie(mps_thread_reg(&thread, arena), "register thread");
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static void setobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
static mps_res_t mvt_alloc(mps_addr_t *ref, mps_ap_t ap, size_t size) {
|
||||
mps_res_t res;
|
||||
|
||||
size = ((size+7)/8)*8;
|
||||
size = (size + MPS_PF_ALIGN - 1) & ~(MPS_PF_ALIGN - 1);
|
||||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, *ref, ap, size);
|
||||
|
|
@ -71,7 +71,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
static void dt(int kind,
|
||||
size_t minSize, size_t avgSize, size_t maxSize,
|
||||
mps_word_t depth, mps_word_t fragLimit,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
mps_ap_t ap;
|
||||
|
|
@ -118,11 +118,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %x (%s: %x, %x, %x, %i, %i, %x, %x, %i, %i)",
|
||||
"corrupt at %x (%s: %x, %x, %x, %i, %i, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize,
|
||||
(int) depth, (int) fragLimit,
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
}
|
||||
size = ranrange(mins, maxs);
|
||||
|
|
@ -145,16 +145,16 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %i, %i, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %i, %i, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize,
|
||||
(int) depth, (int) fragLimit,
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
mps_word_t dep, frag;
|
||||
|
||||
cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*100)), "create arena");
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static void setobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
static mps_res_t mvt_alloc(mps_addr_t *ref, mps_ap_t ap, size_t size) {
|
||||
mps_res_t res;
|
||||
|
||||
size = ((size+7)/8)*8;
|
||||
size = (size + MPS_PF_ALIGN - 1) & ~ (MPS_PF_ALIGN - 1);
|
||||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, *ref, ap, size);
|
||||
|
|
@ -71,7 +71,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
static void dt(int kind,
|
||||
size_t minSize, size_t avgSize, size_t maxSize,
|
||||
mps_word_t depth, mps_word_t fragLimit,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
mps_ap_t ap;
|
||||
|
|
@ -118,11 +118,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %x (%s: %x, %x, %x, %i, %i, %x, %x, %i, %i)",
|
||||
"corrupt at %x (%s: %x, %x, %x, %i, %i, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize,
|
||||
(int) depth, (int) fragLimit,
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
}
|
||||
size = ranrange(mins, maxs);
|
||||
|
|
@ -145,16 +145,16 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %i, %i, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %i, %i, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize,
|
||||
(int) depth, (int) fragLimit,
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
mps_word_t dep, frag;
|
||||
|
||||
cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*100)), "create arena");
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static void setobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
static mps_res_t mvt_alloc(mps_addr_t *ref, mps_ap_t ap, size_t size) {
|
||||
mps_res_t res;
|
||||
|
||||
size = ((size+7)/8)*8;
|
||||
size = (size + MPS_PF_ALIGN - 1) & ~ (MPS_PF_ALIGN - 1);
|
||||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, *ref, ap, size);
|
||||
|
|
@ -71,7 +71,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
static void dt(int kind,
|
||||
size_t minSize, size_t avgSize, size_t maxSize,
|
||||
mps_word_t depth, mps_word_t fragLimit,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
mps_ap_t ap;
|
||||
|
|
@ -118,11 +118,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %x (%s: %x, %x, %x, %i, %i, %x, %x, %i, %i)",
|
||||
"corrupt at %x (%s: %x, %x, %x, %i, %i, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize,
|
||||
(int) depth, (int) fragLimit,
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
}
|
||||
size = ranrange(mins, maxs);
|
||||
|
|
@ -145,16 +145,16 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %i, %i, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %i, %i, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize,
|
||||
(int) depth, (int) fragLimit,
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
mps_word_t dep, frag;
|
||||
|
||||
cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*100)), "create arena");
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
|
||||
static void dt(int kind,
|
||||
size_t extendBy, size_t avgSize, size_t align,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
int i, hd;
|
||||
|
|
@ -103,11 +103,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %p (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)",
|
||||
"corrupt at %p (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
}
|
||||
size = ranrange(mins, maxs);
|
||||
|
|
@ -129,18 +129,18 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t extendBy, avgSize, maxSize;
|
||||
size_t avgSize;
|
||||
size_t align = sizeof(void*);
|
||||
size_t minSize = sizeof(int);
|
||||
unsigned long extendBy, minSize = sizeof(int), maxSize;
|
||||
int i, j, kind;
|
||||
|
||||
cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*50)), "create arena");
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val)
|
|||
|
||||
static void dt(int kind,
|
||||
size_t extendBy, size_t avgSize, size_t align,
|
||||
size_t mins, size_t maxs, int number, int iter)
|
||||
unsigned long mins, unsigned long maxs, int number, int iter)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
int i, hd;
|
||||
|
|
@ -107,11 +107,11 @@ static void dt(int kind,
|
|||
if (queue[hd].addr != NULL)
|
||||
{
|
||||
asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)),
|
||||
"corrupt at %x (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)",
|
||||
"corrupt at %x (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)",
|
||||
queue[hd].addr,
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter);
|
||||
mins, maxs, number, iter);
|
||||
commentif(comments, "Free %i at %x, size %x", hd,
|
||||
queue[hd].addr, queue[hd].size);
|
||||
mps_free(pool, queue[hd].addr, queue[hd].size);
|
||||
|
|
@ -140,16 +140,16 @@ static void dt(int kind,
|
|||
time1=clock();
|
||||
secs=(time1-time0)/(double)CLOCKS_PER_SEC;
|
||||
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s",
|
||||
comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s",
|
||||
tdesc[kind], (int) extendBy, (int) avgSize, (int) align,
|
||||
slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f',
|
||||
(int) mins, (int) maxs, number, iter, secs);
|
||||
mins, maxs, number, iter, secs);
|
||||
}
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
size_t mins;
|
||||
unsigned long mins;
|
||||
int symm;
|
||||
size_t comlimit;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ static void test(void) {
|
|||
|
||||
for (p=0; p<2000; p++) {
|
||||
die(mps_alloc(&q, pool, 1024*1024), "alloc");
|
||||
q = (mps_addr_t) ((char *) q + 8);
|
||||
mps_free(pool, q, 256*1024-8);
|
||||
q = (mps_addr_t) ((char *) q + MPS_PF_ALIGN);
|
||||
mps_free(pool, q, 256*1024-MPS_PF_ALIGN);
|
||||
report("promise", "%i", p);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ static void test(void) {
|
|||
}
|
||||
}
|
||||
if(mps_message_get(&message, arena, mps_message_type_gc())) {
|
||||
unsigned long live, condemned, notCondemned;
|
||||
size_t live, condemned, notCondemned;
|
||||
live = mps_message_gc_live_size(arena, message);
|
||||
condemned = mps_message_gc_condemned_size(arena, message);
|
||||
notCondemned =
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ static void test(void) {
|
|||
for (p=0; p<2000; p++) {
|
||||
report("promise", "%i", p);
|
||||
die(mps_alloc(&r, pool, 1024*1024), "alloc");
|
||||
mps_free(pool, q, 256*1024-8);
|
||||
q = (mps_addr_t) ((char *) r + 8);
|
||||
mps_free(pool, q, 256*1024-MPS_PF_ALIGN);
|
||||
q = (mps_addr_t) ((char *) r + MPS_PF_ALIGN);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ static void test(void) {
|
|||
}
|
||||
}
|
||||
if(mps_message_get(&message, arena, mps_message_type_gc())) {
|
||||
unsigned long live, condemned, notCondemned;
|
||||
size_t live, condemned, notCondemned;
|
||||
live = mps_message_gc_live_size(arena, message);
|
||||
condemned = mps_message_gc_condemned_size(arena, message);
|
||||
notCondemned = mps_message_gc_not_condemned_size(arena, message);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ static void mergelds(int merge) {
|
|||
}
|
||||
}
|
||||
|
||||
static void blat(mps_ap_t apamc, int percent) {
|
||||
static void blat(mps_ap_t apamc, unsigned percent) {
|
||||
int i;
|
||||
for (i=0; i < MAXLDS; i++) {
|
||||
if (ranint(100) < percent) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
TEST_HEADER
|
||||
id = $Id: //info.ravenbrook.com/project/mps/branch/2015-08-11/compact/test/function/229.c#1 $
|
||||
id = $Id$
|
||||
summary = test arena extension and compaction
|
||||
language = c
|
||||
link = testlib.o
|
||||
parameters = SIZE=1024*1024 ITERATIONS=100
|
||||
parameters = CHUNKSIZE=1024*1024 ITERATIONS=100
|
||||
END_HEADER
|
||||
*/
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ static void test(void)
|
|||
unsigned i;
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, SIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, CHUNKSIZE);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
|
|
@ -37,12 +37,12 @@ static void test(void)
|
|||
check_chunks(arena, 1);
|
||||
|
||||
for (i = 0; i < ITERATIONS; ++i) {
|
||||
die(mps_alloc(&block[i], pool, SIZE), "mps_alloc");
|
||||
die(mps_alloc(&block[i], pool, CHUNKSIZE), "mps_alloc");
|
||||
check_chunks(arena, i + 2);
|
||||
}
|
||||
|
||||
for (i = ITERATIONS; i > 0; --i) {
|
||||
mps_free(pool, block[i - 1], SIZE);
|
||||
mps_free(pool, block[i - 1], CHUNKSIZE);
|
||||
mps_arena_collect(arena); /* ensure ArenaCompact is called */
|
||||
check_chunks(arena, i);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue