mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-23 23:36:27 -07:00
Merge branch/2014-04-08/align into branch/2014-05-15/size.
Copied from Perforce Change: 186116 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
7e22bed98f
26 changed files with 599 additions and 326 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, (void *)"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 = */ (void *)"post",
|
||||
/* .fence_size = */ 4,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions = {
|
||||
/* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_size = */ 16,
|
||||
/* .fence_template = */ (void *)"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 = 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 = 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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -354,6 +354,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,17 @@ Bool PoolDebugOptionsCheck(PoolDebugOptions opt)
|
|||
|
||||
ARG_DEFINE_KEY(pool_debug_options, PoolDebugOptions);
|
||||
|
||||
static char debugFencepostTemplate[4] = {'P', 'O', 'S', 'T'};
|
||||
static char debugFreeTemplate[4] = {'D', 'E', 'A', 'D'};
|
||||
|
||||
static PoolDebugOptionsStruct debugPoolOptionsDefault = {
|
||||
debugFencepostTemplate, 4, debugFreeTemplate, 4,
|
||||
};
|
||||
|
||||
static Res DebugPoolInit(Pool pool, ArgList args)
|
||||
{
|
||||
Res res;
|
||||
PoolDebugOptions options;
|
||||
PoolDebugOptions options = &debugPoolOptionsDefault;
|
||||
PoolDebugMixin debug;
|
||||
TagInitMethod tagInit;
|
||||
Size tagSize;
|
||||
|
|
@ -134,10 +141,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 +163,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 +177,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;
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +202,6 @@ static Res DebugPoolInit(Pool pool, ArgList args)
|
|||
return ResOK;
|
||||
|
||||
tagFail:
|
||||
alignFail:
|
||||
SuperclassOfPool(pool)->finish(pool);
|
||||
AVER(res != ResOK);
|
||||
return res;
|
||||
|
|
@ -231,38 +227,119 @@ static void DebugPoolFinish(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* freeSplat -- splat free block with splat pattern
|
||||
/* patternCopy -- copy pattern to fill a range
|
||||
*
|
||||
* If base is in a segment, the whole block has to be in it.
|
||||
* Fill the range of addresses from base (inclusive) to limit
|
||||
* (exclusive) with copies of pattern (which is size bytes long).
|
||||
*
|
||||
* Keep in sync with patternCheck.
|
||||
*/
|
||||
|
||||
static void patternCopy(Addr pattern, Size size, Addr base, Addr limit)
|
||||
{
|
||||
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 */
|
||||
(void)AddrCopy(p, pattern, size);
|
||||
p = end;
|
||||
} else if (p < rounded && rounded <= end && rounded <= limit) {
|
||||
/* Copy up to rounded */
|
||||
(void)AddrCopy(p, (char *)pattern + offset, AddrOffset(p, rounded));
|
||||
p = rounded;
|
||||
} else {
|
||||
/* Copy up to limit */
|
||||
AVER(limit <= end && (p == rounded || limit <= rounded));
|
||||
(void)AddrCopy(p, (char *)pattern + offset, AddrOffset(p, limit));
|
||||
p = limit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* Keep in sync with patternCopy.
|
||||
*/
|
||||
|
||||
static Bool patternCheck(Addr pattern, Size size, Addr base, Addr limit)
|
||||
{
|
||||
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 (AddrComp(p, pattern, size) != 0)
|
||||
return FALSE;
|
||||
p = end;
|
||||
} else if (p < rounded && rounded <= end && rounded <= limit) {
|
||||
/* Copy up to rounded */
|
||||
if (AddrComp(p, (char *)pattern + offset, AddrOffset(p, rounded)) != 0)
|
||||
return FALSE;
|
||||
p = rounded;
|
||||
} else {
|
||||
/* Copy up to limit */
|
||||
AVER(limit <= end && (p == rounded || limit <= rounded));
|
||||
if (AddrComp(p, (char *)pattern + offset, AddrOffset(p, limit)) != 0)
|
||||
return FALSE;
|
||||
p = limit;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
Seg seg;
|
||||
|
||||
AVER(base < limit);
|
||||
|
||||
/* If the block is in a segment, make sure any shield is up. */
|
||||
arena = PoolArena(pool);
|
||||
inSeg = SegOfAddr(&seg, arena, base);
|
||||
if (inSeg) {
|
||||
AVER(limit <= SegLimit(seg));
|
||||
ShieldExpose(arena, seg);
|
||||
if (SegOfAddr(&seg, arena, base)) {
|
||||
do {
|
||||
ShieldExpose(arena, seg);
|
||||
} while (SegLimit(seg) < limit && SegNext(&seg, 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);
|
||||
patternCopy(debug->freeTemplate, debug->freeSize, base, limit);
|
||||
if (SegOfAddr(&seg, arena, base)) {
|
||||
do {
|
||||
ShieldCover(arena, seg);
|
||||
} while (SegLimit(seg) < limit && SegNext(&seg, arena, seg));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,40 +348,24 @@ 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;
|
||||
Seg seg;
|
||||
|
||||
AVER(base < limit);
|
||||
|
||||
/* If the block is in a segment, make sure any shield is up. */
|
||||
arena = PoolArena(pool);
|
||||
inSeg = SegOfAddr(&seg, arena, base);
|
||||
if (inSeg) {
|
||||
AVER(limit <= SegLimit(seg));
|
||||
ShieldExpose(arena, seg);
|
||||
if (SegOfAddr(&seg, arena, base)) {
|
||||
do {
|
||||
ShieldExpose(arena, seg);
|
||||
} while (SegLimit(seg) < limit && SegNext(&seg, 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);
|
||||
res = patternCheck(debug->freeTemplate, debug->freeSize, base, limit);
|
||||
if (SegOfAddr(&seg, arena, base)) {
|
||||
do {
|
||||
ShieldCover(arena, seg);
|
||||
} while (SegLimit(seg) < limit && SegNext(&seg, arena, seg));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -351,63 +412,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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -416,13 +489,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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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/>.
|
||||
*/
|
||||
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
typedef struct FreelistStruct *Freelist;
|
||||
|
||||
#define FreelistMinimumAlignment ((Align)sizeof(FreelistBlock))
|
||||
|
||||
extern Bool FreelistCheck(Freelist freelist);
|
||||
|
||||
extern LandClass FreelistLandClassGet(void);
|
||||
|
|
@ -22,7 +24,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ CFLAGSCOMPILER := \
|
|||
-Wshadow \
|
||||
-Wstrict-aliasing=2 \
|
||||
-Wstrict-prototypes \
|
||||
-Wswitch-default \
|
||||
-Wwrite-strings
|
||||
-Wswitch-default
|
||||
CFLAGSCOMPILERSTRICT := -ansi -pedantic
|
||||
|
||||
# A different set of compiler flags for less strict compilation, for
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ 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 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 = */ (void *)"post",
|
||||
/* .fence_size = */ 4,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions = {
|
||||
/* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_size = */ 16,
|
||||
/* .fence_template = */ (void *)"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 = 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 = 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;
|
||||
|
|
|
|||
|
|
@ -326,9 +326,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
|
||||
|
|
@ -754,9 +754,9 @@ extern void mps_arena_roots_walk(mps_arena_t,
|
|||
|
||||
|
||||
typedef struct mps_pool_debug_option_s {
|
||||
const void *fence_template;
|
||||
void *fence_template;
|
||||
size_t fence_size;
|
||||
const void *free_template;
|
||||
void *free_template;
|
||||
size_t free_size;
|
||||
} mps_pool_debug_option_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:
|
||||
|
|
|
|||
79
mps/code/mpsw3.h
Normal file
79
mps/code/mpsw3.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* mpsw3.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE, WINDOWS PART
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .readership: customers, MPS developers.
|
||||
* .sources: <design/interface-c/>.
|
||||
*/
|
||||
|
||||
#ifndef mpsw3_h
|
||||
#define mpsw3_h
|
||||
|
||||
#include "mps.h" /* needed for mps_tramp_t */
|
||||
#include "mpswin.h" /* needed for SEH filter */
|
||||
|
||||
|
||||
extern LONG mps_SEH_filter(LPEXCEPTION_POINTERS, void **, size_t *);
|
||||
extern void mps_SEH_handler(void *, size_t);
|
||||
|
||||
|
||||
#define mps_tramp(r_o, f, p, s) \
|
||||
MPS_BEGIN \
|
||||
void **_r_o = (r_o); \
|
||||
mps_tramp_t _f = (f); \
|
||||
void *_p = (p); \
|
||||
size_t _s = (s); \
|
||||
void *_hp = NULL; size_t _hs = 0; \
|
||||
__try { \
|
||||
*_r_o = (*_f)(_p, _s); \
|
||||
} __except(mps_SEH_filter(GetExceptionInformation(), \
|
||||
&_hp, &_hs)) { \
|
||||
mps_SEH_handler(_hp, _hs); \
|
||||
} \
|
||||
MPS_END
|
||||
|
||||
|
||||
#endif /* mpsw3_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 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.
|
||||
*/
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -261,7 +261,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);
|
||||
|
|
|
|||
|
|
@ -456,7 +456,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;
|
||||
|
|
@ -500,7 +500,12 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
AVER(avgSize <= extendBy); /* .arg.check */
|
||||
AVER(spare >= 0.0); /* .arg.check */
|
||||
AVER(spare <= 1.0); /* .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 = */ (void *)"post",
|
||||
/* .fence_size = */ 4,
|
||||
/* .free_template = */ (void *)"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 = 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 = 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 = sizeof(void *) * (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;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@ an ``AVER()`` has fired. Naturally, if the information required for
|
|||
the dump has been corrupted, it will fail, as softly as possible
|
||||
(source @@@@).
|
||||
|
||||
_`.req.portable`: Client code that uses these features must be easily
|
||||
portable to all the supported platforms. (Source: job003749_.)
|
||||
|
||||
.. _job003749: http://www.ravenbrook.com/project/mps/issue/job003749/
|
||||
|
||||
.. note::
|
||||
|
||||
There are more requirements, especially about memory dumps and
|
||||
|
|
@ -90,6 +95,11 @@ specified as a byte/word which used repeatedly to fill the fencepost.
|
|||
_`.fence.content.template`: The content could be given as a template
|
||||
which is of the right size and is simply copied onto the fencepost.
|
||||
|
||||
_`.fence.content.template.repeat`: The content could be given as a
|
||||
template which is copied repeatedly until the fencepost is full. (This
|
||||
would avoid the need to specify different templates on different
|
||||
architectures, and so help meet `.req.portable`_.)
|
||||
|
||||
_`.fence.walk`: `.req.fencepost.check`_ requires the ability to find
|
||||
all the allocated objects. In formatted pools, this is not a problem.
|
||||
In unformatted pools, we could use the walker. It's a feasible
|
||||
|
|
@ -233,14 +243,14 @@ to pools. In particular, clients will be able to use tagging and
|
|||
fenceposting separately on each pool.
|
||||
|
||||
_`.fence.size`: Having fenceposts of adjustable size and pattern is
|
||||
quite useful. We feel that restricting the size to an integral
|
||||
multiple of the [pool or format?] alignment is harmless and simplifies
|
||||
the implementation enormously.
|
||||
useful. Restricting the size to an integral multiple of the [pool or
|
||||
format?] alignment would simplify the implementation but breaks
|
||||
`.req.portable`_.
|
||||
|
||||
_`.fence.template`: We use templates (`.fence.content.template`_) to
|
||||
fill in the fenceposts, but we do not give any guarantees about the
|
||||
location of the fenceposts, only that they're properly aligned. This
|
||||
leaves us the opportunity to do tail-only fenceposting, if we choose.
|
||||
location of the fenceposts. This leaves us the opportunity to do
|
||||
tail-only fenceposting, if we choose.
|
||||
|
||||
_`.fence.slop`: [see impl.c.dbgpool.FenceAlloc @@@@]
|
||||
|
||||
|
|
@ -416,6 +426,8 @@ Document History
|
|||
|
||||
- 2013-04-14 GDR_ Converted to reStructuredText.
|
||||
|
||||
- 2014-04-09 GDR_ Added newly discovered requirement `.req.portable`_.
|
||||
|
||||
.. _RB: http://www.ravenbrook.com/consultants/rb/
|
||||
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ May contain exact references? [4]_ yes --- yes yes ---
|
|||
May contain ambiguous references? [4]_ no --- no no --- --- --- --- --- no
|
||||
May contain weak references? [4]_ no --- no yes --- --- --- --- --- no
|
||||
Allocations fixed or variable in size? var var var var var fixed var var var var
|
||||
Alignment? [5]_ conf conf conf conf conf [6]_ [6]_ [7]_ [7]_ conf
|
||||
Alignment? [5]_ conf conf conf conf conf [6]_ conf [7]_ [7]_ conf
|
||||
Dependent objects? [8]_ no --- no yes --- --- --- --- --- no
|
||||
May use remote references? [9]_ no --- no no --- --- --- --- --- no
|
||||
Blocks are automatically managed? [10]_ yes yes yes yes yes no no no no no
|
||||
|
|
@ -151,13 +151,13 @@ Blocks may use :term:`in-band headers`? yes yes yes yes yes
|
|||
.. [5] "Alignment" is "conf" if the client program may specify
|
||||
:term:`alignment` for each pool.
|
||||
|
||||
.. [6] The alignment of blocks allocated from :ref:`pool-mv` pools
|
||||
is platform-dependent.
|
||||
.. [6] The alignment of blocks allocated from :ref:`pool-mfs`
|
||||
pools is the platform's :term:`natural alignment`,
|
||||
:c:macro:`MPS_PF_ALIGN`.
|
||||
|
||||
.. [7] :ref:`pool-mvt` and :ref:`pool-mvff` pools have
|
||||
configurable alignment, but it may not be smaller than the
|
||||
:term:`natural alignment` for the :term:`platform` (see
|
||||
:c:macro:`MPS_PF_ALIGN`).
|
||||
configurable alignment, but it may not be smaller than
|
||||
``sizeof(void *)``.
|
||||
|
||||
.. [8] In pools with this property, each object may specify an
|
||||
:term:`dependent object` which the client program
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ MV properties
|
|||
|
||||
* Allocations may be variable in size.
|
||||
|
||||
* The :term:`alignment` of blocks is not configurable: it is the
|
||||
:term:`natural alignment` of the platform (see
|
||||
:c:macro:`MPS_PF_ALIGN`).
|
||||
* The :term:`alignment` of blocks is configurable.
|
||||
|
||||
* Blocks do not have :term:`dependent objects`.
|
||||
|
||||
|
|
@ -73,7 +71,13 @@ MV interface
|
|||
:term:`pool`.
|
||||
|
||||
When creating an MV pool, :c:func:`mps_pool_create_k` may take
|
||||
three :term:`keyword arguments`:
|
||||
the following :term:`keyword arguments`:
|
||||
|
||||
* :c:macro:`MPS_KEY_ALIGN` (type :c:type:`mps_align_t`, default is
|
||||
:c:macro:`MPS_PF_ALIGN`) is the
|
||||
:term:`alignment` of addresses for allocation (and freeing) in
|
||||
the pool. If an unaligned size is passed to :c:func:`mps_alloc` or
|
||||
:c:func:`mps_free`, it will be rounded up to the pool's alignment.
|
||||
|
||||
* :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`,
|
||||
default 65536) is the :term:`size` of segment that the pool will
|
||||
|
|
@ -119,10 +123,11 @@ MV interface
|
|||
class.
|
||||
|
||||
When creating a debugging MV pool, :c:func:`mps_pool_create_k`
|
||||
takes four keyword arguments: :c:macro:`MPS_KEY_EXTEND_SIZE`,
|
||||
:c:macro:`MPS_KEY_MEAN_SIZE`, :c:macro:`MPS_KEY_MAX_SIZE` are as
|
||||
described above, and :c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS`
|
||||
specifies the debugging options. See :c:type:`mps_debug_option_s`.
|
||||
takes the following keyword arguments: :c:macro:`MPS_KEY_ALIGN`,
|
||||
:c:macro:`MPS_KEY_EXTEND_SIZE`, :c:macro:`MPS_KEY_MEAN_SIZE`,
|
||||
:c:macro:`MPS_KEY_MAX_SIZE` are as described above, and
|
||||
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` specifies the debugging
|
||||
options. See :c:type:`mps_debug_option_s`.
|
||||
|
||||
.. deprecated:: starting with version 1.112.
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ MVFF properties
|
|||
* Allocations may be variable in size.
|
||||
|
||||
* The :term:`alignment` of blocks is configurable, but may not be
|
||||
smaller than the :term:`natural alignment` of the platform.
|
||||
smaller than ``sizeof(void *)``.
|
||||
|
||||
* Blocks do not have :term:`dependent objects`.
|
||||
|
||||
|
|
@ -127,10 +127,10 @@ MVFF interface
|
|||
* :c:macro:`MPS_KEY_ALIGN` (type :c:type:`mps_align_t`, default is
|
||||
:c:macro:`MPS_PF_ALIGN`) is the
|
||||
:term:`alignment` of addresses for allocation (and freeing) in
|
||||
the pool. If an unaligned size is passed to :c:func:`mps_alloc` or
|
||||
:c:func:`mps_free`, it will be rounded up to the pool's alignment.
|
||||
The minimum alignment supported by pools of this class is
|
||||
``sizeof(void *)``.
|
||||
the pool. If an unaligned size is passed to :c:func:`mps_alloc`
|
||||
or :c:func:`mps_free`, it will be rounded up to the pool's
|
||||
alignment. The minimum alignment supported by pools of this
|
||||
class is ``sizeof(void *)``.
|
||||
|
||||
* :c:macro:`MPS_KEY_SPARE` (type :c:type:`double`, default 0.75)
|
||||
is the maximum proportion of memory that the pool will keep
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ MVT properties
|
|||
|
||||
* Allocations may be variable in size.
|
||||
|
||||
* The :term:`alignment` of blocks is configurable, but may not be
|
||||
smaller than ``sizeof(void *)``.
|
||||
|
||||
* Blocks do not have :term:`dependent objects`.
|
||||
|
||||
* Blocks are not automatically :term:`reclaimed`.
|
||||
|
|
@ -117,7 +120,7 @@ MVT interface
|
|||
the pool. If an unaligned size is passed to :c:func:`mps_alloc` or
|
||||
:c:func:`mps_free`, it will be rounded up to the pool's alignment.
|
||||
The minimum alignment supported by pools of this class is
|
||||
``sizeof(void *)``.
|
||||
``sizeof(void *)``.
|
||||
|
||||
* :c:macro:`MPS_KEY_MIN_SIZE` (type :c:type:`size_t`, default is
|
||||
:c:macro:`MPS_PF_ALIGN`) is the
|
||||
|
|
|
|||
|
|
@ -40,10 +40,23 @@ New features
|
|||
the lowest generation whose new size was within its capacity.)
|
||||
|
||||
|
||||
|
||||
Interface changes
|
||||
.................
|
||||
|
||||
#. It is now possible to configure the alignment of objects allocated
|
||||
in a :ref:`pool-mv` pool, by passing the :c:macro:`MPS_KEY_ALIGN`
|
||||
keyword argument to :c:func:`mps_pool_create_k`.
|
||||
|
||||
#. The alignment requirements for :ref:`pool-mvff` and :ref:`pool-mvt`
|
||||
pools have been relaxed on the platforms ``w3i3mv`` and ``w3i6mv``.
|
||||
On all platforms it is now possible to specify alignments down to
|
||||
``sizeof(void *)`` as the alignment for pools of these classes.
|
||||
|
||||
#. The sizes of the templates in a :c:type:`mps_pool_debug_option_s`
|
||||
structure no longer have to be related to the alignment of the
|
||||
pools that they are used with. This makes it easier to reuse these
|
||||
structures.
|
||||
|
||||
#. There is now a default value (currently 1 \ :term:`megabyte`) for
|
||||
the :c:macro:`MPS_KEY_ARENA_SIZE` keyword argument to
|
||||
:c:func:`mps_arena_create_k` when creating a virtual memory arena.
|
||||
|
|
@ -81,6 +94,12 @@ Other changes
|
|||
|
||||
.. _job003745: https://www.ravenbrook.com/project/mps/issue/job003745/
|
||||
|
||||
#. The debugging version of the :ref:`pool-mvff` pool class,
|
||||
:c:func:`mps_class_mvff_debug`, no longer triggers an assertion
|
||||
failure if you allocate a large object. See job003751_.
|
||||
|
||||
.. _job003751: https://www.ravenbrook.com/project/mps/issue/job003751/
|
||||
|
||||
#. :program:`mpseventtxt` now successfully processes a telemetry log
|
||||
containing multiple labels associated with the same address. See
|
||||
job003756_.
|
||||
|
|
|
|||
|
|
@ -170,9 +170,9 @@ Cache interface
|
|||
|
||||
The size classes are described by an array of element type
|
||||
:c:type:`mps_sac_class_s`. This array is used to initialize the
|
||||
segregated allocation cache, and is not needed
|
||||
after:c:func:`mps_sac_create` returns. The following constraints
|
||||
apply to the array:
|
||||
segregated allocation cache, and is not needed after
|
||||
:c:func:`mps_sac_create` returns. The following constraints apply
|
||||
to the array:
|
||||
|
||||
* You must specify at least one size class.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ debugging:
|
|||
for the pattern at any time by calling
|
||||
:c:func:`mps_pool_check_free_space`.
|
||||
|
||||
The :term:`client program` specifies templates for both of these
|
||||
The :term:`client program` may specify templates for both of these
|
||||
features via the :c:type:`mps_pool_debug_option_s` structure. This
|
||||
allows it to specify patterns:
|
||||
|
||||
|
|
@ -66,8 +66,8 @@ allows it to specify patterns:
|
|||
For example::
|
||||
|
||||
mps_pool_debug_option_s debug_options = {
|
||||
(const void *)"postpost", 8,
|
||||
(const void *)"freefree", 8,
|
||||
"fencepost", 9,
|
||||
"free", 4,
|
||||
};
|
||||
mps_pool_t pool;
|
||||
mps_res_t res;
|
||||
|
|
@ -87,9 +87,9 @@ For example::
|
|||
class`. ::
|
||||
|
||||
typedef struct mps_pool_debug_option_s {
|
||||
const void *fence_template;
|
||||
void *fence_template;
|
||||
size_t fence_size;
|
||||
const void *free_template;
|
||||
void *free_template;
|
||||
size_t free_size;
|
||||
} mps_pool_debug_option_s;
|
||||
|
||||
|
|
@ -104,10 +104,6 @@ For example::
|
|||
``free_size`` is the :term:`size` of ``free_template`` in bytes, or
|
||||
zero if the debugging pool should not splat free space.
|
||||
|
||||
Both ``fence_size`` and ``free_size`` must be a multiple of the
|
||||
:term:`alignment` of the :term:`pool`, and also a multiple of the
|
||||
alignment of the pool's :term:`object format` if it has one.
|
||||
|
||||
The debugging pool will copy the ``fence_size`` bytes pointed to by
|
||||
``fence_template`` in a repeating pattern onto each fencepost during
|
||||
allocation, and it will copy the bytes pointed to by
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ now :c:macro:`MPS_KEY_ARGS_END`.
|
|||
Keyword Type & field in ``arg.val`` See
|
||||
======================================== ====================================================== ==========================================================
|
||||
:c:macro:`MPS_KEY_ARGS_END` *none* *see above*
|
||||
:c:macro:`MPS_KEY_ALIGN` :c:type:`mps_align_t` ``align`` :c:func:`mps_class_mvff`, :c:func:`mps_class_mvt`
|
||||
:c:macro:`MPS_KEY_ALIGN` :c:type:`mps_align_t` ``align`` :c:func:`mps_class_mv`, :c:func:`mps_class_mvff`, :c:func:`mps_class_mvt`
|
||||
:c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` :c:type:`mps_bool_t` ``b`` :c:func:`mps_class_ams`
|
||||
:c:macro:`MPS_KEY_ARENA_CL_BASE` :c:type:`mps_addr_t` ``addr`` :c:func:`mps_arena_class_cl`
|
||||
:c:macro:`MPS_KEY_ARENA_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_arena_class_vm`, :c:func:`mps_arena_class_cl`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue