1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 08:43:40 -07:00

Changes outside the code directory that should have been in changelist 184342. oops.

Copied from Perforce
 Change: 184358
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2014-02-17 17:04:23 +00:00
commit daca17fe7e
12 changed files with 133 additions and 152 deletions

View file

@ -90,6 +90,7 @@ shield_ Shield abstraction: separate control of collector access
sig_ Signatures in the MPS
splay_ Design of splay trees
sso1al_ Stack scanner for Digital Unix / Alpha systems
strategy_ Collection strategy
telemetry_ The design of the MPS telemetry mechanism
tests_ The design of MPS internal tests
thread-manager_ The design of the MPS thread manager
@ -156,6 +157,7 @@ writef_ The design of the MPS writef function
.. _sig: sig
.. _splay: splay
.. _sso1al: sso1al
.. _strategy: strategy
.. _telemetry: telemetry
.. _tests: tests
.. _thread-manager: thread-manager
@ -199,6 +201,7 @@ Document History
- 2013-05-22 GDR_ Add link to keyword-arguments.
- 2013-05-25 RB_ Replacing "cstyle" with reworked "guide.impl.c.format".
- 2013-06-07 RB_ Converting to reST_. Linking to [RB_2002-06-18]_.
- 2014-01-29 RB_ The arena no longer manages generation zonesets.
.. _RB: http://www.ravenbrook.com/consultants/rb
.. _NB: http://www.ravenbrook.com/consultants/nb

View file

@ -166,47 +166,14 @@ automatic-pool segment in any zone in the zoneset. It is not limited
to the segments actually associated with the condemned generation(s).
An attempt is made to use distinct zonesets for different generations.
Whenever a segment is allocated (``AMCBufferFill()``), a
``SegPref`` is created containing the generation number
(obtained from ``amcBuf->gen->pgen->nr``) and passed to
``SegAlloc()``. The arena keeps a zoneset for each generation
number (up to ``VMArenaGenCount``, defined in
``arenavm.c`` to be ``MPS_WORD_WIDTH/2``), and a
``freeSet``. The zoneset for each generation number starts out
empty, and the ``freeSet`` starts out ``ZoneSetUNIV``.
When a segment is allocated with a ``SegPref`` with a generation
number, an attempt is made to allocate it in the corresponding zoneset
(``pagesFindFreeInZones()``). If the zoneset is empty, an
attempt is made to allocate it in the ``freeSet`` zoneset.
After it is allocated, the zones it occupies are removed from the
``freeSet`` and (if there's a generation ``SegPref``)
added to the zoneset for that generation number.
Segments are allocated from ``AMCBufferFill()`` using ``ChainAlloc()``
which creates a ``SegPref`` using the zoneset from the generation's
``GenDesc``. The zoneset for each generation number starts out
empty. If the zoneset is empty, an attempt is made to allocate from a
free zone. The ``GenDesc`` zoneset is augmented with whichever zones the
new segment occupies.
Note that this zone placement code knows nothing of chains,
generations, pool classes, etc. It is based solely on the generation
*number*, so generations with the same number from different chains
share a zoneset preference for the purpose of placing newly allocated
segments. Combined with the fact that condemnation is per-zone, this
effectively means that generations in distinct chains are collected
together. One consequence of this is that we don't have a very fine
granularity of control over collection: a garbage collection of all
chains together is triggered by the most eager chain. There's no way
for a library or other small part of a client program to arrange
independent collection of a separate pool or chain.
When ``AMCBufferFill()`` gets the allocated segment back, it
adds it to the zoneset associated with that generation in the pool's
controlling chain. Note that a chain's per-generation zonesets, which
represent the zones in which segments for that generation in that
chain have been placed, are quite distinct from the arena-wide
per-generation-number zonesets, which represent the zones in which
segments for that generation number in any chain have been placed.
The arena-wide per-generation-number zoneset
``vmArena->genZoneSet[N]`` is augmented in
``vmAllocComm()``. The per-chain per-generation zoneset
``chain->gen[N].zones`` is augmented in
``PoolGenUpdateZones()``. Neither kind of zoneset can ever
shrink.
Note that this zoneset can never shrink.
Accounting
..........
@ -413,10 +380,12 @@ TODO: When do we do some tracing work? How much tracing work do we do?
Document History
----------------
- 2013-06-04 NB Checked this in although it's far from complete.
- 2013-06-04 NB_ Checked this in although it's far from complete.
Pasted in my 'ramping notes' from email, which mention some bugs
which I may have fixed (TODO: check this).
- 2014-01-29 RB_ The arena no longer manages generation zonesets.
.. _RB: http://www.ravenbrook.com/consultants/rb
.. _NB: http://www.ravenbrook.com/consultants/nb/

View file

@ -673,55 +673,6 @@ code must be added to ``obj_scan`` and ``obj_skip``::
:ref:`topic-format`.
.. index::
single: generation chain
single: chain; generation
single: Scheme; generation chain
Generation chains
-----------------
The AMC pool requires not only an object format but a
:term:`generation chain`. This specifies the generation structure of
the :term:`generational garbage collection`.
You create a generation chain by constructing an array of structures
of type :c:type:`mps_gen_param_s`, one for each generation, and
passing them to :c:func:`mps_chain_create`. Each of these structures
contains two values, the *capacity* of the generation in
:term:`kilobytes`, and the *mortality*, the proportion of
objects in the generation that you expect to survive a collection of
that generation.
These numbers are *hints* to the MPS that it may use to make decisions
about when and what to collect: nothing will go wrong (other than
suboptimal performance) if you make poor choices. Making good choices
for the capacity and mortality of each generation is not easy, and is postponed to the chapter :ref:`guide-perf`.
Here's the code for creating the generation chain for the toy Scheme
interpreter::
mps_gen_param_s obj_gen_params[] = {
{ 150, 0.85 },
{ 170, 0.45 },
};
res = mps_chain_create(&obj_chain,
arena,
LENGTH(obj_gen_params),
obj_gen_params);
if (res != MPS_RES_OK) error("Couldn't create obj chain");
Note that these numbers have have been deliberately chosen to be
small, so that the MPS is forced to collect often, so that you can see
it working. Don't just copy these numbers unless you also want to see
frequent garbage collections!
.. topics::
:ref:`topic-collection`.
.. index::
single: pool; creating
single: Scheme; pool
@ -748,25 +699,10 @@ Second, the :term:`object format`::
} MPS_ARGS_END(args);
if (res != MPS_RES_OK) error("Couldn't create obj format");
Third, the :term:`generation chain`::
mps_gen_param_s obj_gen_params[] = {
{ 150, 0.85 },
{ 170, 0.45 },
};
mps_chain_t obj_chain;
res = mps_chain_create(&obj_chain,
arena,
LENGTH(obj_gen_params),
obj_gen_params);
if (res != MPS_RES_OK) error("Couldn't create obj chain");
And finally the :term:`pool`::
mps_pool_t obj_pool;
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, obj_chain);
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, obj_fmt);
MPS_ARGS_DONE(args);
res = mps_pool_create_k(&obj_pool, arena, mps_class_amc(), args);
@ -1206,10 +1142,12 @@ tracking down the causes, appear in the chapter :ref:`guide-debug`.
Tidying up
----------
When your program is done with the MPS, it's good practice to tear
down all the MPS data structures. This causes the MPS to check the
consistency of its data structures and report any problems it
detects. It also causes the MPS to flush its :term:`telemetry stream`.
When your program is done with the MPS, it's good practice to
:term:`park <parked state>` the arena (by calling
:c:func:`mps_arena_park`) and then tear down all the MPS data
structures. This causes the MPS to check the consistency of its data
structures and report any problems it detects. It also causes the MPS
to flush its :term:`telemetry stream`.
MPS data structures must be destroyed or deregistered in the reverse
order to that in which they were registered or created. So you must
@ -1218,16 +1156,15 @@ destroy all :term:`allocation points` created in a
were created in an :term:`arena` before destroying the arena, and so
on.
Here's the tear-down code from the toy Scheme interpreter::
For example::
mps_arena_park(arena);
mps_ap_destroy(obj_ap);
mps_pool_destroy(obj_pool);
mps_chain_destroy(obj_chain);
mps_fmt_destroy(obj_fmt);
mps_root_destroy(reg_root);
mps_thread_dereg(thread);
mps_arena_destroy(arena);
mps_arena_park(arena); /* ensure no collection is running */
mps_ap_destroy(obj_ap); /* destroy ap before pool */
mps_pool_destroy(obj_pool); /* destroy pool before fmt */
mps_fmt_destroy(obj_fmt); /* destroy fmt before arena */
mps_root_destroy(reg_root); /* destroy root before arena */
mps_thread_dereg(thread); /* deregister thread before arena */
mps_arena_destroy(arena); /* last of all */
What next?

View file

@ -31,10 +31,6 @@ following tendencies will be efficiently exploited by an AMC pool:
- objects that don't die young will live a long time.
In the pool's :term:`generation chain`, specify the capacity and
mortality of generations 0 to *n*\1. Survivors from generation *n*\1
get promoted into an arena-wide "top" generation.
.. index::
single: AMC; properties
@ -57,6 +53,9 @@ AMC properties
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* Uses :term:`generational garbage collection`: blocks are promoted
from generation to generation in the pool's chain.
* Blocks may contain :term:`exact references` to blocks in the same or
other pools (but may not contain :term:`ambiguous references` or
:term:`weak references (1)`, and may not use :term:`remote
@ -106,7 +105,7 @@ AMC interface
Mostly-Copying) :term:`pool`.
When creating an AMC pool, :c:func:`mps_pool_create_k` requires
two :term:`keyword arguments`:
one :term:`keyword argument`:
* :c:macro:`MPS_KEY_FORMAT` (type :c:type:`mps_fmt_t`) specifies
the :term:`object format` for the objects allocated in the pool.
@ -114,13 +113,15 @@ AMC interface
method`, a :term:`forward method`, an :term:`is-forwarded
method` and a :term:`padding method`.
It accepts one optional keyword argument:
* :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies
the :term:`generation chain` for the pool.
the :term:`generation chain` for the pool. If not specified, the
pool will use the arena's default chain.
For example::
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
MPS_ARGS_DONE(args);
res = mps_pool_create_k(&pool, arena, mps_class_amc(), args);

View file

@ -60,7 +60,7 @@ AMCZ interface
Mostly-Copying Zero-rank) :term:`pool`.
When creating an AMCZ pool, :c:func:`mps_pool_create_k` requires
two :term:`keyword arguments`:
one :term:`keyword argument`:
* :c:macro:`MPS_KEY_FORMAT` (type :c:type:`mps_fmt_t`) specifies
the :term:`object format` for the objects allocated in the pool.
@ -68,13 +68,15 @@ AMCZ interface
method`, an :term:`is-forwarded method` and a :term:`padding
method`.
It accepts one optional keyword argument:
* :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies
the :term:`generation chain` for the pool.
the :term:`generation chain` for the pool. If not specified, the
pool will use the arena's default chain.
For example::
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
MPS_ARGS_DONE(args);
res = mps_pool_create_k(&pool, arena, mps_class_amcz(), args);
@ -85,7 +87,7 @@ AMCZ interface
When using :c:func:`mps_pool_create`, pass the format and
chain like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_amcz(),
mps_fmt_t fmt,
mps_chain_t chain)
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_amcz(),
mps_fmt_t fmt,
mps_chain_t chain)

View file

@ -17,11 +17,6 @@ management>` but :term:`non-moving <non-moving garbage collector>`
:term:`pool class`. It should be used instead of :ref:`pool-amc` for
blocks that need to be automatically managed, but cannot be moved.
AMS does not use :term:`generational garbage collection`, but when
creating a pool you use a :term:`generation chain` to specify the
capacity and mortality of a single "generation". These numbers are
used to schedule the collection of the whole pool.
.. note::
AMS is likely to be useful as a step in integrating a program with
@ -56,6 +51,9 @@ AMS properties
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* Does not use :term:`generational garbage collection`, so blocks are
never promoted out of the generation in which they are allocated.
* Blocks may contain :term:`exact references` to blocks in the same or
other pools, or :term:`ambiguous references` (if the
:c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` keyword argument is set to
@ -116,6 +114,21 @@ AMS interface
the :term:`generation chain` for the pool. It must have a single
generation.
It accepts three optional keyword arguments:
* :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies
the :term:`generation chain` for the pool. If not specified, the
pool will use the arena's default chain.
* :c:macro:`MPS_KEY_GEN` (type :c:type:`unsigned`) specifies the
:term:`generation` in the chain into which new objects will be
allocated. If you pass your own chain, then this defaults to
``0``, but if you didn't (and so use the arena's default chain),
then an appropriate generation is used.
Note that AWL does not use generational garbage collection, so
blocks remain in this generation and are not promoted.
* :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` (type
:c:type:`mps_bool_t`, default false) specifies whether references
may be ambiguous.
@ -123,7 +136,6 @@ AMS interface
For example::
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, 1);
MPS_ARGS_DONE(args);
@ -132,8 +144,8 @@ AMS interface
.. deprecated:: starting with version 1.112.
When using :c:func:`mps_pool_create`, pass the format and
chain like this::
When using :c:func:`mps_pool_create`, pass the format,
chain, and ambiguous flag like this::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_ams(),

View file

@ -70,6 +70,9 @@ AWL properties
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* Does not use :term:`generational garbage collection`, so blocks are
never promoted out of the generation in which they are allocated.
* Blocks may contain :term:`exact references` or :term:`weak
references (1)` to blocks in the same or other pools (but may not
contain :term:`ambiguous references`, and may not use :term:`remote
@ -323,6 +326,21 @@ AWL interface
how to find the :term:`dependent object` for an object in the
pool.
It accepts two optional keyword arguments:
* :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies
the :term:`generation chain` for the pool. If not specified, the
pool will use the arena's default chain.
* :c:macro:`MPS_KEY_GEN` (type :c:type:`unsigned`) specifies the
:term:`generation` in the chain into which new objects will be
allocated. If you pass your own chain, then this defaults to
``0``, but if you didn't (and so use the arena's default chain),
then an appropriate generation is used.
Note that AWL does not use generational garbage collection, so
blocks remain in this generation and are not promoted.
For example::
MPS_ARGS_BEGIN(args) {

View file

@ -118,6 +118,7 @@ Alignment? [5]_ conf conf conf conf 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
Blocks are promoted between generations yes yes no no no --- --- --- --- ---
Blocks are manually managed? [10]_ no no no no no yes yes yes yes yes
Blocks are scanned? [11]_ yes no yes yes no no no no no yes
Blocks support base pointers only? [12]_ yes yes yes yes yes --- --- --- --- yes

View file

@ -59,6 +59,9 @@ LO properties
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* Does not use :term:`generational garbage collection`, so blocks are
never promoted out of the generation in which they are allocated.
* Blocks may not contain :term:`references` to blocks in automatically
managed pools.
@ -105,13 +108,28 @@ LO interface
Return the :term:`pool class` for an LO (Leaf Object)
:term:`pool`.
When creating an LO pool, :c:func:`mps_pool_create_k` require one
When creating an LO pool, :c:func:`mps_pool_create_k` requires one
:term:`keyword argument`:
* :c:macro:`MPS_KEY_FORMAT` (type :c:type:`mps_fmt_t`) specifies
the :term:`object format` for the objects allocated in the pool.
The format must provide a :term:`skip method`.
It accepts two optional keyword arguments:
* :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies
the :term:`generation chain` for the pool. If not specified, the
pool will use the arena's default chain.
* :c:macro:`MPS_KEY_GEN` (type :c:type:`unsigned`) specifies the
:term:`generation` in the chain into which new objects will be
allocated. If you pass your own chain, then this defaults to
``0``, but if you didn't (and so use the arena's default chain),
then an appropriate generation is used.
Note that LO does not use generational garbage collection, so
blocks remain in this generation and are not promoted.
For example::
MPS_ARGS_BEGIN(args) {

View file

@ -28,10 +28,29 @@ capable of collecting many automatically managed pools simultaneously.
Generation chains
-----------------
A :term:`generation chain` describes the structure of the
:term:`generations` in a set of :term:`automatically managed
<automatic memory management>` :term:`pools`. The same generation
chain should be used for all pools whose blocks live and die together.
A :term:`generation chain` describes a sequence of :term:`generations`
used by a set of :term:`automatically managed <automatic memory
management>` :term:`pools`.
A generation is a set of blocks that are managed together by the
:term:`garbage collector`: they are :term:`condemned <condemned set>`
together, and in :term:`moving <moving memory manager>` pools they are
moved together. If two pools allocate blocks that are expected to live
and die together, then it is efficient for them to share a chain.
Typically blocks are allocated in the first generation in the chain,
the :term:`nursery generation` (though you can change this using the
:c:macro:`MPS_KEY_GEN` keyword argument to :c:func:`mps_pool_create`),
and each time a block survives one collection then it is
:term:`promoted <promotion>` to the next generation. Thus a generation
contains a set of blocks of similar ages.
By default, all pools in an arena share the same generation chain
("the arena's default generation chain"), but if this doesn't meet
your requirements, then when creating an automatically managed pool,
you can choose which chain it should use by passing the
:c:macro:`MPS_KEY_CHAIN` keyword argument to
:c:func:`mps_pool_create`.
Create a generation chain by preparing an array of
:c:type:`mps_gen_param_s` structures giving the *capacity* (in
@ -59,8 +78,9 @@ For example::
.. c:type:: mps_chain_t
The type of :term:`generation chains`. A
generation chain describes the structure of :term:`generations` in a :term:`pool`.
The type of :term:`generation chains`. A generation chain
describes the structure of :term:`generations` in a set of
:term:`pools`.
.. c:type:: mps_gen_param_s
@ -260,7 +280,7 @@ Garbage collection messages
generated the message;
* :c:func:`mps_message_gc_not_condemned_size` returns the
approximate size of the set of objects that were in collected
approximate size of the set of blocks that were in collected
:term:`pools`, but were not condemned in the garbage
collection that generated the message.
@ -298,7 +318,7 @@ Garbage collection messages
not yet discarded. It must be a garbage collection message: see
:c:func:`mps_message_type_gc`.
The "live size" property is the total size of the set of objects
The "live size" property is the total size of the set of blocks
that survived the :term:`garbage collection` that generated the
message.
@ -318,7 +338,7 @@ Garbage collection messages
:c:func:`mps_message_type_gc`.
The "not condemned size" property is the approximate size of the
set of objects that were in collected :term:`pools`, but
set of blocks that were in collected :term:`pools`, but
were not in the :term:`condemned set` in the :term:`garbage
collection` that generated the message.

View file

@ -74,7 +74,6 @@ For example::
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &debug_options);
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, &fmt);
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, &chain);
MPS_ARGS_DONE(args);
res = mps_pool_create_k(&pool, arena, mps_class_ams_debug(), args);
} MPS_ARGS_END(args);

View file

@ -93,7 +93,7 @@ now :c:macro:`MPS_KEY_ARGS_END`.
: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_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: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_EXTEND_BY` :c:type:`size_t` ``size`` :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`
@ -104,6 +104,7 @@ now :c:macro:`MPS_KEY_ARGS_END`.
:c:macro:`MPS_KEY_FMT_SCAN` :c:type:`mps_fmt_scan_t` ``fmt_scan`` :c:func:`mps_fmt_create_k`
:c:macro:`MPS_KEY_FMT_SKIP` :c:type:`mps_fmt_skip_t` ``fmt_skip`` :c:func:`mps_fmt_create_k`
:c:macro:`MPS_KEY_FORMAT` :c:type:`mps_fmt_t` ``format`` :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:func:`mps_class_snc`
:c:macro:`MPS_KEY_GEN` :c:type:`unsigned` ``u`` :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo`
:c:macro:`MPS_KEY_MAX_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mv`
:c:macro:`MPS_KEY_MEAN_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mv`, :c:func:`mps_class_mvt`, :c:func:`mps_class_mvff`
:c:macro:`MPS_KEY_MFS_UNIT_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mfs`