From b4b1e1396731df180dc45e5f5ae0527be191c711 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 8 Apr 2014 20:28:28 +0100 Subject: [PATCH 01/17] Branching master to branch/2014-04-08/align. Copied from Perforce Change: 185361 ServerID: perforce.ravenbrook.com From 88626830d89f83cc382f4293087d29a458bffb7d Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 8 Apr 2014 21:32:19 +0100 Subject: [PATCH 02/17] Alignment is now configurable for mv pools using mps_key_align. MVFF and MVT support alignments down to FreelistMinimumAlignment. For MVFF and MVT, alignments that are too small are rounded up automatically, to make it easier to write portable programs. Copied from Perforce Change: 185369 ServerID: perforce.ravenbrook.com --- mps/code/config.h | 1 + mps/code/freelist.c | 14 +++++--------- mps/code/freelist.h | 7 +++++-- mps/code/mpm.h | 1 + mps/code/poolmv.c | 5 +++++ mps/code/poolmv2.c | 8 +++++++- mps/code/poolmvff.c | 10 ++++++++-- mps/manual/source/pool/intro.rst | 12 ++++++------ mps/manual/source/pool/mv.rst | 21 +++++++++++++-------- mps/manual/source/pool/mvff.rst | 13 +++++++------ mps/manual/source/pool/mvt.rst | 6 +++++- mps/manual/source/release.rst | 16 ++++++++++++++++ mps/manual/source/topic/keyword.rst | 2 +- 13 files changed, 80 insertions(+), 36 deletions(-) diff --git a/mps/code/config.h b/mps/code/config.h index e29127c153c..3072ad0285f 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -291,6 +291,7 @@ /* Pool MV Configuration -- see */ +#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) diff --git a/mps/code/freelist.c b/mps/code/freelist.c index 6260451ff59..8468127e963 100644 --- a/mps/code/freelist.c +++ b/mps/code/freelist.c @@ -1,7 +1,7 @@ /* freelist.c: FREE LIST ALLOCATOR IMPLEMENTATION * * $Id$ - * Copyright (c) 2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license. * * .sources: . */ @@ -25,10 +25,6 @@ typedef union FreelistBlockUnion { } FreelistBlockUnion; -/* See */ -#define freelistMinimumAlignment ((Align)sizeof(FreelistBlock)) - - #define FreelistTag(word) ((word) & 1) #define FreelistTagSet(word) ((FreelistBlock)((Word)(word) | 1)) #define FreelistTagReset(word) ((FreelistBlock)((Word)(word) & ~(Word)1)) @@ -144,7 +140,7 @@ Bool FreelistCheck(Freelist fl) { CHECKS(Freelist, fl); /* See */ - CHECKL(AlignIsAligned(fl->alignment, freelistMinimumAlignment)); + CHECKL(AlignIsAligned(fl->alignment, FreelistMinimumAlignment)); CHECKL((fl->list == NULL) == (fl->listSize == 0)); return TRUE; } @@ -152,9 +148,9 @@ Bool FreelistCheck(Freelist fl) Res FreelistInit(Freelist fl, Align alignment) { + AVER(fl != NULL); /* See */ - if (!AlignIsAligned(alignment, freelistMinimumAlignment)) - return ResPARAM; + AVER(AlignIsAligned(alignment, FreelistMinimumAlignment)); fl->alignment = alignment; fl->list = NULL; @@ -626,7 +622,7 @@ void FreelistFlushToCBS(Freelist fl, CBS cbs) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2013 Ravenbrook Limited . + * Copyright (C) 2013-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/freelist.h b/mps/code/freelist.h index 1bb9840c8c9..8ac4404736c 100644 --- a/mps/code/freelist.h +++ b/mps/code/freelist.h @@ -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: . */ @@ -18,6 +18,9 @@ typedef struct FreelistStruct *Freelist; typedef union FreelistBlockUnion *FreelistBlock; +/* See */ +#define FreelistMinimumAlignment ((Align)sizeof(FreelistBlock)) + typedef Bool (*FreelistIterateMethod)(Bool *deleteReturn, Range range, void *closureP, Size closureS); @@ -53,7 +56,7 @@ extern void FreelistFlushToCBS(Freelist fl, CBS cbs); /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2013 Ravenbrook Limited . + * Copyright (C) 2013-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/mpm.h b/mps/code/mpm.h index d830674512f..2d5b87d2fbf 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -99,6 +99,7 @@ extern Addr (AddrAlignDown)(Addr addr, Align align); #define IndexAlignDown(s, a) ((Index)WordAlignDown((Word)(s), a)) #define AlignIsAligned(a1, a2) WordIsAligned((Word)(a1), a2) +#define AlignAlignUp(s, a) ((Align)WordAlignUp((Word)(s), a)) extern Addr (AddrSet)(Addr target, Byte value, Size size); diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 0ce4f28c95d..7e7ef74df77 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -208,6 +208,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; @@ -217,6 +218,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)) @@ -224,12 +227,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); diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index b2903481b45..e134f0737be 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -253,7 +253,7 @@ static Res MVTInit(Pool pool, ArgList args) fragLimit = (Count)(arg.val.d * 100); } - AVER(SizeIsAligned(align, MPS_PF_ALIGN)); + AVERT(Align, align); AVER(0 < minSize); AVER(minSize <= meanSize); AVER(meanSize <= maxSize); @@ -261,6 +261,12 @@ static Res MVTInit(Pool pool, ArgList args) AVER(fragLimit <= 100); /* TODO: More sanity checks possible? */ + /* 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 . + */ + align = AlignAlignUp(align, FreelistMinimumAlignment); + /* see */ fillSize = SizeAlignUp(maxSize, ArenaAlign(arena)); /* see */ diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index 201d2047104..37215540c35 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -531,7 +531,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; @@ -570,11 +570,17 @@ 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); AVERT(Bool, slotHigh); AVERT(Bool, arenaHigh); AVERT(Bool, firstFit); + /* This restriction on the alignment is necessary because of the use + * of a Freelist to store the free address ranges in low-memory + * situations. . + */ + align = AlignAlignUp(align, FreelistMinimumAlignment); + mvff = Pool2MVFF(pool); mvff->extendBy = extendBy; diff --git a/mps/manual/source/pool/intro.rst b/mps/manual/source/pool/intro.rst index ed8f83b8d4a..b44fea4de98 100644 --- a/mps/manual/source/pool/intro.rst +++ b/mps/manual/source/pool/intro.rst @@ -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 smaller values than + ``sizeof(void *)`` are rounded up. .. [8] In pools with this property, each object may specify an :term:`dependent object` which the client program diff --git a/mps/manual/source/pool/mv.rst b/mps/manual/source/pool/mv.rst index 433525f7362..ae8c1f65457 100644 --- a/mps/manual/source/pool/mv.rst +++ b/mps/manual/source/pool/mv.rst @@ -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 request from the @@ -117,10 +121,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. diff --git a/mps/manual/source/pool/mvff.rst b/mps/manual/source/pool/mvff.rst index e688a00d09d..199b56f0a28 100644 --- a/mps/manual/source/pool/mvff.rst +++ b/mps/manual/source/pool/mvff.rst @@ -79,8 +79,8 @@ 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. +* The :term:`alignment` of blocks is configurable, but smaller + alignments than ``sizeof(void *)`` are rounded up. * Blocks do not have :term:`dependent objects`. @@ -127,10 +127,11 @@ 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 *)``; you can pass a smaller alignment + but it will be rounded up. * :c:macro:`MPS_KEY_MVFF_ARENA_HIGH` (type :c:type:`mps_bool_t`, default false) determines whether new segments are acquired at high diff --git a/mps/manual/source/pool/mvt.rst b/mps/manual/source/pool/mvt.rst index f3bbba705a0..351adc9ff8f 100644 --- a/mps/manual/source/pool/mvt.rst +++ b/mps/manual/source/pool/mvt.rst @@ -78,6 +78,9 @@ MVT properties * Allocations may be variable in size. +* The :term:`alignment` of blocks is configurable, but smaller + alignments than ``sizeof(void *)`` are rounded up. + * Blocks do not have :term:`dependent objects`. * Blocks are not automatically :term:`reclaimed`. @@ -117,7 +120,8 @@ 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 *)``; you can pass a smaller alignment but it will + be rounded up. * :c:macro:`MPS_KEY_MIN_SIZE` (type :c:type:`size_t`, default is :c:macro:`MPS_PF_ALIGN`) is the diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 83e23aea3c3..71e88e48c9f 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -27,6 +27,22 @@ New features calling :c:func:`mps_pool_create_k`. +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`. + +#. It is now possible to specify any alignment for :ref:`pool-mvff` + and :ref:`pool-mvt` pools. Alignments smaller than + ``sizeof(void *)`` are rounded up automatically. This means that on + the platforms ``w3i3mv`` and ``w3i6mv``, where + :c:macro:`MPS_PF_ALIGN` is larger than ``sizeof(void *)``, it is + now possible to specify the latter as the alignment for these + pools. + + Other changes ............. diff --git a/mps/manual/source/topic/keyword.rst b/mps/manual/source/topic/keyword.rst index 3b3fbcb01ad..a97201b4fd9 100644 --- a/mps/manual/source/topic/keyword.rst +++ b/mps/manual/source/topic/keyword.rst @@ -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` From e7a9e1e2442576de18383db5ad4d67c0416067be Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 13:00:52 +0100 Subject: [PATCH 03/17] Make debugging pool implementation more flexible -- there's no longer a requirement for fencesize to be a multiple of the pool alignment, nor for freesize to be a divisor of the pool alignment. this makes it easy to write simple and portable debug options structures without having to mess about with mps_pf_align. Copied from Perforce Change: 185379 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 195 +++++++++++++++++--------- mps/manual/source/topic/debugging.rst | 8 +- 2 files changed, 134 insertions(+), 69 deletions(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 77c1d6eaf40..ef78360c182 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -158,10 +158,6 @@ static Res DebugPoolInit(Pool pool, ArgList args) /* into Addr memory, to avoid breaking . */ 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 +172,6 @@ static Res DebugPoolInit(Pool pool, ArgList args) /* into Addr memory, to avoid breaking . */ debug->freeSize = options->freeSize; if (debug->freeSize != 0) { - if (PoolAlignment(pool) % debug->freeSize != 0) { - res = ResPARAM; - goto alignFail; - } debug->freeTemplate = options->freeTemplate; } @@ -205,7 +197,6 @@ static Res DebugPoolInit(Pool pool, ArgList args) return ResOK; tagFail: -alignFail: SuperclassOfPool(pool)->finish(pool); AVER(res != ResOK); return res; @@ -231,6 +222,96 @@ static void DebugPoolFinish(Pool pool) } +/* 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). + * + * Keep in sync with patternCheck. + */ + +static void patternCopy(const void *pattern, Size size, Addr base, Addr limit) +{ + Addr p; + + AVER(pattern != NULL); + AVER(0 < size); + AVER(base != NULL); + AVER(base <= limit); + + for (p = base; 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, AddrAdd(pattern, offset), AddrOffset(p, rounded)); + p = rounded; + } else { + /* Copy up to limit */ + AVER(limit <= end && (p == rounded || limit <= rounded)); + (void)AddrCopy(p, AddrAdd(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(const void *pattern, Size size, Addr base, Addr limit) +{ + Addr p; + + AVER(pattern != NULL); + AVER(0 < size); + AVER(base != NULL); + AVER(base <= limit); + + for (p = base; 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, AddrAdd(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, AddrAdd(pattern, offset), AddrOffset(p, limit)) != 0) + return FALSE; + p = limit; + } + } + + return TRUE; +} + + /* freeSplat -- splat free block with splat pattern * * If base is in a segment, the whole block has to be in it. @@ -238,8 +319,6 @@ static void DebugPoolFinish(Pool pool) 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; @@ -253,14 +332,7 @@ static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) 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)); + patternCopy(debug->freeTemplate, debug->freeSize, base, limit); if (inSeg) { ShieldCover(arena, seg); } @@ -271,9 +343,7 @@ 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; @@ -287,22 +357,7 @@ static Bool freeCheck(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) 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: + res = patternCheck(debug->freeTemplate, debug->freeSize, base, limit); if (inSeg) { ShieldCover(arena, seg); } @@ -357,57 +412,70 @@ static void freeCheckFree(PoolDebugMixin debug, * 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). + * + * 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 +484,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); } diff --git a/mps/manual/source/topic/debugging.rst b/mps/manual/source/topic/debugging.rst index 70494aa20cf..942f8fa5987 100644 --- a/mps/manual/source/topic/debugging.rst +++ b/mps/manual/source/topic/debugging.rst @@ -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, + (const void *)"fencepost", 9, + (const void *)"free", 4, }; mps_pool_t pool; mps_res_t res; @@ -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 From 07853f0c33fc693bec8b7dafbc18261632fe1a64 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 13:01:58 +0100 Subject: [PATCH 04/17] Alas, mvff and mvt can't round up alignment because they need to support buffered allocation. Copied from Perforce Change: 185381 ServerID: perforce.ravenbrook.com --- mps/code/poolmv2.c | 11 +++++------ mps/code/poolmvff.c | 9 ++++----- mps/manual/source/pool/intro.rst | 4 ++-- mps/manual/source/pool/mvff.rst | 7 +++---- mps/manual/source/pool/mvt.rst | 7 +++---- mps/manual/source/release.rst | 11 ++++------- 6 files changed, 21 insertions(+), 28 deletions(-) diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index e134f0737be..0a700f401b7 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -254,6 +254,11 @@ static Res MVTInit(Pool pool, ArgList args) } 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 . + */ + AVER(AlignIsAligned(align, FreelistMinimumAlignment)); AVER(0 < minSize); AVER(minSize <= meanSize); AVER(meanSize <= maxSize); @@ -261,12 +266,6 @@ static Res MVTInit(Pool pool, ArgList args) AVER(fragLimit <= 100); /* TODO: More sanity checks possible? */ - /* 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 . - */ - align = AlignAlignUp(align, FreelistMinimumAlignment); - /* see */ fillSize = SizeAlignUp(maxSize, ArenaAlign(arena)); /* see */ diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index 37215540c35..ecb99d441c8 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -571,15 +571,14 @@ static Res MVFFInit(Pool pool, ArgList args) AVER(avgSize > 0); /* .arg.check */ AVER(avgSize <= extendBy); /* .arg.check */ AVERT(Align, align); - AVERT(Bool, slotHigh); - AVERT(Bool, arenaHigh); - AVERT(Bool, firstFit); - /* This restriction on the alignment is necessary because of the use * of a Freelist to store the free address ranges in low-memory * situations. . */ - align = AlignAlignUp(align, FreelistMinimumAlignment); + AVER(AlignIsAligned(align, FreelistMinimumAlignment)); + AVERT(Bool, slotHigh); + AVERT(Bool, arenaHigh); + AVERT(Bool, firstFit); mvff = Pool2MVFF(pool); diff --git a/mps/manual/source/pool/intro.rst b/mps/manual/source/pool/intro.rst index b44fea4de98..53caa616c59 100644 --- a/mps/manual/source/pool/intro.rst +++ b/mps/manual/source/pool/intro.rst @@ -156,8 +156,8 @@ Blocks may use :term:`in-band headers`? yes yes yes yes yes :c:macro:`MPS_PF_ALIGN`. .. [7] :ref:`pool-mvt` and :ref:`pool-mvff` pools have - configurable alignment, but smaller values than - ``sizeof(void *)`` are rounded up. + 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 diff --git a/mps/manual/source/pool/mvff.rst b/mps/manual/source/pool/mvff.rst index 199b56f0a28..02721fc1e20 100644 --- a/mps/manual/source/pool/mvff.rst +++ b/mps/manual/source/pool/mvff.rst @@ -79,8 +79,8 @@ MVFF properties * Allocations may be variable in size. -* The :term:`alignment` of blocks is configurable, but smaller - alignments than ``sizeof(void *)`` are rounded up. +* The :term:`alignment` of blocks is configurable, but may not be + smaller than ``sizeof(void *)``. * Blocks do not have :term:`dependent objects`. @@ -130,8 +130,7 @@ MVFF 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 *)``; you can pass a smaller alignment - but it will be rounded up. + class is ``sizeof(void *)``. * :c:macro:`MPS_KEY_MVFF_ARENA_HIGH` (type :c:type:`mps_bool_t`, default false) determines whether new segments are acquired at high diff --git a/mps/manual/source/pool/mvt.rst b/mps/manual/source/pool/mvt.rst index 351adc9ff8f..4f89b8d5178 100644 --- a/mps/manual/source/pool/mvt.rst +++ b/mps/manual/source/pool/mvt.rst @@ -78,8 +78,8 @@ MVT properties * Allocations may be variable in size. -* The :term:`alignment` of blocks is configurable, but smaller - alignments than ``sizeof(void *)`` are rounded up. +* The :term:`alignment` of blocks is configurable, but may not be + smaller than ``sizeof(void *)``. * Blocks do not have :term:`dependent objects`. @@ -120,8 +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 *)``; you can pass a smaller alignment but it will - be rounded up. + ``sizeof(void *)``. * :c:macro:`MPS_KEY_MIN_SIZE` (type :c:type:`size_t`, default is :c:macro:`MPS_PF_ALIGN`) is the diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 71e88e48c9f..a5ece72768e 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -34,13 +34,10 @@ Interface changes in a :ref:`pool-mv` pool, by passing the :c:macro:`MPS_KEY_ALIGN` keyword argument to :c:func:`mps_pool_create_k`. -#. It is now possible to specify any alignment for :ref:`pool-mvff` - and :ref:`pool-mvt` pools. Alignments smaller than - ``sizeof(void *)`` are rounded up automatically. This means that on - the platforms ``w3i3mv`` and ``w3i6mv``, where - :c:macro:`MPS_PF_ALIGN` is larger than ``sizeof(void *)``, it is - now possible to specify the latter as the alignment for these - pools. +#. 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. Other changes From 0bae62a7fef47ff8e20287e9bf0f201596c8dac9 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 13:02:18 +0100 Subject: [PATCH 05/17] Remove comment from mpscmv2.h -- it's obsolete (no such thing as mps_count_t) and anyway documentation is now in the manual. Copied from Perforce Change: 185382 ServerID: perforce.ravenbrook.com --- mps/code/mpscmv2.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/mps/code/mpscmv2.h b/mps/code/mpscmv2.h index 8490b8f311a..8586a639901 100644 --- a/mps/code/mpscmv2.h +++ b/mps/code/mpscmv2.h @@ -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: From 7089721738ab82b1a128262386400fc778783a49 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 13:04:28 +0100 Subject: [PATCH 06/17] Assertion about alignment in mvfree might catch some errors at an earlier and more comprehensible point in the code. Copied from Perforce Change: 185383 ServerID: perforce.ravenbrook.com --- mps/code/poolmv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 7e7ef74df77..32f66dc4329 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -622,6 +622,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); From d36670e39db44233c00e6be10dddcd19c65ffaaa Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 13:13:09 +0100 Subject: [PATCH 07/17] Update the stress test cases (apss, mpmss, sacss) so that they test different alignments. Copied from Perforce Change: 185384 ServerID: perforce.ravenbrook.com --- mps/code/apss.c | 86 +++++++++++++++++++++------------------- mps/code/fbmtest.c | 3 +- mps/code/fotest.c | 4 +- mps/code/mpm.h | 2 +- mps/code/mpmss.c | 97 ++++++++++++++++++++++++++++------------------ mps/code/mv2test.c | 45 ++++++++++----------- mps/code/sacss.c | 90 +++++++++++++++++++++++------------------- 7 files changed, 183 insertions(+), 144 deletions(-) diff --git a/mps/code/apss.c b/mps/code/apss.c index 8c90536fa00..389569a97c0 100644 --- a/mps/code/apss.c +++ b/mps/code/apss.c @@ -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> (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, + /* .fence_template = */ (const void *)"post", + /* .fence_size = */ 4, /* .free_template = */ (const void *)"DEAD", /* .free_size = */ 4 }; static mps_pool_debug_option_s fenceOptions = { - /* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0", - /* .fence_size = */ 16, + /* .fence_template = */ (const 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); } diff --git a/mps/code/fbmtest.c b/mps/code/fbmtest.c index 9f3754b3496..bf1ae605f76 100644 --- a/mps/code/fbmtest.c +++ b/mps/code/fbmtest.c @@ -21,7 +21,6 @@ #include "mpm.h" #include "mps.h" #include "mpsavm.h" -#include "mpstd.h" #include "testlib.h" #include /* printf */ @@ -560,7 +559,7 @@ extern int main(int argc, char *argv[]) Align align; testlib_init(argc, argv); - align = (1 << rnd() % 4) * MPS_PF_ALIGN; + align = sizeof(void *) << (rnd() % 4); NAllocateTried = NAllocateSucceeded = NDeallocateTried = NDeallocateSucceeded = 0; diff --git a/mps/code/fotest.c b/mps/code/fotest.c index 9dab6650ede..2e63d4e121b 100644 --- a/mps/code/fotest.c +++ b/mps/code/fotest.c @@ -171,7 +171,7 @@ int main(int argc, char *argv[]) die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "mps_arena_create"); - alignment = (1 << (rnd() % 4)) * MPS_PF_ALIGN; + alignment = sizeof(void *) << (rnd() % 4); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, (64 + rnd() % 64) * 1024); MPS_ARGS_ADD(args, MPS_KEY_MEAN_SIZE, (1 + rnd() % 8) * 8); @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "mps_arena_create"); - alignment = (1 << (rnd() % 4)) * MPS_PF_ALIGN; + alignment = sizeof(void *) << (rnd() % 4); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ALIGN, alignment); MPS_ARGS_ADD(args, MPS_KEY_MIN_SIZE, (1 + rnd() % 4) * 4); diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 2d5b87d2fbf..d80f55429ff 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -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)) @@ -99,7 +100,6 @@ extern Addr (AddrAlignDown)(Addr addr, Align align); #define IndexAlignDown(s, a) ((Index)WordAlignDown((Word)(s), a)) #define AlignIsAligned(a1, a2) WordIsAligned((Word)(a1), a2) -#define AlignAlignUp(s, a) ((Align)WordAlignUp((Word)(s), a)) extern Addr (AddrSet)(Addr target, Byte value, Size size); diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c index 339ae5b54f4..e58d60550e8 100644 --- a/mps/code/mpmss.c +++ b/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,82 @@ static size_t fixedSize(size_t i) static mps_pool_debug_option_s bothOptions = { - /* .fence_template = */ (const void *)"postpostpostpost", - /* .fence_size = */ MPS_PF_ALIGN, + /* .fence_template = */ (const void *)"post", + /* .fence_size = */ 4, /* .free_template = */ (const void *)"DEAD", /* .free_size = */ 4 }; static mps_pool_debug_option_s fenceOptions = { - /* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0", - /* .fence_size = */ 16, + /* .fence_template = */ (const 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) { + 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, randomSize8, "MVFF", mps_class_mvff(), args), + "stress MVFF"); + } MPS_ARGS_END(args); + /* 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"); - printf("MFS\n"); - fixedSizeSize = 13; - die(stress(mps_class_mfs(), fixedSize, arena, (size_t)100000, fixedSizeSize), + 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; diff --git a/mps/code/mv2test.c b/mps/code/mv2test.c index 40d53d0589f..bf29f61981f 100644 --- a/mps/code/mv2test.c +++ b/mps/code/mv2test.c @@ -6,14 +6,10 @@ #include #include -#include "mpstd.h" #include #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 -#include "mpstd.h" #include -#include #include @@ -45,21 +43,21 @@ 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, size_t (*size)(size_t i), + const char *name, mps_class_t pool_class, + mps_arg_s *args, size_t classes_count, + mps_sac_classes_s *classes) { 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]; - 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; @@ -125,9 +123,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; @@ -141,55 +139,69 @@ static size_t randomSize8(size_t i) /* testInArena -- test all the pool classes in the given arena */ static mps_pool_debug_option_s debugOptions = { - /* .fence_template = */ (const void *)"postpostpostpost", - /* .fence_size = */ MPS_PF_ALIGN, + /* .fence_template = */ (const void *)"post", + /* .fence_size = */ 4, /* .free_template = */ (const 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}, + {8, 1, 1}, + {16, 1, 2}, + {136, 9, 5}, {topClassSIZE, 9, 4} }; -static void testInArena(mps_arena_t 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_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + 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, randomSize, "MVFF", mps_class_mvff(), args, + classCOUNT, classes), + "stress MVFF"); + } MPS_ARGS_END(args); + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + die(stress(arena, randomSize, "MV", mps_class_mv(), args, + classCOUNT, classes), + "stress MV"); + } MPS_ARGS_END(args); + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &debugOptions); + die(stress(arena, randomSize, "MV debug", mps_class_mv_debug(), args, + classCOUNT, classes), + "stress MV debug"); + } 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; From ae8e213a3b8a8143c45f0a7125085699499ae45c Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 13:30:36 +0100 Subject: [PATCH 08/17] Mvff debug now supports alloc/free of large objects (by exposing and covering all segments which the object overlaps) Copied from Perforce Change: 185386 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 34 ++++++++++++++++++---------------- mps/code/mpmss.c | 12 ++++++++++-- mps/code/sacss.c | 11 +++++++++++ 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index ef78360c182..3cf73aa9859 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -320,21 +320,22 @@ static Bool patternCheck(const void *pattern, Size size, Addr base, Addr limit) static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) { 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)); } patternCopy(debug->freeTemplate, debug->freeSize, base, limit); - if (inSeg) { - ShieldCover(arena, seg); + if (SegOfAddr(&seg, arena, base)) { + do { + ShieldCover(arena, seg); + } while (SegLimit(seg) < limit && SegNext(&seg, arena, seg)); } } @@ -345,21 +346,22 @@ static Bool freeCheck(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) { 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)); } res = patternCheck(debug->freeTemplate, debug->freeSize, base, limit); - if (inSeg) { - ShieldCover(arena, seg); + if (SegOfAddr(&seg, arena, base)) { + do { + ShieldCover(arena, seg); + } while (SegLimit(seg) < limit && SegNext(&seg, arena, seg)); } return res; } diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c index e58d60550e8..45b6e5f8f42 100644 --- a/mps/code/mpmss.c +++ b/mps/code/mpmss.c @@ -154,8 +154,16 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args, "stress MVFF"); } MPS_ARGS_END(args); - /* IWBN to test MVFFDebug, but the MPS doesn't support debugging */ - /* cross-segment allocation (possibly MVFF ought not to). */ + 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); diff --git a/mps/code/sacss.c b/mps/code/sacss.c index c36a2986b78..ee759cfae29 100644 --- a/mps/code/sacss.c +++ b/mps/code/sacss.c @@ -169,6 +169,17 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args) "stress MVFF"); } MPS_ARGS_END(args); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + 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, randomSize, "MVFF debug", mps_class_mvff_debug(), args, + classCOUNT, classes), + "stress MVFF debug"); + } MPS_ARGS_END(args); + MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); die(stress(arena, randomSize, "MV", mps_class_mv(), args, From d7d04e024cae2eeb4515afa548a565a4a075f1c2 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 14:37:39 +0100 Subject: [PATCH 09/17] Size class structures (mps_sac_class_s) are public, so should have names starting with "mps_" (these were removed incorrectly in change 179383). Copied from Perforce Change: 185389 ServerID: perforce.ravenbrook.com --- mps/code/mps.h | 6 +++--- mps/code/sac.c | 28 ++++++++++++++-------------- mps/manual/source/topic/cache.rst | 6 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/mps/code/mps.h b/mps/code/mps.h index b948a5f8d7d..58cbb2ebf88 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h @@ -325,9 +325,9 @@ typedef struct _mps_sac_s { /* .sacc: Keep in sync with . */ 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 diff --git a/mps/code/sac.c b/mps/code/sac.c index 435988cf867..3854a40b0d5 100644 --- a/mps/code/sac.c +++ b/mps/code/sac.c @@ -113,10 +113,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 */ } @@ -124,7 +124,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); /* */ } @@ -132,10 +132,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 */ @@ -151,9 +151,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; @@ -161,19 +161,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; diff --git a/mps/manual/source/topic/cache.rst b/mps/manual/source/topic/cache.rst index fc523161a21..589e5e86db0 100644 --- a/mps/manual/source/topic/cache.rst +++ b/mps/manual/source/topic/cache.rst @@ -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. From 6207b83839c9febdf6d566e834a7804cd36f85ce Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 14:38:20 +0100 Subject: [PATCH 10/17] Sac stress test now tests with a variety of alignments, and tests the mfs class too. Copied from Perforce Change: 185390 ServerID: perforce.ravenbrook.com --- mps/code/sacss.c | 75 +++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/mps/code/sacss.c b/mps/code/sacss.c index ee759cfae29..549bcb95fd2 100644 --- a/mps/code/sacss.c +++ b/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" @@ -26,9 +27,6 @@ #define testSetSIZE 200 #define testLOOPS 10 -#define topClassSIZE 0xA00 -#define classCOUNT 4 - /* make -- allocate an object */ @@ -43,10 +41,10 @@ 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_arena_t arena, size_t (*size)(size_t i), +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, size_t classes_count, - mps_sac_classes_s *classes) + mps_arg_s *args) { mps_res_t res; mps_pool_t pool; @@ -54,6 +52,16 @@ static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i), 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 *)); + } printf("%s\n", name); @@ -61,7 +69,8 @@ static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i), 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) { @@ -136,7 +145,16 @@ static size_t randomSize(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 *)"post", @@ -145,12 +163,8 @@ static mps_pool_debug_option_s debugOptions = { /* .free_size = */ 4 }; -static mps_sac_classes_s classes[4] = { - {8, 1, 1}, - {16, 1, 2}, - {136, 9, 5}, - {topClassSIZE, 9, 4} -}; + +/* testInArena -- test all the pool classes in the given arena */ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args) { @@ -160,41 +174,50 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args) "mps_arena_create"); MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + 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, randomSize, "MVFF", mps_class_mvff(), args, - classCOUNT, classes), + die(stress(arena, align, randomSize, "MVFF", mps_class_mvff(), args), "stress MVFF"); } MPS_ARGS_END(args); MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + 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, randomSize, "MVFF debug", mps_class_mvff_debug(), args, - classCOUNT, classes), + die(stress(arena, align, randomSize, "MVFF debug", + mps_class_mvff_debug(), args), "stress MVFF debug"); } MPS_ARGS_END(args); MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_ALIGN, 8); - die(stress(arena, randomSize, "MV", mps_class_mv(), args, - classCOUNT, classes), + 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_ARGS_ADD(args, MPS_KEY_ALIGN, 8); + 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, randomSize, "MV debug", mps_class_mv_debug(), args, - classCOUNT, classes), + 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); } From a5a1a9e03f11121df802d4e6f2303e52c9347756 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 17:58:09 +0100 Subject: [PATCH 11/17] Avoid "cast discards const qualifier from pointer target type" from gcc. Copied from Perforce Change: 185406 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 3cf73aa9859..e477f424b2d 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -252,12 +252,12 @@ static void patternCopy(const void *pattern, Size size, Addr base, Addr limit) p = end; } else if (p < rounded && rounded <= end && rounded <= limit) { /* Copy up to rounded */ - (void)AddrCopy(p, AddrAdd(pattern, offset), AddrOffset(p, rounded)); + (void)AddrCopy(p, (const char *)pattern + offset, AddrOffset(p, rounded)); p = rounded; } else { /* Copy up to limit */ AVER(limit <= end && (p == rounded || limit <= rounded)); - (void)AddrCopy(p, AddrAdd(pattern, offset), AddrOffset(p, limit)); + (void)AddrCopy(p, (const char *)pattern + offset, AddrOffset(p, limit)); p = limit; } } @@ -296,13 +296,13 @@ static Bool patternCheck(const void *pattern, Size size, Addr base, Addr limit) p = end; } else if (p < rounded && rounded <= end && rounded <= limit) { /* Copy up to rounded */ - if (AddrComp(p, AddrAdd(pattern, offset), AddrOffset(p, rounded)) != 0) + if (AddrComp(p, (const 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, AddrAdd(pattern, offset), AddrOffset(p, limit)) != 0) + if (AddrComp(p, (const char *)pattern + offset, AddrOffset(p, limit)) != 0) return FALSE; p = limit; } From 0cd88eda36203dda81b0606b2fdae6c00f9019d5 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 18:17:59 +0100 Subject: [PATCH 12/17] Add release notes entries for job003749 and job003751. Copied from Perforce Change: 185409 ServerID: perforce.ravenbrook.com --- mps/manual/source/release.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index a5ece72768e..5fbc7bb2067 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -39,6 +39,11 @@ Interface changes 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. + Other changes ............. @@ -49,6 +54,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/ + .. _release-notes-1.113: From 814595296d0d5b67821e6e0382f3442527be6b2c Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 9 Apr 2014 19:00:50 +0100 Subject: [PATCH 13/17] Remove claim ".fence.size guarantees the template is larger" since this is no longer true. update debugging pool design to record the newly discovered portability requirement. Copied from Perforce Change: 185411 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 11 +++++------ mps/design/object-debug.txt | 22 +++++++++++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index e477f424b2d..4fca4df402b 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -408,12 +408,11 @@ 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. */ diff --git a/mps/design/object-debug.txt b/mps/design/object-debug.txt index 300a4e261a8..b99049a9d1d 100644 --- a/mps/design/object-debug.txt +++ b/mps/design/object-debug.txt @@ -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/ From 02e0595e2f21f1e6532ac26e8cf273811015d9f3 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 13 Apr 2014 10:28:19 +0100 Subject: [PATCH 14/17] Comment is no longer true: now handle blocks that span segments. Copied from Perforce Change: 185487 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 4fca4df402b..b4b724ca3b3 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -312,10 +312,7 @@ static Bool patternCheck(const void *pattern, Size size, Addr base, Addr limit) } -/* freeSplat -- splat free block with splat pattern - * - * If base is in a segment, the whole block has to be in it. - */ +/* freeSplat -- splat free block with splat pattern */ static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) { From f7dd0b6c467640fd2d4929a72fd515f70ddb0805 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 13 Apr 2014 18:02:10 +0100 Subject: [PATCH 15/17] Provide a default value for mps_key_pool_debug_options. Don't use const in the types of the debugging templates: it's infectious! Copied from Perforce Change: 185489 ServerID: perforce.ravenbrook.com --- mps/code/amsss.c | 2 +- mps/code/apss.c | 6 +++--- mps/code/dbgpool.c | 30 +++++++++++++++------------ mps/code/mpmss.c | 6 +++--- mps/code/mps.h | 4 ++-- mps/code/sacss.c | 4 ++-- mps/manual/source/topic/debugging.rst | 10 ++++----- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/mps/code/amsss.c b/mps/code/amsss.c index 1d04f199349..1d5b84bbc1a 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -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(void *arg, size_t haveAmbigous) { diff --git a/mps/code/apss.c b/mps/code/apss.c index 389569a97c0..81edbe7d04d 100644 --- a/mps/code/apss.c +++ b/mps/code/apss.c @@ -121,14 +121,14 @@ static size_t randomSizeAligned(size_t i, mps_align_t align) static mps_pool_debug_option_s bothOptions = { - /* .fence_template = */ (const void *)"post", + /* .fence_template = */ (void *)"post", /* .fence_size = */ 4, - /* .free_template = */ (const void *)"DEAD", + /* .free_template = */ (void *)"DEAD", /* .free_size = */ 4 }; static mps_pool_debug_option_s fenceOptions = { - /* .fence_template = */ (const void *)"123456789abcdef", + /* .fence_template = */ (void *)"123456789abcdef", /* .fence_size = */ 15, /* .free_template = */ NULL, /* .free_size = */ 0 diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index b4b724ca3b3..7201e166249 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -123,10 +123,14 @@ Bool PoolDebugOptionsCheck(PoolDebugOptions opt) ARG_DEFINE_KEY(pool_debug_options, PoolDebugOptions); +static PoolDebugOptionsStruct debugPoolOptionsDefault = { + (void *)"POST", 4, (void *)"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); @@ -230,7 +232,7 @@ static void DebugPoolFinish(Pool pool) * Keep in sync with patternCheck. */ -static void patternCopy(const void *pattern, Size size, Addr base, Addr limit) +static void patternCopy(Addr pattern, Size size, Addr base, Addr limit) { Addr p; @@ -239,7 +241,8 @@ static void patternCopy(const void *pattern, Size size, Addr base, Addr limit) AVER(base != NULL); AVER(base <= limit); - for (p = base; p < limit; ) { + p = base; + while (p < limit) { Addr end = AddrAdd(p, size); Addr rounded = AddrRoundUp(p, size); Size offset = (Word)p % size; @@ -252,12 +255,12 @@ static void patternCopy(const void *pattern, Size size, Addr base, Addr limit) p = end; } else if (p < rounded && rounded <= end && rounded <= limit) { /* Copy up to rounded */ - (void)AddrCopy(p, (const char *)pattern + offset, AddrOffset(p, 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, (const char *)pattern + offset, AddrOffset(p, limit)); + (void)AddrCopy(p, (char *)pattern + offset, AddrOffset(p, limit)); p = limit; } } @@ -273,7 +276,7 @@ static void patternCopy(const void *pattern, Size size, Addr base, Addr limit) * Keep in sync with patternCopy. */ -static Bool patternCheck(const void *pattern, Size size, Addr base, Addr limit) +static Bool patternCheck(Addr pattern, Size size, Addr base, Addr limit) { Addr p; @@ -282,7 +285,8 @@ static Bool patternCheck(const void *pattern, Size size, Addr base, Addr limit) AVER(base != NULL); AVER(base <= limit); - for (p = base; p < limit; ) { + p = base; + while (p < limit) { Addr end = AddrAdd(p, size); Addr rounded = AddrRoundUp(p, size); Size offset = (Word)p % size; @@ -296,13 +300,13 @@ static Bool patternCheck(const void *pattern, Size size, Addr base, Addr limit) p = end; } else if (p < rounded && rounded <= end && rounded <= limit) { /* Copy up to rounded */ - if (AddrComp(p, (const char *)pattern + offset, AddrOffset(p, rounded)) != 0) + 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, (const char *)pattern + offset, AddrOffset(p, limit)) != 0) + if (AddrComp(p, (char *)pattern + offset, AddrOffset(p, limit)) != 0) return FALSE; p = limit; } diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c index 45b6e5f8f42..a2019bca0f5 100644 --- a/mps/code/mpmss.c +++ b/mps/code/mpmss.c @@ -121,14 +121,14 @@ static size_t fixedSize(size_t i) static mps_pool_debug_option_s bothOptions = { - /* .fence_template = */ (const void *)"post", + /* .fence_template = */ (void *)"post", /* .fence_size = */ 4, - /* .free_template = */ (const void *)"DEAD", + /* .free_template = */ (void *)"DEAD", /* .free_size = */ 4 }; static mps_pool_debug_option_s fenceOptions = { - /* .fence_template = */ (const void *)"123456789abcdef", + /* .fence_template = */ (void *)"123456789abcdef", /* .fence_size = */ 15, /* .free_template = */ NULL, /* .free_size = */ 0 diff --git a/mps/code/mps.h b/mps/code/mps.h index 58cbb2ebf88..315fe2012e7 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h @@ -753,9 +753,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; diff --git a/mps/code/sacss.c b/mps/code/sacss.c index 549bcb95fd2..7148338584d 100644 --- a/mps/code/sacss.c +++ b/mps/code/sacss.c @@ -157,9 +157,9 @@ static size_t fixedSize(size_t i) static mps_pool_debug_option_s debugOptions = { - /* .fence_template = */ (const void *)"post", + /* .fence_template = */ (void *)"post", /* .fence_size = */ 4, - /* .free_template = */ (const void *)"DEAD", + /* .free_template = */ (void *)"DEAD", /* .free_size = */ 4 }; diff --git a/mps/manual/source/topic/debugging.rst b/mps/manual/source/topic/debugging.rst index 942f8fa5987..1f2cb498cf4 100644 --- a/mps/manual/source/topic/debugging.rst +++ b/mps/manual/source/topic/debugging.rst @@ -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 *)"fencepost", 9, - (const void *)"free", 4, + "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; From 6b4cfb526389e047929a2f35c6cbfd5b5de52c06 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 13 Apr 2014 19:23:33 +0100 Subject: [PATCH 16/17] Avoid "cast discards const qualifier from pointer target type" error from gcc. Copied from Perforce Change: 185491 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 7201e166249..79e34c603ac 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -123,8 +123,11 @@ 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 = { - (void *)"POST", 4, (void *)"DEAD", 4, + debugFencepostTemplate, 4, debugFreeTemplate, 4, }; static Res DebugPoolInit(Pool pool, ArgList args) From b1fd10c2783c8f5887ef4f325b1b7b3386c51087 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 13 Apr 2014 19:52:51 +0100 Subject: [PATCH 17/17] Debug options structures are incompatible with gcc -wwrite-strings. Copied from Perforce Change: 185493 ServerID: perforce.ravenbrook.com --- mps/code/gc.gmk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mps/code/gc.gmk b/mps/code/gc.gmk index 826cb0ef659..d09db6ad180 100644 --- a/mps/code/gc.gmk +++ b/mps/code/gc.gmk @@ -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