diff --git a/mps/code/amcss.c b/mps/code/amcss.c index 3b15f7fb967..294ce224b15 100644 --- a/mps/code/amcss.c +++ b/mps/code/amcss.c @@ -312,11 +312,11 @@ int main(int argc, char *argv[]) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, scale * testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, grainSize); + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, scale * testArenaSIZE); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); } MPS_ARGS_END(args); mps_message_type_enable(arena, mps_message_type_gc()); mps_message_type_enable(arena, mps_message_type_gc_start()); - die(mps_arena_commit_limit_set(arena, scale * testArenaSIZE), "set limit"); die(mps_thread_reg(&thread, arena), "thread_reg"); test(arena, mps_class_amc(), exactRootsCOUNT); test(arena, mps_class_amcz(), 0); diff --git a/mps/code/amcsshe.c b/mps/code/amcsshe.c index fec9fb3a677..bd3ea73d068 100644 --- a/mps/code/amcsshe.c +++ b/mps/code/amcsshe.c @@ -251,10 +251,10 @@ int main(int argc, char *argv[]) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE)); + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, testArenaSIZE); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); } MPS_ARGS_END(args); mps_message_type_enable(arena, mps_message_type_gc()); - die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit"); die(mps_thread_reg(&thread, arena), "thread_reg"); test(arena, mps_class_amc(), exactRootsCOUNT); test(arena, mps_class_amcz(), 0); diff --git a/mps/code/amcssth.c b/mps/code/amcssth.c index c6e2d214b5d..3eea28df075 100644 --- a/mps/code/amcssth.c +++ b/mps/code/amcssth.c @@ -291,10 +291,10 @@ static void test_arena(int mode) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE)); + if (mode == ModeCOMMIT) + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, 2 * testArenaSIZE); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); } MPS_ARGS_END(args); - if (mode == ModeCOMMIT) - die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit"); mps_message_type_enable(arena, mps_message_type_gc()); mps_message_type_enable(arena, mps_message_type_gc_start()); diff --git a/mps/code/amsss.c b/mps/code/amsss.c index 4e1e15814f7..223bd205aea 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -209,9 +209,9 @@ int main(int argc, char *argv[]) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE)); + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, 2 * testArenaSIZE); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); } MPS_ARGS_END(args); - die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "commit_limit_set"); mps_message_type_enable(arena, mps_message_type_gc_start()); mps_message_type_enable(arena, mps_message_type_gc()); diff --git a/mps/code/apss.c b/mps/code/apss.c index 4f77e8bbc85..5192baada42 100644 --- a/mps/code/apss.c +++ b/mps/code/apss.c @@ -164,10 +164,16 @@ static mps_pool_debug_option_s fenceOptions = { }; -/* testInArena -- test all the pool classes in the given arena */ +/* test -- create arena using given class and arguments; test all the + * pool classes in this arena + */ -static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) +static void test(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); @@ -203,45 +209,36 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) die(stress(arena, NULL, align, randomSizeAligned, "MVT", mps_class_mvt(), args), "stress MVT"); } MPS_ARGS_END(args); + + mps_arena_destroy(arena); } int main(int argc, char *argv[]) { - mps_arena_t arena; - testlib_init(argc, argv); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(2*testArenaSIZE)); - die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), - "mps_arena_create"); + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, testArenaSIZE); + test(mps_arena_class_vm(), args, &fenceOptions); } MPS_ARGS_END(args); - die(mps_arena_commit_limit_set(arena, testArenaSIZE), "commit limit"); - testInArena(arena, &fenceOptions); - mps_arena_destroy(arena); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(2*testArenaSIZE)); - die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), - "mps_arena_create"); + test(mps_arena_class_vm(), args, &bothOptions); } MPS_ARGS_END(args); - testInArena(arena, &bothOptions); - mps_arena_destroy(arena); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_CL_BASE, malloc(testArenaSIZE)); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE)); - die(mps_arena_create_k(&arena, mps_arena_class_cl(), args), - "mps_arena_create"); + test(mps_arena_class_cl(), args, &bothOptions); } MPS_ARGS_END(args); - testInArena(arena, &bothOptions); - mps_arena_destroy(arena); printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); return 0; diff --git a/mps/code/arena.c b/mps/code/arena.c index 738761aaa33..93ca87fbd4f 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -197,6 +197,8 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args) { Res res; Bool zoned = ARENA_DEFAULT_ZONED; + Size commitLimit = ARENA_DEFAULT_COMMIT_LIMIT; + Size spareCommitLimit = ARENA_DEFAULT_SPARE_COMMIT_LIMIT; mps_arg_s arg; AVER(arena != NULL); @@ -205,16 +207,18 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args) if (ArgPick(&arg, args, MPS_KEY_ARENA_ZONED)) zoned = arg.val.b; + if (ArgPick(&arg, args, MPS_KEY_COMMIT_LIMIT)) + commitLimit = arg.val.size; + if (ArgPick(&arg, args, MPS_KEY_SPARE_COMMIT_LIMIT)) + spareCommitLimit = arg.val.size; arena->class = class; arena->reserved = (Size)0; arena->committed = (Size)0; - /* commitLimit may be overridden by init (but probably not */ - /* as there's not much point) */ - arena->commitLimit = (Size)-1; + arena->commitLimit = commitLimit; arena->spareCommitted = (Size)0; - arena->spareCommitLimit = ARENA_INIT_SPARE_COMMIT_LIMIT; + arena->spareCommitLimit = spareCommitLimit; arena->grainSize = grainSize; /* zoneShift is usually overridden by init */ arena->zoneShift = ARENA_ZONESHIFT; @@ -285,9 +289,11 @@ ARG_DEFINE_KEY(VMW3_TOP_DOWN, Bool); /* ArenaCreate -- create the arena and call initializers */ -ARG_DEFINE_KEY(ARENA_SIZE, Size); ARG_DEFINE_KEY(ARENA_GRAIN_SIZE, Size); +ARG_DEFINE_KEY(ARENA_SIZE, Size); ARG_DEFINE_KEY(ARENA_ZONED, Bool); +ARG_DEFINE_KEY(COMMIT_LIMIT, Size); +ARG_DEFINE_KEY(SPARE_COMMIT_LIMIT, Size); static Res arenaFreeLandInit(Arena arena) { @@ -1325,7 +1331,6 @@ void ArenaSetSpareCommitLimit(Arena arena, Size limit) } EVENT2(SpareCommitLimitSet, arena, limit); - return; } /* Used by arenas which don't use spare committed memory */ diff --git a/mps/code/config.h b/mps/code/config.h index 8fbd251a220..0fded6a291d 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -405,6 +405,13 @@ #define ARENA_CLIENT_GRAIN_SIZE ((Size)8192) +#define ARENA_DEFAULT_COMMIT_LIMIT ((Size)-1) + +/* TODO: This should be proportional to the memory usage of the MPS, not + * a constant. That will require design, and then some interface and + * documenation changes. */ +#define ARENA_DEFAULT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL) + #define ARENA_DEFAULT_ZONED TRUE #define ArenaDefaultZONESET (ZoneSetUNIV << (MPS_WORD_WIDTH / 2)) @@ -611,11 +618,6 @@ #define MPS_PROD_STRING "mps" #define MPS_PROD_MPS -/* TODO: This should be proportional to the memory usage of the MPS, not - a constant. That will require design, and then some interface and - documenation changes. */ -#define ARENA_INIT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL) - /* Default chain for GC pools * diff --git a/mps/code/locusss.c b/mps/code/locusss.c index 70cf313ed45..b3769dd674a 100644 --- a/mps/code/locusss.c +++ b/mps/code/locusss.c @@ -219,13 +219,11 @@ static void runArenaTest(size_t size, MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, size); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, size - chunkSize); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "mps_arena_create"); } MPS_ARGS_END(args); - die(mps_arena_commit_limit_set(arena, size - chunkSize), - "mps_arena_commit_limit_set"); - testInArena(arena, failcase, usefulFailcase); mps_arena_destroy(arena); diff --git a/mps/code/mps.h b/mps/code/mps.h index 4e75d49b73a..d9e750417e0 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h @@ -155,12 +155,12 @@ extern const struct mps_key_s _mps_key_ARGS_END; #define MPS_KEY_ARGS_END (&_mps_key_ARGS_END) extern mps_arg_s mps_args_none[]; -extern const struct mps_key_s _mps_key_ARENA_SIZE; -#define MPS_KEY_ARENA_SIZE (&_mps_key_ARENA_SIZE) -#define MPS_KEY_ARENA_SIZE_FIELD size extern const struct mps_key_s _mps_key_ARENA_GRAIN_SIZE; #define MPS_KEY_ARENA_GRAIN_SIZE (&_mps_key_ARENA_GRAIN_SIZE) #define MPS_KEY_ARENA_GRAIN_SIZE_FIELD size +extern const struct mps_key_s _mps_key_ARENA_SIZE; +#define MPS_KEY_ARENA_SIZE (&_mps_key_ARENA_SIZE) +#define MPS_KEY_ARENA_SIZE_FIELD size extern const struct mps_key_s _mps_key_ARENA_ZONED; #define MPS_KEY_ARENA_ZONED (&_mps_key_ARENA_ZONED) #define MPS_KEY_ARENA_ZONED_FIELD b @@ -176,6 +176,12 @@ extern const struct mps_key_s _mps_key_GEN; extern const struct mps_key_s _mps_key_RANK; #define MPS_KEY_RANK (&_mps_key_RANK) #define MPS_KEY_RANK_FIELD rank +extern const struct mps_key_s _mps_key_COMMIT_LIMIT; +#define MPS_KEY_COMMIT_LIMIT (&_mps_key_COMMIT_LIMIT) +#define MPS_KEY_COMMIT_LIMIT_FIELD size +extern const struct mps_key_s _mps_key_SPARE_COMMIT_LIMIT; +#define MPS_KEY_SPARE_COMMIT_LIMIT (&_mps_key_SPARE_COMMIT_LIMIT) +#define MPS_KEY_SPARE_COMMIT_LIMIT_FIELD size extern const struct mps_key_s _mps_key_EXTEND_BY; #define MPS_KEY_EXTEND_BY (&_mps_key_EXTEND_BY) diff --git a/mps/code/mpsicv.c b/mps/code/mpsicv.c index c90230c85a6..44036efead9 100644 --- a/mps/code/mpsicv.c +++ b/mps/code/mpsicv.c @@ -324,6 +324,7 @@ static mps_res_t root_single(mps_ss_t ss, void *p, size_t s) * mps_arena_reserved * incidentally tests: * mps_alloc + * mps_arena_commit_limit_set * mps_class_mv * mps_pool_create * mps_pool_destroy diff --git a/mps/design/arena.txt b/mps/design/arena.txt index a72bfbcb09c..2a94bb05b39 100644 --- a/mps/design/arena.txt +++ b/mps/design/arena.txt @@ -432,13 +432,13 @@ bytes; ``spareCommitLimit`` records the limit (set by the user) on the amount of spare committed memory. ``spareCommitted`` is modified by the arena class but its value is used by the generic arena code. There are two uses: a getter function for this value is provided through the -MPS interface (``mps_arena_spare_commit_limit_set()``), and by the -``SetSpareCommitLimit()`` function to determine whether the amount of -spare committed memory needs to be reduced. ``spareCommitLimit`` is -manipulated by generic arena code, however the associated semantics -are the responsibility of the class. It is the class's responsibility -to ensure that it doesn't use more spare committed bytes than the -value in ``spareCommitLimit``. +MPS interface (``mps_arena_spare_commit_limit()``), and by the +``ArenaSetSpareCommitLimit()`` function to determine whether the +amount of spare committed memory needs to be reduced. +``spareCommitLimit`` is manipulated by generic arena code, however the +associated semantics are the responsibility of the class. It is the +class's responsibility to ensure that it doesn't use more spare +committed bytes than the value in ``spareCommitLimit``. _`.spare-commit-limit`: The function ``ArenaSetSpareCommitLimit()`` sets the ``spareCommitLimit`` field. If the limit is set to a value lower diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 49fbae67579..a7e028fae2a 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -17,6 +17,12 @@ New features specifying the minimum size of the memory segments that the pool requests from the :term:`arena`. +#. The function :c:func:`mps_arena_create_k` accepts two new + :term:`keyword arguments`. :c:macro:`MPS_KEY_COMMIT_LIMIT` + sets the :term:`commit limit` for the arena, and + :c:macro:`MPS_KEY_SPARE_COMMIT_LIMIT` sets the :term:`spare + commit limit` for the arena. + Interface changes ................. @@ -31,7 +37,6 @@ Interface changes deprecated in favour of the generic functions :c:func:`mps_pool_free_size` and :c:func:`mps_pool_total_size`. - Other changes ............. diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst index d33242e279d..f98de4ba56d 100644 --- a/mps/manual/source/topic/arena.rst +++ b/mps/manual/source/topic/arena.rst @@ -139,7 +139,14 @@ Client arenas * :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`) is its size. - It also accepts one optional keyword argument: + It also accepts two optional keyword arguments: + + * :c:macro:`MPS_KEY_COMMIT_LIMIT` (type :c:type:`size_t`) is + the maximum amount of memory, in :term:`bytes (1)`, that the MPS + will use out of the provided chunk (or chunks, if the arena is + extended). See :c:func:`mps_arena_commit_limit` for details. The + default commit limit is the maximum value of the + :c:type:`size_t` type. * :c:macro:`MPS_KEY_ARENA_GRAIN_SIZE` (type :c:type:`size_t`, default 8192) is the granularity with which the arena will @@ -206,7 +213,7 @@ Virtual memory arenas more efficient. When creating a virtual memory arena, :c:func:`mps_arena_create_k` - accepts two optional :term:`keyword arguments` on all platforms: + accepts four optional :term:`keyword arguments` on all platforms: * :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`, default 256 :term:`megabytes`) is the initial amount of virtual address @@ -233,6 +240,12 @@ Virtual memory arenas more times it has to extend its address space, the less efficient garbage collection will become. + * :c:macro:`MPS_KEY_COMMIT_LIMIT` (type :c:type:`size_t`) is + the maximum amount of main memory, in :term:`bytes (1)`, that + the MPS will obtain from the operating system. See + :c:func:`mps_arena_commit_limit` for details. The default commit + limit is the maximum value of the :c:type:`size_t` type. + * :c:macro:`MPS_KEY_ARENA_GRAIN_SIZE` (type :c:type:`size_t`) is the granularity with which the arena will manage memory internally. It must be a power of 2. If not provided, the @@ -244,12 +257,18 @@ Virtual memory arenas that's smaller than the operating system page size, the MPS rounds it up to the page size and continues. - A third optional :term:`keyword argument` may be passed, but it + * :c:macro:`MPS_KEY_SPARE_COMMIT_LIMIT` (type + :c:type:`size_t`, default 0) is the spare commit limit in + :term:`bytes (1)`. See :c:func:`mps_arena_spare_commit_limit` + for details. + + A fifth optional :term:`keyword argument` may be passed, but it only has any effect on the Windows operating system: - * :c:macro:`MPS_KEY_VMW3_TOP_DOWN` (type :c:type:`mps_bool_t`). If - true, the arena will allocate address space starting at the - highest possible address and working downwards through memory. + * :c:macro:`MPS_KEY_VMW3_TOP_DOWN` (type :c:type:`mps_bool_t`, + default false). If true, the arena will allocate address space + starting at the highest possible address and working downwards + through memory. .. note:: @@ -298,10 +317,42 @@ Arena properties ``arena`` is the arena to return the commit limit for. - Returns the commit limit in :term:`bytes (1)`. The commit limit - controls how much memory the MPS can obtain from the operating - system, and can be changed by calling - :c:func:`mps_arena_commit_limit_set`. + Returns the commit limit in :term:`bytes (1)`. + + For a :term:`client arena`, this this the maximum amount of + memory, in :term:`bytes (1)`, that the MPS will use out of the + chunks provided by the client to the arena. + + For a :term:`virtual memory arena`, this is the maximum amount of + memory that the MPS will map to RAM via the operating system's + virtual memory interface. + + The commit limit can be set by passing the + :c:macro:`MPS_KEY_COMMIT_LIMIT` :term:`keyword argument` to + :c:func:`mps_arena_create_k`. It can be changed by calling + :c:func:`mps_arena_commit_limit_set`. The + commit limit cannot be set to a value that is lower than the + number of bytes that the MPS is using. If an attempt is made to + set the commit limit to a value greater than or equal to that + returned by :c:func:`mps_arena_committed` then it will succeed. If + an attempt is made to set the commit limit to a value less than + that returned by :c:func:`mps_arena_committed` then it will + succeed only if the amount committed by the MPS can be reduced by + reducing the amount of spare committed memory; in such a case the + spare committed memory will be reduced appropriately and the + attempt will succeed. + + .. note:: + + The commit limit puts a limit on all memory committed by the + MPS. The :term:`spare committed memory` (that is, memory + committed by the MPS but not currently in use, neither by the + :term:`client program`, or by the MPS itself) can be limited + separately; see :c:func:`mps_arena_spare_committed`. Note that + "spare committed" memory is subject to both limits; there + cannot be more spare committed memory than the spare commit + limit, and there can't be so much spare committed memory that + there is more committed memory than the commit limit. .. c:function:: mps_res_t mps_arena_commit_limit_set(mps_arena_t arena, size_t limit) @@ -315,29 +366,7 @@ Arena properties Returns :c:macro:`MPS_RES_OK` if successful, or another :term:`result code` if not. - If successful, the commit limit for ``arena`` is set to ``limit``. The - commit limit controls how much memory the MPS will obtain from the - operating system. The commit limit cannot be set to a value that - is lower than the number of bytes that the MPS is using. If an - attempt is made to set the commit limit to a value greater than or - equal to that returned by :c:func:`mps_arena_committed` then it - will succeed. If an attempt is made to set the commit limit to a - value less than that returned by :c:func:`mps_arena_committed` - then it will succeed only if the amount committed by the MPS can - be reduced by reducing the amount of spare committed memory; in - such a case the spare committed memory will be reduced - appropriately and the attempt will succeed. - - .. note:: - - :c:func:`mps_arena_commit_limit_set` puts a limit on all - memory committed by the MPS. The :term:`spare committed - memory` can be limited separately with - :c:func:`mps_arena_spare_commit_limit_set`. Note that "spare - committed" memory is subject to both limits; there cannot be - more spare committed memory than the spare commit limit, and - there can't be so much spare committed memory that there is - more committed memory than the commit limit. + See :c:func:`mps_arena_spare_commit_limit` for details. .. c:function:: size_t mps_arena_committed(mps_arena_t arena) @@ -428,32 +457,20 @@ Arena properties ``arena`` is the arena to return the spare commit limit for. Returns the spare commit limit in :term:`bytes (1)`. The spare - commit limit can be changed by calling - :c:func:`mps_arena_spare_commit_limit_set`. + commit limit is the maximum amount of :term:`spare committed + memory` (that is, memory committed by the MPS but not currently in + use, neither by the :term:`client program`, or by the MPS itself) + the MPS is allowed to have. - -.. c:function:: void mps_arena_spare_commit_limit_set(mps_arena_t arena, size_t limit) - - Change the :term:`spare commit limit` for an :term:`arena`. - - ``arena`` is the arena to change the spare commit limit for. - - ``limit`` is the new spare commit limit in :term:`bytes (1)`. - - The spare commit limit is the maximum amount of :term:`spare - committed memory` the MPS is allowed to have. Setting it to a - value lower than the current amount of spare committed memory - causes spare committed memory to be uncommitted so as to bring the - value under the limit. In particular, setting it to 0 will mean - that the MPS will have no spare committed memory. - - Non-virtual-memory arena classes (for example, a :term:`client - arena`) do not have spare committed memory. For these arenas, this - function sets a value but has no other effect. - - Initially the spare commit limit is a configuration-dependent - value. The value of the limit can be retrieved by the function - :c:func:`mps_arena_spare_commit_limit`. + The spare commit limit can be set by passing the + :c:macro:`MPS_KEY_SPARE_COMMIT_LIMIT` :term:`keyword + argument` to :c:func:`mps_arena_create_k`. It can be changed + by calling :c:func:`mps_arena_spare_commit_limit_set`. + Setting it to a value lower than + the current amount of spare committed memory causes spare + committed memory to be uncommitted so as to bring the value under + the limit. In particular, setting it to 0 will mean that the MPS + will have no spare committed memory. .. c:function:: size_t mps_arena_spare_committed(mps_arena_t arena) @@ -475,12 +492,13 @@ Arena properties memory by :c:func:`mps_arena_committed` and is restricted by :c:func:`mps_arena_commit_limit`. - The amount of "spare committed" memory can be limited by calling - :c:func:`mps_arena_spare_commit_limit_set`, and the value of that - limit can be retrieved with - :c:func:`mps_arena_spare_commit_limit`. This is analogous to the - functions for limiting the amount of :term:`committed ` - memory. + The amount of "spare committed" memory can be limited passing the + :c:macro:`MPS_KEY_SPARE_COMMIT_LIMIT` :term:`keyword + argument` to :c:func:`mps_arena_create_k` or by calling + :c:func:`mps_arena_spare_commit_limit_set`. The value of the limit can be + retrieved with :c:func:`mps_arena_spare_commit_limit`. This is + analogous to the functions for limiting the amount of + :term:`committed ` memory. .. note:: @@ -488,6 +506,23 @@ Arena properties so this function always returns 0. +.. c:function:: void mps_arena_spare_commit_limit_set(mps_arena_t arena, size_t limit) + + Change the :term:`spare commit limit` for an :term:`arena`. + + ``arena`` is the arena to change the spare commit limit for. + + ``limit`` is the new spare commit limit in :term:`bytes (1)`. + + Non-virtual-memory arena classes (for example, a :term:`client + arena`) do not have spare committed memory. For these arenas, this + function sets a value but has no other effect. + + Initially the spare commit limit is a configuration-dependent + value. The value of the limit can be retrieved by the function + :c:func:`mps_arena_spare_commit_limit`. + + .. index:: single: arena; states diff --git a/mps/manual/source/topic/keyword.rst b/mps/manual/source/topic/keyword.rst index ac80333ba36..ddbfbfd57ac 100644 --- a/mps/manual/source/topic/keyword.rst +++ b/mps/manual/source/topic/keyword.rst @@ -89,10 +89,11 @@ now :c:macro:`MPS_KEY_ARGS_END`. :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` :c:macro:`MPS_KEY_ARENA_GRAIN_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_arena_class_vm`, :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` :c:macro:`MPS_KEY_AWL_FIND_DEPENDENT` ``void *(*)(void *)`` ``addr_method`` :c:func:`mps_class_awl` :c:macro:`MPS_KEY_CHAIN` :c:type:`mps_chain_t` ``chain`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz`, :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo` + :c:macro:`MPS_KEY_COMMIT_LIMIT` :c:type:`size_t` ``size`` :c:func:`mps_arena_class_vm`, :c:func:`mps_arena_class_cl` :c:macro:`MPS_KEY_EXTEND_BY` :c:type:`size_t` ``size`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz`, :c:func:`mps_class_mfs`, :c:func:`mps_class_mv`, :c:func:`mps_class_mvff` :c:macro:`MPS_KEY_FMT_ALIGN` :c:type:`mps_align_t` ``align`` :c:func:`mps_fmt_create_k` :c:macro:`MPS_KEY_FMT_CLASS` :c:type:`mps_fmt_class_t` ``fmt_class`` :c:func:`mps_fmt_create_k` @@ -117,6 +118,7 @@ now :c:macro:`MPS_KEY_ARGS_END`. :c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` :c:type:`mps_pool_debug_option_s` ``*pool_debug_options`` :c:func:`mps_class_ams_debug`, :c:func:`mps_class_mv_debug`, :c:func:`mps_class_mvff_debug` :c:macro:`MPS_KEY_RANK` :c:type:`mps_rank_t` ``rank`` :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_snc` :c:macro:`MPS_KEY_SPARE` :c:type:`double` ``d`` :c:func:`mps_class_mvff` + :c:macro:`MPS_KEY_SPARE_COMMIT_LIMIT` :c:type:`size_t` ``size`` :c:func:`mps_arena_class_vm` :c:macro:`MPS_KEY_VMW3_TOP_DOWN` :c:type:`mps_bool_t` ``b`` :c:func:`mps_arena_class_vm` ======================================== ========================================================= ========================================================== diff --git a/mps/test/function/120.c b/mps/test/function/120.c index 4bd55205998..032fa722c3f 100644 --- a/mps/test/function/120.c +++ b/mps/test/function/120.c @@ -5,6 +5,7 @@ TEST_HEADER language = c link = testlib.o OUTPUT_SPEC + create = COMMIT_LIMIT commit0 = FAIL commit10 = OK com_less = FAIL @@ -33,8 +34,16 @@ static void test(void) { int i; mps_addr_t a; mps_res_t res; + size_t committed; + + /* Create an arena with a commit limit that's too small for the + * essential MPS internal data structures -- this must fail with + * RES_COMMIT_LIMIT. */ -/* create an arena that can't grow beyond 20 M */ + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, 16 * 1024); + report_res("create", mps_arena_create_k(&arena, mps_arena_class_vm(), args)); + } MPS_ARGS_END(args); cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*20)), "create arena"); diff --git a/mps/test/function/165.c b/mps/test/function/165.c index 087d5e08f8d..5bd3bda7a44 100644 --- a/mps/test/function/165.c +++ b/mps/test/function/165.c @@ -1,7 +1,7 @@ /* TEST_HEADER id = $Id$ - summary = simple spare_commit_limit test + summary = simple spare commit limit test language = c link = testlib.o rankfmt.o harness = 2.0 @@ -32,14 +32,15 @@ static void test(void) unsigned long com0, com1, com2; -/* create a VM arena of 40MB */ +/* create a VM arena of 40MB with commit limit of 100MB, i.e. let the + arena do the limiting. */ - cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)(1024*1024*40)), - "create arena"); - -/* set the commit limit to 100MB, i.e. let the arena do the limiting */ - - mps_arena_commit_limit_set(arena, (size_t) (1024ul*1024ul*100ul)); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 1024*1024*40); + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, 1024ul*1024ul*100ul); + cdie(mps_arena_create_k(&arena, mps_arena_class_vm(), args), + "create arena"); + } MPS_ARGS_END(args); cdie(mps_thread_reg(&thread, arena), "register thread"); diff --git a/mps/test/function/231.c b/mps/test/function/231.c new file mode 100644 index 00000000000..c8c29fa44e2 --- /dev/null +++ b/mps/test/function/231.c @@ -0,0 +1,40 @@ +/* +TEST_HEADER + id = $Id$ + summary = create/configure arena with too-small commit limit + language = c + link = testlib.o +OUTPUT_SPEC + create1 = COMMIT_LIMIT + create2 = OK + configure = FAIL +END_HEADER +*/ + +#include "testlib.h" +#include "newfmt.h" + +static void test(void) +{ + mps_arena_t arena; + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, 16 * 1024); + report_res("create1", + mps_arena_create_k(&arena, mps_arena_class_vm(), args)); + } MPS_ARGS_END(args); + + report_res("create2", + mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none)); + + report_res("configure", mps_arena_commit_limit_set(arena, 16 * 1024)); + + mps_arena_destroy(arena); +} + +int main(void) +{ + easy_tramp(test); + pass(); + return 0; +} diff --git a/mps/test/testsets/passing b/mps/test/testsets/passing index 88d5e6dfa51..c6893a54c30 100644 --- a/mps/test/testsets/passing +++ b/mps/test/testsets/passing @@ -170,3 +170,4 @@ function/226.c function/227.c function/228.c function/229.c +function/231.c