mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-05-04 20:31:48 -07:00
Merge mps/branch/2014-04-08/align into the master sources.
Copied from Perforce Change: 186481 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
db08f01684
31 changed files with 580 additions and 353 deletions
|
|
@ -105,7 +105,7 @@ static mps_addr_t make(void)
|
|||
/* test -- the actual stress test */
|
||||
|
||||
static mps_pool_debug_option_s freecheckOptions =
|
||||
{ NULL, 0, (const void *)"Dead", 4 };
|
||||
{ NULL, 0, "Dead", 4 };
|
||||
|
||||
static void test_pool(mps_class_t pool_class, mps_arg_s args[],
|
||||
mps_bool_t haveAmbiguous)
|
||||
|
|
|
|||
|
|
@ -43,28 +43,25 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
|||
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_class_t class, size_t (*size)(size_t i),
|
||||
mps_arena_t arena, ...)
|
||||
static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
||||
size_t (*size)(size_t i, mps_align_t align),
|
||||
const char *name, mps_class_t class, mps_arg_s args[])
|
||||
{
|
||||
mps_res_t res = MPS_RES_OK;
|
||||
mps_pool_t pool;
|
||||
mps_ap_t ap;
|
||||
va_list arg;
|
||||
size_t i, k;
|
||||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
|
||||
va_start(arg, arena);
|
||||
res = mps_pool_create_v(&pool, arena, class, arg);
|
||||
va_end(arg);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
printf("stress %s\n", name);
|
||||
|
||||
die(mps_pool_create_k(&pool, arena, class, args), "pool_create");
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate");
|
||||
|
||||
/* allocate a load of objects */
|
||||
for (i=0; i<testSetSIZE; ++i) {
|
||||
ss[i] = (*size)(i);
|
||||
ss[i] = (*size)(i, align);
|
||||
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
|
|
@ -96,7 +93,7 @@ static mps_res_t stress(mps_class_t class, size_t (*size)(size_t i),
|
|||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
ss[i] = (*size)(i);
|
||||
ss[i] = (*size)(i, align);
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
|
|
@ -111,63 +108,72 @@ allocFail:
|
|||
}
|
||||
|
||||
|
||||
/* randomSizeAligned -- produce sizes both large and small,
|
||||
* aligned by platform alignment */
|
||||
/* randomSizeAligned -- produce sizes both large and small, aligned to
|
||||
* align.
|
||||
*/
|
||||
|
||||
static size_t randomSizeAligned(size_t i)
|
||||
static size_t randomSizeAligned(size_t i, mps_align_t align)
|
||||
{
|
||||
size_t maxSize = 2 * 160 * 0x2000;
|
||||
/* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */
|
||||
return alignUp(rnd() % max((maxSize >> (i / 10)), 2) + 1, MPS_PF_ALIGN);
|
||||
return alignUp(rnd() % max((maxSize >> (i / 10)), 2) + 1, align);
|
||||
}
|
||||
|
||||
|
||||
static mps_pool_debug_option_s bothOptions = {
|
||||
/* .fence_template = */ (const void *)"postpostpostpost",
|
||||
/* .fence_size = */ MPS_PF_ALIGN,
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .fence_template = */ "post",
|
||||
/* .fence_size = */ 4,
|
||||
/* .free_template = */ "DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions = {
|
||||
/* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_size = */ 16,
|
||||
/* .fence_template = */ "123456789abcdef",
|
||||
/* .fence_size = */ 15,
|
||||
/* .free_template = */ NULL,
|
||||
/* .free_size = */ 0
|
||||
};
|
||||
|
||||
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
||||
{
|
||||
mps_res_t res;
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
die(stress(arena, align, randomSizeAligned, "MVFF", mps_class_mvff(), args),
|
||||
"stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging APs, */
|
||||
/* yet (MV Debug works here, because it fakes it through PoolAlloc). */
|
||||
printf("MVFF\n");
|
||||
res = stress(mps_class_mvff(), randomSizeAligned, arena,
|
||||
(size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MVFF");
|
||||
|
||||
printf("MV debug\n");
|
||||
res = stress(mps_class_mv_debug(), randomSizeAligned, arena,
|
||||
options, (size_t)65536, (size_t)32, (size_t)65536);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MV debug");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, align, randomSizeAligned, "MV", mps_class_mv(), args),
|
||||
"stress MV");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
printf("MV\n");
|
||||
res = stress(mps_class_mv(), randomSizeAligned, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)65536);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MV");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, align, randomSizeAligned, "MV debug",
|
||||
mps_class_mv_debug(), args),
|
||||
"stress MV debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
printf("MVT\n");
|
||||
res = stress(mps_class_mvt(), randomSizeAligned, arena,
|
||||
(size_t)8, (size_t)32, (size_t)65536, (mps_word_t)4,
|
||||
(mps_word_t)50);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MVT");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, align, randomSizeAligned, "MVT", mps_class_mvt(), args),
|
||||
"stress MVT");
|
||||
} MPS_ARGS_END(args);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -359,6 +359,7 @@
|
|||
|
||||
/* Pool MV Configuration -- see <code/poolmv.c> */
|
||||
|
||||
#define MV_ALIGN_DEFAULT MPS_PF_ALIGN
|
||||
#define MV_EXTEND_BY_DEFAULT ((Size)65536)
|
||||
#define MV_AVG_SIZE_DEFAULT ((Size)32)
|
||||
#define MV_MAX_SIZE_DEFAULT ((Size)65536)
|
||||
|
|
|
|||
|
|
@ -123,10 +123,14 @@ Bool PoolDebugOptionsCheck(PoolDebugOptions opt)
|
|||
|
||||
ARG_DEFINE_KEY(pool_debug_options, PoolDebugOptions);
|
||||
|
||||
static PoolDebugOptionsStruct debugPoolOptionsDefault = {
|
||||
"POST", 4, "DEAD", 4,
|
||||
};
|
||||
|
||||
static Res DebugPoolInit(Pool pool, ArgList args)
|
||||
{
|
||||
Res res;
|
||||
PoolDebugOptions options;
|
||||
PoolDebugOptions options = &debugPoolOptionsDefault;
|
||||
PoolDebugMixin debug;
|
||||
TagInitMethod tagInit;
|
||||
Size tagSize;
|
||||
|
|
@ -134,10 +138,8 @@ static Res DebugPoolInit(Pool pool, ArgList args)
|
|||
|
||||
AVERT(Pool, pool);
|
||||
|
||||
/* TODO: Split this structure into separate keyword arguments,
|
||||
now that we can support them. */
|
||||
ArgRequire(&arg, args, MPS_KEY_POOL_DEBUG_OPTIONS);
|
||||
options = (PoolDebugOptions)arg.val.pool_debug_options;
|
||||
if (ArgPick(&arg, args, MPS_KEY_POOL_DEBUG_OPTIONS))
|
||||
options = (PoolDebugOptions)arg.val.pool_debug_options;
|
||||
|
||||
AVERT(PoolDebugOptions, options);
|
||||
|
||||
|
|
@ -158,10 +160,6 @@ static Res DebugPoolInit(Pool pool, ArgList args)
|
|||
/* into Addr memory, to avoid breaking <design/type/#addr.use>. */
|
||||
debug->fenceSize = options->fenceSize;
|
||||
if (debug->fenceSize != 0) {
|
||||
if (debug->fenceSize % PoolAlignment(pool) != 0) {
|
||||
res = ResPARAM;
|
||||
goto alignFail;
|
||||
}
|
||||
/* Fenceposting turns on tagging */
|
||||
if (tagInit == NULL) {
|
||||
tagSize = 0;
|
||||
|
|
@ -176,10 +174,6 @@ static Res DebugPoolInit(Pool pool, ArgList args)
|
|||
/* into Addr memory, to avoid breaking <design/type#addr.use>. */
|
||||
debug->freeSize = options->freeSize;
|
||||
if (debug->freeSize != 0) {
|
||||
if (PoolAlignment(pool) % debug->freeSize != 0) {
|
||||
res = ResPARAM;
|
||||
goto alignFail;
|
||||
}
|
||||
debug->freeTemplate = options->freeTemplate;
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +202,6 @@ static Res DebugPoolInit(Pool pool, ArgList args)
|
|||
return ResOK;
|
||||
|
||||
tagFail:
|
||||
alignFail:
|
||||
SuperclassOfPool(pool)->finish(pool);
|
||||
AVER(res != ResOK);
|
||||
return res;
|
||||
|
|
@ -234,39 +227,150 @@ static void DebugPoolFinish(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* freeSplat -- splat free block with splat pattern
|
||||
/* patternIterate -- call visitor for occurrences of pattern between
|
||||
* base and limit
|
||||
*
|
||||
* If base is in a segment, the whole block has to be in it.
|
||||
* pattern is an arbitrary pattern that's size bytes long.
|
||||
*
|
||||
* Imagine that the entirety of memory were covered by contiguous
|
||||
* copies of pattern starting at address 0. Then call visitor for each
|
||||
* copy (or part) of pattern that lies between base and limit. In each
|
||||
* call, target is the address of the copy or part (where base <=
|
||||
* target < limit); source is the corresponding byte of the pattern
|
||||
* (where pattern <= source < pattern + size); and size is the length
|
||||
* of the copy or part.
|
||||
*/
|
||||
|
||||
typedef Bool (*patternVisitor)(Addr target, ReadonlyAddr source, Size size);
|
||||
|
||||
static Bool patternIterate(ReadonlyAddr pattern, Size size,
|
||||
Addr base, Addr limit, patternVisitor visitor)
|
||||
{
|
||||
Addr p;
|
||||
|
||||
AVER(pattern != NULL);
|
||||
AVER(0 < size);
|
||||
AVER(base != NULL);
|
||||
AVER(base <= limit);
|
||||
|
||||
p = base;
|
||||
while (p < limit) {
|
||||
Addr end = AddrAdd(p, size);
|
||||
Addr rounded = AddrRoundUp(p, size);
|
||||
Size offset = (Word)p % size;
|
||||
if (end < p || rounded < p) {
|
||||
/* Address range overflow */
|
||||
break;
|
||||
} else if (p == rounded && end <= limit) {
|
||||
/* Room for a whole copy */
|
||||
if (!(*visitor)(p, pattern, size))
|
||||
return FALSE;
|
||||
p = end;
|
||||
} else if (p < rounded && rounded <= end && rounded <= limit) {
|
||||
/* Copy up to rounded */
|
||||
if (!(*visitor)(p, ReadonlyAddrAdd(pattern, offset),
|
||||
AddrOffset(p, rounded)))
|
||||
return FALSE;
|
||||
p = rounded;
|
||||
} else {
|
||||
/* Copy up to limit */
|
||||
AVER(limit <= end && (p == rounded || limit <= rounded));
|
||||
if (!(*visitor)(p, ReadonlyAddrAdd(pattern, offset),
|
||||
AddrOffset(p, limit)))
|
||||
return FALSE;
|
||||
p = limit;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* patternCopy -- copy pattern to fill a range
|
||||
*
|
||||
* Fill the range of addresses from base (inclusive) to limit
|
||||
* (exclusive) with copies of pattern (which is size bytes long).
|
||||
*/
|
||||
|
||||
static Bool patternCopyVisitor(Addr target, ReadonlyAddr source, Size size)
|
||||
{
|
||||
(void)AddrCopy(target, source, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void patternCopy(ReadonlyAddr pattern, Size size, Addr base, Addr limit)
|
||||
{
|
||||
(void)patternIterate(pattern, size, base, limit, patternCopyVisitor);
|
||||
}
|
||||
|
||||
|
||||
/* patternCheck -- check pattern against a range
|
||||
*
|
||||
* Compare the range of addresses from base (inclusive) to limit
|
||||
* (exclusive) with copies of pattern (which is size bytes long). The
|
||||
* copies of pattern must be arranged so that fresh copies start at
|
||||
* aligned addresses wherever possible.
|
||||
*/
|
||||
|
||||
static Bool patternCheckVisitor(Addr target, ReadonlyAddr source, Size size)
|
||||
{
|
||||
return AddrComp(target, source, size) == 0;
|
||||
}
|
||||
|
||||
static Bool patternCheck(ReadonlyAddr pattern, Size size, Addr base, Addr limit)
|
||||
{
|
||||
return patternIterate(pattern, size, base, limit, patternCheckVisitor);
|
||||
}
|
||||
|
||||
|
||||
/* debugPoolSegIterate -- iterate over a range of segments in an arena
|
||||
*
|
||||
* Expects to be called on a range corresponding to objects withing a
|
||||
* single pool.
|
||||
*
|
||||
* NOTE: This relies on pools consistently using segments
|
||||
* contiguously.
|
||||
*/
|
||||
|
||||
static void debugPoolSegIterate(Arena arena, Addr base, Addr limit,
|
||||
void (*visitor)(Arena, Seg))
|
||||
{
|
||||
Seg seg;
|
||||
|
||||
if (SegOfAddr(&seg, arena, base)) {
|
||||
do {
|
||||
base = SegLimit(seg);
|
||||
(*visitor)(arena, seg);
|
||||
} while (base < limit && SegOfAddr(&seg, arena, base));
|
||||
AVER(base >= limit); /* shouldn't run out of segments */
|
||||
}
|
||||
}
|
||||
|
||||
static void debugPoolShieldExpose(Arena arena, Seg seg)
|
||||
{
|
||||
ShieldExpose(arena, seg);
|
||||
}
|
||||
|
||||
static void debugPoolShieldCover(Arena arena, Seg seg)
|
||||
{
|
||||
ShieldCover(arena, seg);
|
||||
}
|
||||
|
||||
|
||||
/* freeSplat -- splat free block with splat pattern */
|
||||
|
||||
static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit)
|
||||
{
|
||||
Addr p, next;
|
||||
Size freeSize = debug->freeSize;
|
||||
Arena arena;
|
||||
Seg seg = NULL; /* suppress "may be used uninitialized" */
|
||||
Bool inSeg;
|
||||
|
||||
AVER(base < limit);
|
||||
|
||||
/* If the block is in a segment, make sure any shield is up. */
|
||||
/* If the block is in one or more segments, make sure the segments
|
||||
are exposed so that we can overwrite the block with the pattern. */
|
||||
arena = PoolArena(pool);
|
||||
inSeg = SegOfAddr(&seg, arena, base);
|
||||
if (inSeg) {
|
||||
AVER(limit <= SegLimit(seg));
|
||||
ShieldExpose(arena, seg);
|
||||
}
|
||||
/* Write as many copies of the template as fit in the block. */
|
||||
for (p = base, next = AddrAdd(p, freeSize);
|
||||
next <= limit && p < next /* watch out for overflow in next */;
|
||||
p = next, next = AddrAdd(next, freeSize))
|
||||
(void)AddrCopy(p, debug->freeTemplate, freeSize);
|
||||
/* Fill the tail of the block with a partial copy of the template. */
|
||||
if (next > limit || next < p)
|
||||
(void)AddrCopy(p, debug->freeTemplate, AddrOffset(p, limit));
|
||||
if (inSeg) {
|
||||
ShieldCover(arena, seg);
|
||||
}
|
||||
debugPoolSegIterate(arena, base, limit, debugPoolShieldExpose);
|
||||
patternCopy(debug->freeTemplate, debug->freeSize, base, limit);
|
||||
debugPoolSegIterate(arena, base, limit, debugPoolShieldCover);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -274,41 +378,17 @@ static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit)
|
|||
|
||||
static Bool freeCheck(PoolDebugMixin debug, Pool pool, Addr base, Addr limit)
|
||||
{
|
||||
Addr p, next;
|
||||
Size freeSize = debug->freeSize;
|
||||
Res res;
|
||||
Bool res;
|
||||
Arena arena;
|
||||
Seg seg = NULL; /* suppress "may be used uninitialized" */
|
||||
Bool inSeg;
|
||||
|
||||
AVER(base < limit);
|
||||
|
||||
/* If the block is in a segment, make sure any shield is up. */
|
||||
/* If the block is in one or more segments, make sure the segments
|
||||
are exposed so we can read the pattern. */
|
||||
arena = PoolArena(pool);
|
||||
inSeg = SegOfAddr(&seg, arena, base);
|
||||
if (inSeg) {
|
||||
AVER(limit <= SegLimit(seg));
|
||||
ShieldExpose(arena, seg);
|
||||
}
|
||||
/* Compare this to the AddrCopys in freeSplat. */
|
||||
/* Check the complete copies of the template in the block. */
|
||||
for (p = base, next = AddrAdd(p, freeSize);
|
||||
next <= limit && p < next /* watch out for overflow in next */;
|
||||
p = next, next = AddrAdd(next, freeSize))
|
||||
if (AddrComp(p, debug->freeTemplate, freeSize) != 0) {
|
||||
res = FALSE; goto done;
|
||||
}
|
||||
/* Check the partial copy of the template at the tail of the block. */
|
||||
if (next > limit || next < p)
|
||||
if (AddrComp(p, debug->freeTemplate, AddrOffset(p, limit)) != 0) {
|
||||
res = FALSE; goto done;
|
||||
}
|
||||
res = TRUE;
|
||||
|
||||
done:
|
||||
if (inSeg) {
|
||||
ShieldCover(arena, seg);
|
||||
}
|
||||
debugPoolSegIterate(arena, base, limit, debugPoolShieldExpose);
|
||||
res = patternCheck(debug->freeTemplate, debug->freeSize, base, limit);
|
||||
debugPoolSegIterate(arena, base, limit, debugPoolShieldCover);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -354,63 +434,75 @@ static void freeCheckFree(PoolDebugMixin debug,
|
|||
* start fp client object slop end fp
|
||||
*
|
||||
* slop is the extra allocation from rounding up the client request to
|
||||
* the pool's alignment. The fenceposting code does this, so there's a
|
||||
* better chance of the end fencepost being flush with the next object
|
||||
* (can't be guaranteed, since the underlying pool could have allocated
|
||||
* an even larger block). The alignment slop is filled from the
|
||||
* fencepost template as well (as much as fits, .fence.size guarantees
|
||||
* the template is larger).
|
||||
* the pool's alignment. The fenceposting code adds this slop so that
|
||||
* there's a better chance of the end fencepost being flush with the
|
||||
* next object (though it can't be guaranteed, since the underlying
|
||||
* pool could have allocated an even larger block). The alignment slop
|
||||
* is filled from the fencepost template as well.
|
||||
*
|
||||
* Keep in sync with fenceCheck.
|
||||
*/
|
||||
|
||||
static Res fenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
||||
Size size, Bool withReservoir)
|
||||
{
|
||||
Res res;
|
||||
Addr new, clientNew;
|
||||
Size alignedSize;
|
||||
Addr obj, startFence, clientNew, clientLimit, limit;
|
||||
Size alignedFenceSize, alignedSize;
|
||||
|
||||
AVER(aReturn != NULL);
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
AVERT(Pool, pool);
|
||||
|
||||
alignedFenceSize = SizeAlignUp(debug->fenceSize, PoolAlignment(pool));
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
res = freeCheckAlloc(&new, debug, pool, alignedSize + 2*debug->fenceSize,
|
||||
res = freeCheckAlloc(&obj, debug, pool,
|
||||
alignedSize + 2 * alignedFenceSize,
|
||||
withReservoir);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
clientNew = AddrAdd(new, debug->fenceSize);
|
||||
|
||||
startFence = obj;
|
||||
clientNew = AddrAdd(startFence, alignedFenceSize);
|
||||
clientLimit = AddrAdd(clientNew, size);
|
||||
limit = AddrAdd(clientNew, alignedSize + alignedFenceSize);
|
||||
|
||||
/* @@@@ shields? */
|
||||
/* start fencepost */
|
||||
(void)AddrCopy(new, debug->fenceTemplate, debug->fenceSize);
|
||||
/* alignment slop */
|
||||
(void)AddrCopy(AddrAdd(clientNew, size),
|
||||
debug->fenceTemplate, alignedSize - size);
|
||||
/* end fencepost */
|
||||
(void)AddrCopy(AddrAdd(clientNew, alignedSize),
|
||||
debug->fenceTemplate, debug->fenceSize);
|
||||
patternCopy(debug->fenceTemplate, debug->fenceSize, startFence, clientNew);
|
||||
patternCopy(debug->fenceTemplate, debug->fenceSize, clientLimit, limit);
|
||||
|
||||
*aReturn = clientNew;
|
||||
return res;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* fenceCheck -- check fences of an object */
|
||||
/* fenceCheck -- check fences of an object
|
||||
*
|
||||
* Keep in sync with fenceAlloc.
|
||||
*/
|
||||
|
||||
static Bool fenceCheck(PoolDebugMixin debug, Pool pool, Addr obj, Size size)
|
||||
{
|
||||
Size alignedSize;
|
||||
Addr startFence, clientNew, clientLimit, limit;
|
||||
Size alignedFenceSize, alignedSize;
|
||||
|
||||
AVERT_CRITICAL(PoolDebugMixin, debug);
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
/* Can't check obj */
|
||||
|
||||
alignedFenceSize = SizeAlignUp(debug->fenceSize, PoolAlignment(pool));
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
|
||||
startFence = AddrSub(obj, alignedFenceSize);
|
||||
clientNew = obj;
|
||||
clientLimit = AddrAdd(clientNew, size);
|
||||
limit = AddrAdd(clientNew, alignedSize + alignedFenceSize);
|
||||
|
||||
/* @@@@ shields? */
|
||||
/* Compare this to the AddrCopys in fenceAlloc */
|
||||
return (AddrComp(AddrSub(obj, debug->fenceSize), debug->fenceTemplate,
|
||||
debug->fenceSize) == 0
|
||||
&& AddrComp(AddrAdd(obj, size), debug->fenceTemplate,
|
||||
alignedSize - size) == 0
|
||||
&& AddrComp(AddrAdd(obj, alignedSize), debug->fenceTemplate,
|
||||
debug->fenceSize) == 0);
|
||||
return patternCheck(debug->fenceTemplate, debug->fenceSize,
|
||||
startFence, clientNew)
|
||||
&& patternCheck(debug->fenceTemplate, debug->fenceSize,
|
||||
clientLimit, limit);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -419,13 +511,14 @@ static Bool fenceCheck(PoolDebugMixin debug, Pool pool, Addr obj, Size size)
|
|||
static void fenceFree(PoolDebugMixin debug,
|
||||
Pool pool, Addr old, Size size)
|
||||
{
|
||||
Size alignedSize;
|
||||
Size alignedFenceSize, alignedSize;
|
||||
|
||||
ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free");
|
||||
|
||||
alignedFenceSize = SizeAlignUp(debug->fenceSize, PoolAlignment(pool));
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
freeCheckFree(debug, pool, AddrSub(old, debug->fenceSize),
|
||||
alignedSize + 2*debug->fenceSize);
|
||||
freeCheckFree(debug, pool, AddrSub(old, alignedFenceSize),
|
||||
alignedSize + 2 * alignedFenceSize);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ typedef void (*TagInitMethod)(void* tag, va_list args);
|
|||
*/
|
||||
|
||||
typedef struct PoolDebugOptionsStruct {
|
||||
void* fenceTemplate;
|
||||
const void *fenceTemplate;
|
||||
Size fenceSize;
|
||||
void* freeTemplate;
|
||||
const void *freeTemplate;
|
||||
Size freeSize;
|
||||
/* TagInitMethod tagInit; */
|
||||
/* Size tagSize; */
|
||||
|
|
@ -43,9 +43,9 @@ typedef PoolDebugOptionsStruct *PoolDebugOptions;
|
|||
|
||||
typedef struct PoolDebugMixinStruct {
|
||||
Sig sig;
|
||||
Addr fenceTemplate;
|
||||
const struct AddrStruct *fenceTemplate;
|
||||
Size fenceSize;
|
||||
Addr freeTemplate;
|
||||
const struct AddrStruct *freeTemplate;
|
||||
Size freeSize;
|
||||
TagInitMethod tagInit;
|
||||
Size tagSize;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#include "mpm.h"
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#include "testlib.h"
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
|
|
|||
|
|
@ -41,13 +41,6 @@ typedef union FreelistBlockUnion {
|
|||
#define freelistEND ((FreelistBlock)0)
|
||||
|
||||
|
||||
/* freelistMinimumAlignment -- the minimum allowed alignment for the
|
||||
* address ranges in a free list: see <design/freelist/#impl.grain.align>
|
||||
*/
|
||||
|
||||
#define freelistMinimumAlignment ((Align)sizeof(FreelistBlock))
|
||||
|
||||
|
||||
/* FreelistTag -- return the tag of word */
|
||||
|
||||
#define FreelistTag(word) ((word) & 1)
|
||||
|
|
@ -181,7 +174,7 @@ Bool FreelistCheck(Freelist fl)
|
|||
land = &fl->landStruct;
|
||||
CHECKD(Land, land);
|
||||
/* See <design/freelist/#impl.grain.align> */
|
||||
CHECKL(AlignIsAligned(freelistAlignment(fl), freelistMinimumAlignment));
|
||||
CHECKL(AlignIsAligned(freelistAlignment(fl), FreelistMinimumAlignment));
|
||||
CHECKL((fl->list == freelistEND) == (fl->listSize == 0));
|
||||
CHECKL((fl->list == freelistEND) == (fl->size == 0));
|
||||
CHECKL(SizeIsAligned(fl->size, freelistAlignment(fl)));
|
||||
|
|
@ -203,7 +196,7 @@ static Res freelistInit(Land land, ArgList args)
|
|||
return res;
|
||||
|
||||
/* See <design/freelist/#impl.grain> */
|
||||
AVER(AlignIsAligned(LandAlignment(land), freelistMinimumAlignment));
|
||||
AVER(AlignIsAligned(LandAlignment(land), FreelistMinimumAlignment));
|
||||
|
||||
fl = freelistOfLand(land);
|
||||
fl->list = freelistEND;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* freelist.h: FREE LIST ALLOCATOR INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: <design/freelist/>.
|
||||
*/
|
||||
|
|
@ -15,6 +15,9 @@ typedef struct FreelistStruct *Freelist;
|
|||
|
||||
extern Bool FreelistCheck(Freelist freelist);
|
||||
|
||||
/* See <design/freelist/#impl.grain.align> */
|
||||
#define FreelistMinimumAlignment ((Align)sizeof(FreelistBlock))
|
||||
|
||||
extern LandClass FreelistLandClassGet(void);
|
||||
|
||||
#endif /* freelist.h */
|
||||
|
|
@ -22,7 +25,7 @@ extern LandClass FreelistLandClassGet(void);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ extern Addr (AddrAlignDown)(Addr addr, Align align);
|
|||
|
||||
#define AddrIsAligned(p, a) WordIsAligned((Word)(p), a)
|
||||
#define AddrAlignUp(p, a) ((Addr)WordAlignUp((Word)(p), a))
|
||||
#define AddrRoundUp(p, r) ((Addr)WordRoundUp((Word)(p), r))
|
||||
|
||||
#define ReadonlyAddrAdd(p, s) ((ReadonlyAddr)((const char *)(p) + (s)))
|
||||
|
||||
#define SizeIsAligned(s, a) WordIsAligned((Word)(s), a)
|
||||
#define SizeAlignUp(s, a) ((Size)WordAlignUp((Word)(s), a))
|
||||
|
|
|
|||
111
mps/code/mpmss.c
111
mps/code/mpmss.c
|
|
@ -25,19 +25,19 @@
|
|||
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_class_t class, size_t (*size)(size_t i),
|
||||
mps_arena_t arena, ...)
|
||||
static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i),
|
||||
const char *name, mps_class_t pool_class,
|
||||
mps_arg_s *args)
|
||||
{
|
||||
mps_res_t res;
|
||||
mps_pool_t pool;
|
||||
va_list arg;
|
||||
size_t i, k;
|
||||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
|
||||
va_start(arg, arena);
|
||||
res = mps_pool_create_v(&pool, arena, class, arg);
|
||||
va_end(arg);
|
||||
printf("%s\n", name);
|
||||
|
||||
res = mps_pool_create_k(&pool, arena, pool_class, args);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ static mps_res_t stress(mps_class_t class, size_t (*size)(size_t i),
|
|||
}
|
||||
|
||||
|
||||
/* randomSize -- produce sizes both latge and small */
|
||||
/* randomSize -- produce sizes both large and small */
|
||||
|
||||
static size_t randomSize(size_t i)
|
||||
{
|
||||
|
|
@ -99,7 +99,7 @@ static size_t randomSize(size_t i)
|
|||
}
|
||||
|
||||
|
||||
/* randomSize8 -- produce sizes both latge and small, 8-byte aligned */
|
||||
/* randomSize8 -- produce sizes both large and small, 8-byte aligned */
|
||||
|
||||
static size_t randomSize8(size_t i)
|
||||
{
|
||||
|
|
@ -121,61 +121,90 @@ static size_t fixedSize(size_t i)
|
|||
|
||||
|
||||
static mps_pool_debug_option_s bothOptions = {
|
||||
/* .fence_template = */ (const void *)"postpostpostpost",
|
||||
/* .fence_size = */ MPS_PF_ALIGN,
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .fence_template = */ "post",
|
||||
/* .fence_size = */ 4,
|
||||
/* .free_template = */ "DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions = {
|
||||
/* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_size = */ 16,
|
||||
/* .fence_template = */ "123456789abcdef",
|
||||
/* .fence_size = */ 15,
|
||||
/* .free_template = */ NULL,
|
||||
/* .free_size = */ 0
|
||||
};
|
||||
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
||||
static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args,
|
||||
mps_pool_debug_option_s *options)
|
||||
{
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging */
|
||||
/* cross-segment allocation (possibly MVFF ought not to). */
|
||||
printf("MVFF\n");
|
||||
die(stress(mps_class_mvff(), randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE),
|
||||
"stress MVFF");
|
||||
printf("MV debug\n");
|
||||
die(stress(mps_class_mv_debug(), randomSize, arena,
|
||||
options, (size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV debug");
|
||||
mps_arena_t arena;
|
||||
|
||||
printf("MFS\n");
|
||||
fixedSizeSize = 13;
|
||||
die(stress(mps_class_mfs(), fixedSize, arena, (size_t)100000, fixedSizeSize),
|
||||
die(mps_arena_create_k(&arena, arena_class, arena_args),
|
||||
"mps_arena_create");
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
die(stress(arena, randomSize8, "MVFF", mps_class_mvff(), args),
|
||||
"stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, randomSize8, "MVFF debug", mps_class_mvff_debug(), args),
|
||||
"stress MVFF debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, randomSize, "MV", mps_class_mv(), args),
|
||||
"stress MV");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, randomSize, "MV debug", mps_class_mv_debug(), args),
|
||||
"stress MV debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
fixedSizeSize = 1 + rnd() % 64;
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, fixedSizeSize);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, 100000);
|
||||
die(stress(arena, fixedSize, "MFS", mps_class_mfs(), args),
|
||||
"stress MFS");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
printf("MV\n");
|
||||
die(stress(mps_class_mv(), randomSize, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV");
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
testInArena(arena, &bothOptions);
|
||||
mps_arena_destroy(arena);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
testInArena(mps_arena_class_vm(), args, &bothOptions);
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), smallArenaSIZE),
|
||||
"mps_arena_create");
|
||||
testInArena(arena, &fenceOptions);
|
||||
mps_arena_destroy(arena);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, smallArenaSIZE);
|
||||
testInArena(mps_arena_class_vm(), args, &fenceOptions);
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ typedef void (*Fun)(void); /* <design/type/#fun> */
|
|||
typedef MPS_T_WORD Word; /* <design/type/#word> */
|
||||
typedef unsigned char Byte; /* <design/type/#byte> */
|
||||
typedef struct AddrStruct *Addr; /* <design/type/#addr> */
|
||||
typedef const struct AddrStruct *ReadonlyAddr; /* <design/type/#readonlyaddr> */
|
||||
typedef Word Size; /* <design/type/#size> */
|
||||
typedef Word Count; /* <design/type/#count> */
|
||||
typedef Word Index; /* <design/type/#index> */
|
||||
|
|
|
|||
|
|
@ -323,9 +323,9 @@ typedef struct _mps_sac_s {
|
|||
|
||||
/* .sacc: Keep in sync with <code/sac.h>. */
|
||||
typedef struct mps_sac_class_s {
|
||||
size_t _block_size;
|
||||
size_t _cached_count;
|
||||
unsigned _frequency;
|
||||
size_t mps_block_size;
|
||||
size_t mps_cached_count;
|
||||
unsigned mps_frequency;
|
||||
} mps_sac_class_s;
|
||||
|
||||
#define mps_sac_classes_s mps_sac_class_s
|
||||
|
|
|
|||
|
|
@ -9,22 +9,6 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
/* The mvt pool class has five extra parameters to mps_pool_create:
|
||||
* mps_res_t mps_pool_create(mps_pool_t * pool, mps_arena_t arena,
|
||||
* mps_class_t mvt_class,
|
||||
* size_t minimum_size,
|
||||
* size_t mean_size,
|
||||
* size_t maximum_size,
|
||||
* mps_count_t reserve_depth
|
||||
* mps_count_t fragmentation_limit);
|
||||
* minimum_, mean_, and maximum_size are the mimimum, mean, and
|
||||
* maximum (typical) size of objects expected to be allocated in the
|
||||
* pool. reserve_depth is a measure of the expected hysteresis of the
|
||||
* object population. fragmentation_limit is a percentage (between 0
|
||||
* and 100): if the free space managed by the pool exceeds the
|
||||
* specified percentage, the pool will resort to a "first fit"
|
||||
* allocation policy.
|
||||
*/
|
||||
extern mps_class_t mps_class_mvt(void);
|
||||
|
||||
/* The mvt pool class supports two extensions to the pool protocol:
|
||||
|
|
|
|||
|
|
@ -6,14 +6,10 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "mpstd.h"
|
||||
#include <time.h>
|
||||
|
||||
#include "mpscmvt.h"
|
||||
#include "mps.h"
|
||||
|
||||
typedef mps_word_t mps_count_t; /* machine word (target dep.) */
|
||||
|
||||
#include "mpslib.h"
|
||||
#include "mpsavm.h"
|
||||
#include "testlib.h"
|
||||
|
|
@ -71,11 +67,11 @@ static size_t randomSize(unsigned long i)
|
|||
#define TEST_SET_SIZE 1234
|
||||
#define TEST_LOOPS 27
|
||||
|
||||
static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
||||
static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size, mps_align_t align)
|
||||
{
|
||||
mps_res_t res;
|
||||
|
||||
size = alignUp(size, MPS_PF_ALIGN);
|
||||
size = alignUp(size, align);
|
||||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, *p, ap, size);
|
||||
|
|
@ -87,8 +83,9 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
|||
}
|
||||
|
||||
|
||||
static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
||||
size_t (*size)(unsigned long i), mps_arg_s args[])
|
||||
static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
||||
size_t (*size)(unsigned long i),
|
||||
mps_class_t class, mps_arg_s args[])
|
||||
{
|
||||
mps_res_t res;
|
||||
mps_ap_t ap;
|
||||
|
|
@ -105,7 +102,7 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
for(i=0; i<TEST_SET_SIZE; ++i) {
|
||||
ss[i] = (*size)(i);
|
||||
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
res = make((mps_addr_t *)&ps[i], ap, ss[i], align);
|
||||
if(res != MPS_RES_OK)
|
||||
ss[i] = 0;
|
||||
else
|
||||
|
|
@ -144,7 +141,7 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
/* allocate some new objects */
|
||||
for(i=x; i<TEST_SET_SIZE; ++i) {
|
||||
size_t s = (*size)(i);
|
||||
res = make((mps_addr_t *)&ps[i], ap, s);
|
||||
res = make((mps_addr_t *)&ps[i], ap, s, align);
|
||||
if(res != MPS_RES_OK)
|
||||
break;
|
||||
ss[i] = s;
|
||||
|
|
@ -166,33 +163,29 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
}
|
||||
|
||||
|
||||
static void stress_with_arena_class(mps_arena_class_t aclass, Bool zoned)
|
||||
static void test_in_arena(mps_arena_class_t arena_class, mps_arg_s *arena_args)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, zoned);
|
||||
die(mps_arena_create_k(&arena, aclass, args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
die(mps_arena_create_k(&arena, arena_class, arena_args),
|
||||
"mps_arena_create");
|
||||
|
||||
size_min = MPS_PF_ALIGN;
|
||||
size_mean = 42;
|
||||
size_max = 8192;
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MIN_SIZE, size_min);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MEAN_SIZE, size_mean);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MAX_SIZE, size_max);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVT_RESERVE_DEPTH, TEST_SET_SIZE/2);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVT_FRAG_LIMIT, 0.3);
|
||||
die(stress(mps_class_mvt(), arena, randomSize, args), "stress MVT");
|
||||
die(stress(arena, align, randomSize, mps_class_mvt(), args), "stress MVT");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -200,8 +193,16 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
testlib_init(argc, argv);
|
||||
|
||||
stress_with_arena_class(mps_arena_class_vm(), TRUE);
|
||||
stress_with_arena_class(mps_arena_class_vm(), FALSE);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
test_in_arena(mps_arena_class_vm(), args);
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
test_in_arena(mps_arena_class_vm(), args);
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ static void MVDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
|
||||
static Res MVInit(Pool pool, ArgList args)
|
||||
{
|
||||
Align align = MV_ALIGN_DEFAULT;
|
||||
Size extendBy = MV_EXTEND_BY_DEFAULT;
|
||||
Size avgSize = MV_AVG_SIZE_DEFAULT;
|
||||
Size maxSize = MV_MAX_SIZE_DEFAULT;
|
||||
|
|
@ -226,6 +227,8 @@ static Res MVInit(Pool pool, ArgList args)
|
|||
Res res;
|
||||
ArgStruct arg;
|
||||
|
||||
if (ArgPick(&arg, args, MPS_KEY_ALIGN))
|
||||
align = arg.val.align;
|
||||
if (ArgPick(&arg, args, MPS_KEY_EXTEND_BY))
|
||||
extendBy = arg.val.size;
|
||||
if (ArgPick(&arg, args, MPS_KEY_MEAN_SIZE))
|
||||
|
|
@ -233,12 +236,14 @@ static Res MVInit(Pool pool, ArgList args)
|
|||
if (ArgPick(&arg, args, MPS_KEY_MAX_SIZE))
|
||||
maxSize = arg.val.size;
|
||||
|
||||
AVERT(Align, align);
|
||||
AVER(extendBy > 0);
|
||||
AVER(avgSize > 0);
|
||||
AVER(avgSize <= extendBy);
|
||||
AVER(maxSize > 0);
|
||||
AVER(extendBy <= maxSize);
|
||||
|
||||
pool->alignment = align;
|
||||
mv = Pool2MV(pool);
|
||||
arena = PoolArena(pool);
|
||||
|
||||
|
|
@ -626,6 +631,7 @@ static void MVFree(Pool pool, Addr old, Size size)
|
|||
AVERT(MV, mv);
|
||||
|
||||
AVER(old != (Addr)0);
|
||||
AVER(AddrIsAligned(old, pool->alignment));
|
||||
AVER(size > 0);
|
||||
|
||||
size = SizeAlignUp(size, pool->alignment);
|
||||
|
|
|
|||
|
|
@ -254,7 +254,12 @@ static Res MVTInit(Pool pool, ArgList args)
|
|||
fragLimit = (Count)(arg.val.d * 100);
|
||||
}
|
||||
|
||||
AVER(SizeIsAligned(align, MPS_PF_ALIGN));
|
||||
AVERT(Align, align);
|
||||
/* This restriction on the alignment is necessary because of the use
|
||||
* of a Freelist to store the free address ranges in low-memory
|
||||
* situations. See <design/freelist/#impl.grain.align>.
|
||||
*/
|
||||
AVER(AlignIsAligned(align, FreelistMinimumAlignment));
|
||||
AVER(0 < minSize);
|
||||
AVER(minSize <= meanSize);
|
||||
AVER(meanSize <= maxSize);
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ static void MVFFFreeSegs(MVFF mvff, Range range)
|
|||
mvff->total -= RangeSize(&delRange);
|
||||
}
|
||||
|
||||
/* Avoid calling SegNext if the next segment would fail */
|
||||
/* Avoid calling SegFindAboveAddr if the next segment would fail */
|
||||
/* the loop test, mainly because there might not be a */
|
||||
/* next segment. */
|
||||
if (segLimit == RangeLimit(range)) /* segment ends at end of range */
|
||||
|
|
@ -436,7 +436,7 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
{
|
||||
Size extendBy = MVFF_EXTEND_BY_DEFAULT;
|
||||
Size avgSize = MVFF_AVG_SIZE_DEFAULT;
|
||||
Size align = MVFF_ALIGN_DEFAULT;
|
||||
Align align = MVFF_ALIGN_DEFAULT;
|
||||
Bool slotHigh = MVFF_SLOT_HIGH_DEFAULT;
|
||||
Bool arenaHigh = MVFF_ARENA_HIGH_DEFAULT;
|
||||
Bool firstFit = MVFF_FIRST_FIT_DEFAULT;
|
||||
|
|
@ -475,7 +475,12 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
AVER(extendBy > 0); /* .arg.check */
|
||||
AVER(avgSize > 0); /* .arg.check */
|
||||
AVER(avgSize <= extendBy); /* .arg.check */
|
||||
AVER(SizeIsAligned(align, MPS_PF_ALIGN));
|
||||
AVERT(Align, align);
|
||||
/* This restriction on the alignment is necessary because of the use
|
||||
* of a Freelist to store the free address ranges in low-memory
|
||||
* situations. <design/freelist/#impl.grain.align>.
|
||||
*/
|
||||
AVER(AlignIsAligned(align, FreelistMinimumAlignment));
|
||||
AVERT(Bool, slotHigh);
|
||||
AVERT(Bool, arenaHigh);
|
||||
AVERT(Bool, firstFit);
|
||||
|
|
|
|||
|
|
@ -117,10 +117,10 @@ Res SACCreate(SAC *sacReturn, Pool pool, Count classesCount,
|
|||
/* to be large enough, but that gets complicated, if you have to */
|
||||
/* merge classes because of the adjustment. */
|
||||
for (i = 0; i < classesCount; ++i) {
|
||||
AVER(classes[i]._block_size > 0);
|
||||
AVER(SizeIsAligned(classes[i]._block_size, PoolAlignment(pool)));
|
||||
AVER(prevSize < classes[i]._block_size);
|
||||
prevSize = classes[i]._block_size;
|
||||
AVER(classes[i].mps_block_size > 0);
|
||||
AVER(SizeIsAligned(classes[i].mps_block_size, PoolAlignment(pool)));
|
||||
AVER(prevSize < classes[i].mps_block_size);
|
||||
prevSize = classes[i].mps_block_size;
|
||||
/* no restrictions on count */
|
||||
/* no restrictions on frequency */
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ Res SACCreate(SAC *sacReturn, Pool pool, Count classesCount,
|
|||
/* Calculate frequency scale */
|
||||
for (i = 0; i < classesCount; ++i) {
|
||||
unsigned oldFreq = totalFreq;
|
||||
totalFreq += classes[i]._frequency;
|
||||
totalFreq += classes[i].mps_frequency;
|
||||
AVER(oldFreq <= totalFreq); /* check for overflow */
|
||||
UNUSED(oldFreq); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
|
|
@ -136,10 +136,10 @@ Res SACCreate(SAC *sacReturn, Pool pool, Count classesCount,
|
|||
/* Find middle one */
|
||||
totalFreq /= 2;
|
||||
for (i = 0; i < classesCount; ++i) {
|
||||
if (totalFreq < classes[i]._frequency) break;
|
||||
totalFreq -= classes[i]._frequency;
|
||||
if (totalFreq < classes[i].mps_frequency) break;
|
||||
totalFreq -= classes[i].mps_frequency;
|
||||
}
|
||||
if (totalFreq <= classes[i]._frequency / 2)
|
||||
if (totalFreq <= classes[i].mps_frequency / 2)
|
||||
middleIndex = i;
|
||||
else
|
||||
middleIndex = i + 1; /* there must exist another class at i+1 */
|
||||
|
|
@ -155,9 +155,9 @@ Res SACCreate(SAC *sacReturn, Pool pool, Count classesCount,
|
|||
/* It's important this matches SACFind. */
|
||||
esac = ExternalSACOfSAC(sac);
|
||||
for (j = middleIndex + 1, i = 0; j < classesCount; ++j, i += 2) {
|
||||
esac->_freelists[i]._size = classes[j]._block_size;
|
||||
esac->_freelists[i]._size = classes[j].mps_block_size;
|
||||
esac->_freelists[i]._count = 0;
|
||||
esac->_freelists[i]._count_max = classes[j]._cached_count;
|
||||
esac->_freelists[i]._count_max = classes[j].mps_cached_count;
|
||||
esac->_freelists[i]._blocks = NULL;
|
||||
}
|
||||
esac->_freelists[i]._size = SizeMAX;
|
||||
|
|
@ -165,19 +165,19 @@ Res SACCreate(SAC *sacReturn, Pool pool, Count classesCount,
|
|||
esac->_freelists[i]._count_max = 0;
|
||||
esac->_freelists[i]._blocks = NULL;
|
||||
for (j = middleIndex, i = 1; j > 0; --j, i += 2) {
|
||||
esac->_freelists[i]._size = classes[j-1]._block_size;
|
||||
esac->_freelists[i]._size = classes[j-1].mps_block_size;
|
||||
esac->_freelists[i]._count = 0;
|
||||
esac->_freelists[i]._count_max = classes[j]._cached_count;
|
||||
esac->_freelists[i]._count_max = classes[j].mps_cached_count;
|
||||
esac->_freelists[i]._blocks = NULL;
|
||||
}
|
||||
esac->_freelists[i]._size = 0;
|
||||
esac->_freelists[i]._count = 0;
|
||||
esac->_freelists[i]._count_max = classes[j]._cached_count;
|
||||
esac->_freelists[i]._count_max = classes[j].mps_cached_count;
|
||||
esac->_freelists[i]._blocks = NULL;
|
||||
|
||||
/* finish init */
|
||||
esac->_trapped = FALSE;
|
||||
esac->_middle = classes[middleIndex]._block_size;
|
||||
esac->_middle = classes[middleIndex].mps_block_size;
|
||||
sac->pool = pool;
|
||||
sac->classesCount = classesCount;
|
||||
sac->middleIndex = middleIndex;
|
||||
|
|
|
|||
142
mps/code/sacss.c
142
mps/code/sacss.c
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "mpscmv.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "mpscmfs.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mps.h"
|
||||
|
|
@ -15,9 +16,7 @@
|
|||
#include "mpslib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mpstd.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
|
@ -28,9 +27,6 @@
|
|||
#define testSetSIZE 200
|
||||
#define testLOOPS 10
|
||||
|
||||
#define topClassSIZE 0xA00
|
||||
#define classCOUNT 4
|
||||
|
||||
|
||||
/* make -- allocate an object */
|
||||
|
||||
|
|
@ -45,25 +41,36 @@ static mps_res_t make(mps_addr_t *p, mps_sac_t sac, size_t size)
|
|||
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_class_t class,
|
||||
size_t classes_count, mps_sac_classes_s *classes,
|
||||
size_t (*size)(size_t i), mps_arena_t arena, ...)
|
||||
static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
||||
size_t (*size)(size_t i),
|
||||
const char *name, mps_class_t pool_class,
|
||||
mps_arg_s *args)
|
||||
{
|
||||
mps_res_t res;
|
||||
mps_pool_t pool;
|
||||
mps_sac_t sac;
|
||||
va_list arg;
|
||||
size_t i, k;
|
||||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
mps_sac_classes_s classes[4] = {
|
||||
{1, 1, 1},
|
||||
{2, 1, 2},
|
||||
{16, 9, 5},
|
||||
{100, 9, 4},
|
||||
};
|
||||
size_t classes_count = sizeof classes / sizeof *classes;
|
||||
for (i = 0; i < classes_count; ++i) {
|
||||
classes[i].mps_block_size *= alignUp(align, sizeof(void *));
|
||||
}
|
||||
|
||||
va_start(arg, arena);
|
||||
res = mps_pool_create_v(&pool, arena, class, arg);
|
||||
va_end(arg);
|
||||
printf("%s\n", name);
|
||||
|
||||
res = mps_pool_create_k(&pool, arena, pool_class, args);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
|
||||
die(mps_sac_create(&sac, pool, classes_count, classes), "SACCreate");
|
||||
die(mps_sac_create(&sac, pool, classes_count, classes),
|
||||
"SACCreate");
|
||||
|
||||
/* allocate a load of objects */
|
||||
for (i = 0; i < testSetSIZE; ++i) {
|
||||
|
|
@ -125,9 +132,9 @@ static mps_res_t stress(mps_class_t class,
|
|||
}
|
||||
|
||||
|
||||
/* randomSize8 -- produce sizes both latge and small */
|
||||
/* randomSize -- produce sizes both large and small */
|
||||
|
||||
static size_t randomSize8(size_t i)
|
||||
static size_t randomSize(size_t i)
|
||||
{
|
||||
size_t maxSize = 2 * 160 * 0x2000;
|
||||
size_t size;
|
||||
|
|
@ -138,58 +145,97 @@ static size_t randomSize8(size_t i)
|
|||
}
|
||||
|
||||
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
/* fixedSize -- produce always the same size */
|
||||
|
||||
static size_t fixedSizeSize = 0;
|
||||
|
||||
static size_t fixedSize(size_t i)
|
||||
{
|
||||
testlib_unused(i);
|
||||
return fixedSizeSize;
|
||||
}
|
||||
|
||||
|
||||
static mps_pool_debug_option_s debugOptions = {
|
||||
/* .fence_template = */ (const void *)"postpostpostpost",
|
||||
/* .fence_size = */ MPS_PF_ALIGN,
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .fence_template = */ "post",
|
||||
/* .fence_size = */ 4,
|
||||
/* .free_template = */ "DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_sac_classes_s classes[4] = {
|
||||
{MPS_PF_ALIGN, 1, 1},
|
||||
{MPS_PF_ALIGN * 2, 1, 2},
|
||||
{128 + MPS_PF_ALIGN, 9, 5},
|
||||
{topClassSIZE, 9, 4}
|
||||
};
|
||||
|
||||
static void testInArena(mps_arena_t arena)
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args)
|
||||
{
|
||||
printf("MVFF\n\n");
|
||||
die(stress(mps_class_mvff(), classCOUNT, classes, randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE),
|
||||
"stress MVFF");
|
||||
printf("MV debug\n\n");
|
||||
die(stress(mps_class_mv_debug(), classCOUNT, classes, randomSize8, arena,
|
||||
&debugOptions, (size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV debug");
|
||||
printf("MV\n\n");
|
||||
die(stress(mps_class_mv(), classCOUNT, classes, randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV");
|
||||
mps_arena_t arena;
|
||||
|
||||
die(mps_arena_create_k(&arena, arena_class, arena_args),
|
||||
"mps_arena_create");
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
die(stress(arena, align, randomSize, "MVFF", mps_class_mvff(), args),
|
||||
"stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &debugOptions);
|
||||
die(stress(arena, align, randomSize, "MVFF debug",
|
||||
mps_class_mvff_debug(), args),
|
||||
"stress MVFF debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, align, randomSize, "MV", mps_class_mv(), args),
|
||||
"stress MV");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &debugOptions);
|
||||
die(stress(arena, align, randomSize, "MV debug",
|
||||
mps_class_mv_debug(), args),
|
||||
"stress MV debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
fixedSizeSize = MPS_PF_ALIGN * (1 + rnd() % 100);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, fixedSizeSize);
|
||||
die(stress(arena, fixedSizeSize, fixedSize, "MFS", mps_class_mfs(), args),
|
||||
"stress MFS");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
testInArena(arena);
|
||||
mps_arena_destroy(arena);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
testInArena(mps_arena_class_vm(), args);
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
testInArena(mps_arena_class_vm(), args);
|
||||
} MPS_ARGS_END(args);
|
||||
testInArena(arena);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue