1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 16:51:06 -07:00

Write pool reference.

Copied from Perforce
 Change: 180165
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-10-30 17:03:29 +00:00
parent 200a7ef7f7
commit 9eb16d7111
17 changed files with 1261 additions and 400 deletions

View file

@ -73,6 +73,10 @@ Memory Management Glossary: B
These instructions are vital for certain synchronization
operations.
barrier hit
.. see:: :term:`protection fault`.
base pointer
A *base pointer* is a :term:`pointer` to the base or start of

View file

@ -136,7 +136,9 @@ Memory Management Glossary: D
*dependent object*. While scanning an object, the MPS
ensures that the dependent object is unprotected so that
it can be updated. This feature supports the
implementation of weak-key and weak-value hash tables.
implementation of :term:`weak-key <weak-key hash table>`
and :term:`weak-value hash tables`. See
:ref:`pool-awl-dependent`.
derived pointer

View file

@ -513,7 +513,7 @@ Memory Management Glossary: P
protection fault
.. aka:: *protection exception*, *protection violation*.
.. aka:: *barrier hit*, *protection exception*, *protection violation*.
A protection fault is an exception or trap which occurs when a
process attempts to access :term:`memory (2)` which has been

View file

@ -420,6 +420,22 @@ Memory Management Glossary: R
.. bibref:: [UNGAR84]_, [JONES96]_.
remote reference
.. mps:specific::
A :term:`reference` that logically belongs to a
:term:`formatted object` and so must be :term:`fixed` when
the object is :term:`scanned <scan>`, but which is not
stored within the block containing the object. (For
example, in an auxiliary table of some sort.)
The MPS does not generally support remote references
because those references may be :term:`protected
<protection>` and so if :term:`scan method` attempts to
:term:`fix` them this will hit a :term:`barrier (1)` and
cause a re-entrant call to the MPS.
replicating garbage collector
A variant of :term:`copying garbage collection`, which does

View file

@ -3,33 +3,93 @@
`<https://info.ravenbrook.com/project/mps/master/manual/wiki/pool_classes.html>`_
`<https://info.ravenbrook.com/project/mps/master/design/poolamc/>`_
.. index::
single: AMC; introduction
single: pool class; AMC
.. _pool-amc:
==============================
AMC (Automatic Mostly-Copying)
==============================
General-purpose automatic (collecting) pool class. This is the most 'advanced' pool class in the MPS, intended for most client objects.
**AMC** is a general-purpose :term:`automatically managed <automatic
memory management>` :term:`pool class`. This is the most "advanced"
pool class in the MPS, intended for the majority of objects in the
client program. Use this pool class unless you need a particular
feature that it doesn't provide.
AMC is "Automatic, Mostly Copying": it uses copying collection except when prevented by ambiguous references. It is generational.
"Mostly Copying" means that it uses :term:`copying garbage collection`
except for blocks that are :term:`pinned <pinning>` by
:term:`ambiguous references`.
Chain: specify capacity and mortality of generations 0..N-1. Survivors from N-1 get promoted into an arena-wide topGen (often anachronistically called the "dynamic" generation).
It uses :term:`generational garbage collection`. That is, it exploits
assumptions about object lifetimes and inter-connection variously
referred to as "the generational hypothesis". In particular, the
following tendencies will be efficiently exploited by an AMC pool:
- most objects die young;
- objects that don't die young will live a long time;
- most references are "backwards in time" (from younger objects to
older objects).
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.
An AMC pool is both scannable and collectable. Objects may contain exact references to other objects that will preserve such other objects. Objects may be reclaimed if they are not reachable from a root. Objects may move during collection, unless reachable via a (direct) ambiguous reference. Objects in an AMC pool may be registered for finalization. Exact (that is, non-ambiguous)references into an object in an AMC pool must be to the start of the object.
.. index::
single: AMC; properties
The AMC pool class exploits assumptions about object lifetimes and inter-connection variously referred to as "the generational hypothesis". In particular, the following tendencies will be efficiently exploited by such a pool:
AMC properties
--------------
- Most objects die young;
* Does not support allocation via :c:func:`mps_alloc` or deallocation
via :c:func:`mps_free`.
- Objects that don't die young will live a long time;
* Supports allocation via :term:`allocation points`. If an allocation
point is created in an AMC pool, the call to :c:func:`mps_ap_create`
takes no additional parameters.
- Most references are backwards in time.
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
:c:func:`mps_ap_frame_push` and :c:func:`mps_ap_frame_pop` may be used on an allocation point in an AMC pool.They do not declare the affected objects to be definitely dead (compare with the SNC pool class),but have an undefined effect on the collection strategy.
* Does not support :term:`segregated allocation caches`.
If an allocation point is created in an AMC pool, the call to :c:func:`mps_ap_create` will take no additional parameters.
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* 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
references`).
* Allocations may be variable in size.
* The :term:`alignment` of blocks is configurable.
* Blocks do not have :term:`dependent objects`.
* Blocks that are not :term:`reachable` from a :term:`root` are
automatically :term:`reclaimed`.
* Blocks are :term:`scanned <scan>`.
* Blocks may only be referenced by :term:`base pointers` (unless they
belong to an object format of variant auto-header).
* Blocks may be protected by :term:`barriers (1)`.
* Blocks may :term:`move <moving garbage collector>`.
* Blocks may be registered for :term:`finalization`.
* Blocks must belong to an :term:`object format`.
.. index::
single: AMC; interface
AMC interface
-------------
@ -57,9 +117,16 @@ AMC interface
``chain`` specifies the :term:`generation chain` for the pool.
.. index::
pair: AMC; introspection
AMC introspection
-----------------
::
#include "mpscamc.h"
.. c:function:: void mps_amc_apply(mps_pool_t pool, mps_amc_apply_stepper_t f, void *p, size_t s)
Visit all :term:`formatted objects` in an AMC pool.

View file

@ -2,28 +2,68 @@
`<https://info.ravenbrook.com/project/mps/master/manual/wiki/pool_classes.html>`_
.. index::
single: AMCZ; introduction
single: pool class; AMCZ
.. _pool-amcz:
=========================================
AMCZ (Automatic Mostly-Copying Zero-rank)
=========================================
**AMCZ** is a general-purpose :term:`automatically managed <automatic
memory management>` :term:`pool class` for :term:`leaf objects`
("zero-rank" objects that contain no references).
General-purpose leaf-only pool class (for objects that contain no references). A variant of AMC (the Z means "Zero rank", ie. containing no references).
It is otherwise indentical to :ref:`pool-amc`.
AMCZ is intended for "simple" objects like numbers, characters, and
strings. Segregating these objects into one or more AMCZ pools avoids
the cost of scanning them that would be incurred if they were
interleaved in a pool with objects containing references.
.. index::
single: AMCZ; properties
---------------------
AMCZ symbol reference
---------------------
AMCZ properties
---------------
AMCZ is indentical to :ref:`pool-amc`, except that:
* Blocks may not contain :term:`references`.
* Blocks are not :term:`scanned <scan>`. A consequence of this is that
the pool's :term:`object format` need not provide a :term:`scan
method`.
* Blocks are not protected by :term:`barriers (1)`.
.. index::
single: AMCZ; interface
AMCZ interface
--------------
::
#include "mpscamc.h"
------------
Undocumented
------------
.. c:function:: mps_class_t mps_class_amcz(void)
Return the :term:`pool class` for an AMCZ (Automatic
Mostly-Copying Zero-rank) :term:`pool`.
When creating an AMCZ pool, :c:func:`mps_pool_create` takes two
extra arguments::
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)
``fmt`` specifies the :term:`object format` for the objects
allocated in the pool.
``chain`` specifies the :term:`generation chain` for the pool.

View file

@ -3,23 +3,83 @@
`<https://info.ravenbrook.com/project/mps/master/manual/wiki/pool_classes.html>`_
`<https://info.ravenbrook.com/project/mps/master/design/poolams/>`_
.. index::
single: AMS; introduction
single: pool class; AMS
.. _pool-ams:
==============================
AMS (Automatic Mark and Sweep)
==============================
Non-moving automatic (collecting) pool class.
**AMS** is an :term:`automatically managed <automatic memory
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 is "Automatic Mark & Sweep". Not generational.
Chain: specify capacity and mortality of 'generation' 0. [Why? Perhaps to trigger nursery-like collections? New 2001-03-02. RHSK 2006-11-27]
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.
.. index::
single: AMS; properties
--------------------
AMS symbol reference
--------------------
AMS properties
--------------
* Does not support allocation via :c:func:`mps_alloc` or deallocation
via :c:func:`mps_free`.
* Supports allocation via :term:`allocation points`. If an allocation
point is created in an AMC pool, the call to :c:func:`mps_ap_create`
takes no additional parameters.
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
* Does not support :term:`segregated allocation caches`.
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* 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
references`).
* Allocations may be variable in size.
* The :term:`alignment` of blocks is configurable.
* Blocks do not have :term:`dependent objects`.
* Blocks that are not :term:`reachable` from a :term:`root` are
automatically :term:`reclaimed`.
* Blocks are :term:`scanned <scan>`.
* Blocks may only be referenced by :term:`base pointers` (unless they
belong to an object format of variant auto-header).
* Blocks are not protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`. A consequence
of this is that the pool's :term:`object format` need not provide a
:term:`forward method`, an :term:`is-forwarded method` or a
:term:`padding method`.
* Blocks may be registered for :term:`finalization`.
* Blocks must belong to an :term:`object format`.
.. index::
single: AMS; interface
AMS interface
-------------
::
@ -46,8 +106,21 @@ AMS symbol reference
must have a single generation.
------------
Undocumented
------------
.. c:function:: mps_class_t mps_class_ams_debug(void)
A :ref:`debugging <topic-debugging>` version of the AMS pool
class.
When creating a debugging AMS pool, :c:func:`mps_pool_create`
takes three extra arguments::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_ams_debug(),
mps_debug_option_s debug_option,
mps_fmt_t fmt,
mps_chain_t chain)
``debug_option`` specifies the debugging options. See
:c:type:`mps_debug_option_s`.
``fmt`` and ``chain`` are the same as for :c:func:`mps_class_ams`.

View file

@ -2,68 +2,334 @@
`<https://info.ravenbrook.com/project/mps/master/manual/wiki/pool_classes.html>`_
`<https://info.ravenbrook.com/project/mps/master/design/poolawl/>`_
`<http://info.ravenbrook.com/mail/2003/03/17/13-51-24/0.txt>`_
DRJ: `<https://info.ravenbrook.com/mail/2003/03/17/13-51-24/0.txt>`_
NB: `<https://info.ravenbrook.com/mail/2002/04/12/15-52-29/0.txt>`_
NB: `<https://info.ravenbrook.com/mail/2002/04/12/15-56-15/0.txt>`_
.. index::
single: AWL; introduction
single: pool class; AWL
.. _pool-awl:
===========================
AWL (Automatic Weak Linked)
===========================
**AWL** is an :term:`automatically managed <automatic memory
management>` :term:`pool class` that may contain :term:`weak
references (1)`.
Automatic Weak Linked
The purpose of this pool class is to allow the client to implement
:term:`weak-key <weak-key hash table>`, :term:`weak-value <weak-value
hash table>`, and :term:`doubly weak hash tables`.
For weak references, linked to normal references. The purpose of this pool class is to allow the client to implement hash tables (or, conceivably some similar datastructures) that are partly or wholly weak. A client might want a weak-key strong-value table, or a strong-key weak-value table (or in fact weak-key weak-value). For example, Java's java.util.WeakHashMap class.
In a weak-key hash table, the keys are weakly referenced, so their
presence in the table will not prevent the key object from being
garbage collected. Once the key is no longer :term:`reachable`, weak
references to it may get :dfn:`splatted` (that is, replaced with null
pointers). Once that has happened, the client program can't get at the
value corresponding to the key any more, so the implementation is free
to splat the value slot as well.
The principle idea behind a weak-key strong-value hash table is that the keys are weakly referenced, so their presence in the table will not prevent the key object from being garbage collected. Once the key is no longer reachable, weak references to it may get splatted. Obviously once that has happened you can't get at the value corresponding to the key anymore, so the implementation is free to splat the value slot as well.
AWL allows the implementation to splat the value slot at the same time
that the weak key slot is splatted. (Or the other way around for
weak-value tables.) See :ref:`pool-awl-dependent`.
Pool Class AWL allows the implementation to splat the value slot at the same time that the (weak) key slot is splatted. (Or the other way around if you have strong-key weak-value tables).
Exactly how you do this is not yet well documented (but see below for more hints).
.. index::
single: AWL; properties
AWL has another special power: it enables better handing of barrier hits on weak objects. To explain the benefit we need to describe a problem first. The MPS uses a read-barrier to perform incremental garbage collection [@@ link to canned-for-client explanation of how a garbage collector works in broad terms]. When the client tries to read an object containing weak references the MPS may have protected it so that the MPS can process the object before the client gets to see it. The problem for weak objects is that the client may try and access the object at a point in the collection cycle when the MPS cannot yet determine the status of the objects that the weak object refers to. What the MPS does in this situation is assume that all the referenced objects are going to live. This assumption is correct but conservative; it may result in objects that are weakly referenced staying alive for longer than they need to. In the worst case this can result in a very large amount of memory being used by objects that are no longer needed.
AWL properties
--------------
In order to combat this problem the MPS sometimes does the following: Instead of processing the entire weak object and unprotecting it so that the client can access the object the MPS may emulate the processor instruction. When this happens the MPS doesn't process the entire weak object, it only processes the exact location that was being accessed (typically a single word), it emulates the processor instruction, and it keeps the object protected. This happens invisibly from the client's perspective, it's exactly as if the instruction executed as normal. The MPS instead of processing the entire object processes just a single word.
* Does not support allocation via :c:func:`mps_alloc` or deallocation
via :c:func:`mps_free`.
Naturally this emulation business is delicate and hairy and involves staring at the most badly written parts of low-level processor architecture manuals for days.
* Supports allocation via :term:`allocation points`. If an allocation
point is created in an AMC pool, the call to :c:func:`mps_ap_create`
takes one additional parameter, a :term:`rank` of type
:c:type:`mps_rank_t`. The rank must be either
:c:func:`mps_rank_exact` (to allocate ordinary objects containing
:term:`exact references`), or :c:func:`mps_rank_weak` (to allocate
objects that contain weak references). For example::
Emulation of accesses to protected objects happens when:
mps_ap_t ap;
mps_res_t res;
res = mps_ap_create(&ap, pool, mps_rank_weak());
if (res != MPS_RES_OK) error("can't create allocation point");
The object is a weak object allocated in an AWL pool.
The MPS is on Linux/IA-32 or Windows/IA-32. Extending this list to new (reasonable) operating systems should be tolerable (for example, OS X/IA-32), new processor architectures require more work.
The processor instruction that is accessing the object is of a suitable simple form. The MPS doesn't contain an emulator for all possible instructions that might access memory, so it only recognises and emulates a few forms of instruction. Currently this is simple MOVs from memory to a register or vice-versa, but it's best not to rely on the details.
Because of this emulation, AWL places a restriction on the format of objects allocated in it:
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
All slots in an object must either be a valid word-aligned reference, or the bottom bits of the word must be non-zero so that it does not look like an aligned pointer. "Aligned pointer" means a word whose numeric value (that is, treated as an unsigned integer) is a multiple of the architecture's natural word size (in bytes). In the very likely event that you're using a 32-bit machine that means that an aligned poiner is a multiple of 4 and its bottom 2 bits are both 0. Bottom line: pointers must be untagged and aligned, ints must be tagged with a non-zero tag.
* Does not support :term:`segregated allocation caches`.
AWL is one of the few pools that can allocate objects that contain non-exact references. The mps_ap_create method when used with an AWL pool accepts an extra argument, which is a rank of type mps_rank_t. The rank is either MPS_RANK_EXACT (to allocate ordinary objects contained exact references), or MPS_RANK_WEAK (to allocate objects that contain weak references). Example::
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
if(MPS_RES_OK != mps_ap_create(&weakap, tablepool, MPS_RANK_WEAK) {
/* Error. */
...
* 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
references`).
* Allocations may be variable in size.
* The :term:`alignment` of blocks is configurable.
* Blocks may have :term:`dependent objects`.
* Blocks that are not :term:`reachable` from a :term:`root` are
automatically :term:`reclaimed`.
* Blocks are :term:`scanned <scan>`.
* Blocks may only be referenced by :term:`base pointers` (unless they
belong to an object format of variant auto-header).
* Blocks may be protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`. A consequence
of this is that the pool's :term:`object format` need not provide a
:term:`forward method`, an :term:`is-forwarded method` or a
:term:`padding method`.
* Blocks may be registered for :term:`finalization`.
* Blocks must belong to an :term:`object format`.
.. index::
pair: AWL; dependent object
.. _pool-awl-dependent:
Dependent objects
-----------------
In order to support prompt deletion of values in a :term:`weak-key
hash table` when the key is splatted (and prompt deletion of values in
a :term:`weak-value hash table`), an AWL pool allows each object to
have a :dfn:`dependent object`.
The dependent object is specified by a ``find_dependent`` function
which is passed to :c:func:`mps_pool_create` when creating an AWL
pool. This is a function of type :c:type:`mps_find_dependent_t` that
takes the address of an object in the pool and returns the address of
its dependent object (or a null pointer if there is no corresponding
dependent object).
When :term:`scanning <scan>` an object in an AWL pool, the MPS ensures
that the dependent object is not protected. This means that the
:term:`scan method` in the pool's :term:`object format` can read or
write the dependent object.
The way you would normally use this feature in a weak hash table would
be to put the table's keys in one object, and its values in another.
(This would be necessary in any case, because the MPS does not support
a mixture of :term:`exact references` and :term:`weak references (1)`
in the same object.) The dependent object for the keys objects is the
values object, and vice versa (if necessary). The scan method looks
out for the splatting of a reference, and when this is detected, it
splats the corresponding reference in the dependent object.
For example::
typedef struct weak_array_s {
struct weak_array_s *dependent;
size_t length; /* actually length * 2 + 1 */
obj_t slot[1];
} weak_array_s, *weak_array_t;
typedef weak_table_s {
type_s type; /* TYPE_WEAK_TABLE */
weak_array_t keys, values;
} weak_table_s, *weak_table_t;
mps_addr_t weak_array_find_dependent(mps_addr_t addr)
{
weak_array_t a = addr;
return a->dependent;
}
...
mps_res_t weak_array_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
{
MPS_SCAN_BEGIN(ss) {
while (base < limit) {
weak_array_t a = base;
size_t i, length = a->length >> 1;
for (i = 0; i < length; ++i) {
mps_addr_t p = a->slot[i];
if (MPS_FIX1(ss, p)) {
mps_res_t res = MPS_FIX2(ss, &p);
if (res != MPS_RES_OK) return res;
if (p == NULL) {
/* key/value was splatted: splat value/key too */
a->dependent->slot[i] = NULL;
}
a->slot[i] = p;
}
}
base += offsetof(weak_array_s, slot) + a->length * sizeof a->slot[0];
}
} MPS_SCAN_END(ss);
return MPS_RES_OK;
}
.. note::
The ``length`` field of the ``weak_array_s`` structure contains
the value ``length * 2 + 1`` so that it cannot be mistaken for a
pointer. See :ref:`pool-awl-caution` below.
.. index::
pair: AWL; protection faults
See also NB's notes on weak hash tables in Dylan:
<https://info.ravenbrook.com/mail/2002/04/12/15-52-29/0.txt>
<https://info.ravenbrook.com/mail/2002/04/12/15-56-15/0.txt>
.. _pool-awl-barrier:
And DRJ's notes here: <https://info.ravenbrook.com/mail/2003/03/17/13-51-24/0.txt>
Protection faults
-----------------
AWL has another special power: it enables better handing of
:term:`protection faults` on :dfn:`weak objects` (objects containing
:term:`weak references (1)`).
To explain the benefit we first need to describe the problem. The MPS
uses a :term:`read barrier` to perform :term:`incremental garbage
collection`. When the client program tries to read an object
containing :term:`weak references (1)`, the MPS may have
:term:`protected <protection>` it so that the MPS can process the
object before the client gets to see it.
The problem is that the client program may try to access a weak object
at a point in the :term:`collection cycle` when the MPS cannot yet
determine the status of the objects that the weak object refers to.
What the MPS does in this situation is assume that all the referenced
objects are going to live. This assumption is correct but
conservative; it may result in objects that are weakly referenced
staying alive for longer than they need to. In the worst case this can
result in a very large amount of memory being used by objects that are
no longer needed.
In order to combat this problem the MPS sometimes does the following:
Instead of processing the entire weak object and unprotecting it, so
that the client program can access the object, the MPS may emulate the
processor instruction. When this happens, the MPS doesn't process the
entire weak object; it only processes the exact location that was
being accessed (typically a single word). It emulates the processor
instruction, and it keeps the object protected. This happens invisibly
from the client program's perspective: it's exactly as if the
instruction executed as normal.
Naturally this emulation business is delicate and involves staring at
the most badly written parts of low-level processor architecture
manuals for days.
Emulation of accesses to protected objects happens when all of the
following are true:
1. The object is a weak object allocated in an AWL pool.
2. The MPS is running on Linux/IA-32 or Windows/IA-32. Extending this
list to new (reasonable) operating systems should be tolerable (for
example, OS X/IA-32). Extending this to new processor architectures
requires more work.
3. The processor instruction that is accessing the object is of a
suitable simple form. The MPS doesn't contain an emulator for all
possible instructions that might access memory, so currently it
only recognizes and emulates a simple ``MOV`` from memory to a
register or vice-versa.
:ref:`Contact us <contact>` if you need emulation of access to weak
references for new operating systems, processor architectures, or
memory access instructions.
--------------------
AWL symbol reference
--------------------
.. index::
pair: AWL; cautions
.. _pool-awl-caution:
Caution
-------
Because of the instruction emulation described in
:ref:`pool-awl-barrier` above, AWL places the following restriction on
the format of objects allocated in it:
* Each slot in an object must either be a valid word-aligned
reference, or else the bottom bits of the word must be non-zero so
that it does not look like an aligned pointer.
"Aligned pointer" means a word whose numeric value (that is, its
value when treated as an unsigned integer) is a multiple of the
architecture's natural :term:`word` size in :term:`bytes (1)`. If
you're using a 32-bit architecture, that means that an aligned
pointer is a multiple of 4 and its bottom two bits are both zero.
The bottom line is that references from an object in an AWL pool
must be untagged and aligned, and integers must be tagged with a
non-zero tag.
Normally one would cope with this restriction by allocating the table
metadata in a pool belonging to another pool class, and only
allocating the arrays of keys and values in an AWL pool. See :ref:`the
example <pool-awl-dependent>` above.
.. index::
single: AWL; interface
AWL interface
-------------
::
#include "mpscawl.h"
------------
Undocumented
------------
.. c:function:: mps_class_t mps_class_awl(void)
Return the :term:`pool class` for an AWL (Automatic Weak Linked)
:term:`pool`.
When creating an AWL pool, :c:func:`mps_pool_create` takes two
extra arguments::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_awl(),
mps_fmt_t fmt,
mps_awl_find_dependent_t find_dependent)
``fmt`` specifies the :term:`object format` for the objects
allocated in the pool.
``find_dependent`` is a function of type
:c:type:`mps_awl_find_dependent_t` that specifies how to find the
:term:`dependent object` for an object in the pool.
When creating an allocation point on an AWL pool,
:c:func:`mps_ap_create` takes one extra argument::
mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool,
mps_rank_t rank)
``rank`` specifies the :term:`rank` of references in objects
allocated on this allocation point. It must be
:c:func:`mps_rank_exact` (if the objects allocated on this
allocation point will contain :term:`exact references`), or
:c:func:`mps_rank_weak` (if the objects will contain :term:`weak
references (1)`).
.. c:type:: mps_addr_t (*mps_awl_find_dependent_t)(mps_addr_t addr)
The type of functions that find the :term:`dependent object` for
an object in an AWL pool.
``addr`` is the address of an object in an AWL pool.
Returns the address of the corresponding dependent object, or a
null pointer if there is none.
The dependent object need not be in memory managed by the MPS, but
if it is, then it must be in a pool in the same arena as ``addr``.

View file

@ -4,8 +4,10 @@ Pool reference
**************
.. toctree::
:maxdepth: 1
:numbered:
:maxdepth: 2
intro
amc
amcz
ams
@ -15,187 +17,3 @@ Pool reference
mvff
mvt
snc
.. _pool-choose:
Choosing a pool class
=====================
This section contains a simple procedure for choosing a :term:`pool
class` based on the properties of the data you plan to store in
it. The MPS works well if you can segregate your data into a variety
of pools, choosing the most appropriate pool class for each.
.. note::
Pool classes can differ in many ways not considered here: speed,
vulnerability to fragmentation, control overhead, and so on. This
procedure gives you a decent recommendation, but an expert in the
MPS might be able to make a better one.
First, answer these questions about your data:
1. Do you need the MPS to :term:`automatically <automatic memory
management>` :term:`reclaim` :term:`unreachable` blocks?
2. Is it acceptable for the MPS to :term:`move <moving memory
manager>` blocks in memory and to place :term:`barriers (1)` on
blocks? (For example, it might not be acceptable to move a block if
it has been passed to :term:`foreign code` that remembered its
location.)
3. Do your blocks contain :term:`references` to blocks stored in
automatically managed pools (including references to other blocks
in the same pool, if it's automatically managed)? And if so, are
these references :term:`exact <exact reference>`, :term:`ambiguous
<ambiguous reference>` or :term:`weak <weak reference (1)>`?
Second, look up your answers in this table to find the recommended
pool class to use:
========== ====================== =========== ====================================
Automatic? Movable & protectable? References? Use this pool class
========== ====================== =========== ====================================
yes yes none :ref:`pool-amcz`
yes yes exact :ref:`pool-amc`
yes yes ambiguous nothing suitable
yes yes weak :ref:`pool-awl`
yes no none :ref:`pool-lo`
yes no exact :ref:`pool-ams`
yes no ambiguous nothing suitable
yes no weak nothing suitable
no *any* none :ref:`pool-mvt`
no *any* ambiguous :ref:`pool-mvt` [1]_
no *any* exact :ref:`pool-mvt` [1]_
no *any* weak :ref:`pool-mvt` [1]_
========== ====================== =========== ====================================
.. note::
.. [1] :ref:`pool-mvt` doesn't scan for references, but you can
work around this by registering your blocks as
:term:`roots` (with the appropriate :term:`rank`) just
after they are allocated, and deregistering them just
before freeing them.
.. Sources:
`<https://info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mmdoc/doc/mps/guide/pool-classes/>`_
.. _pool-properties:
Pool class properties
=====================
This table summarizes the properties of each :term:`pool class`
provided by the open source MPS. For "block" properties, "yes" means
that the property holds for *all* blocks allocated from the pool. An
entry "---" indicates that a property makes no sense for a pool class:
for example, if blocks in a pool may not contain :term:`references`,
it makes no sense to ask whether they may contain :term:`weak
references (1)`.
============================================= ===== ===== ===== ===== ===== ===== ===== ===== =====
Property AMC AMCZ AMS AWL LO MV MVFF MVT SNC
============================================= ===== ===== ===== ===== ===== ===== ===== ===== =====
Supports :c:func:`mps_alloc`? no no no no no yes yes no ??
Supports :c:func:`mps_free`? no no no no no yes yes yes ??
Supports allocation points? yes yes yes yes yes no no yes ??
Timing of collections? [2]_ auto auto yes auto auto --- --- --- ??
May contain references? [3]_ yes no yes yes no no no no ??
May contain exact references? [4]_ yes --- yes yes --- --- --- --- ??
May contain ambiguous references? [4]_ no --- no no --- --- --- --- ??
May contain weak references? [4]_ no --- no yes --- --- --- --- ??
Allocations fixed or variable in size? var var var var var var var var ??
Alignment? [5]_ conf conf conf conf conf [6]_ [7]_ [6]_ ??
Dependent objects? [8]_ no --- no yes --- --- --- --- ??
May use remote references? [9]_ no --- ?? no --- --- --- --- ??
Ambiguous references keep blocks alive? no no ?? no no --- --- --- ??
Blocks are automatically managed? [10]_ yes yes yes yes yes no no no ??
Blocks are manually managed? [10]_ no no no no no yes yes yes ??
Blocks are scanned? [11]_ yes no yes yes no no no no ??
Blocks support base references only? [12]_ yes yes ?? yes yes --- --- --- ??
Blocks support internal references? [12]_ no no ?? no no --- --- --- ??
Blocks may be protected by barriers? yes no ?? yes no no no no ??
Blocks may move? yes yes no no no no no no ??
Blocks may be finalized? yes yes ?? yes yes no no no ??
Blocks must be formatted? [11]_ yes yes yes yes yes no no no ??
============================================= ===== ===== ===== ===== ===== ===== ===== ===== =====
.. note::
.. [2] "Timing of collections" is "auto" if :term:`garbage collection`
is under the control of the MPS, which decides when collection
should take place and performs it :term:`automatically
<automatic memory management>` and :term:`incrementally
<incremental garbage collection>`.
.. [3] Pools that may not contain references are suitable for
storing :term:`leaf objects` only.
.. [4] Pools "may contain :term:`ambiguous <ambiguous reference>` /
:term:`exact <exact reference>` / :term:`weak <weak
reference (1)>` references" if the references that the client
program fixes during scanning may include references of the
indicated :term:`rank`.
.. [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` and
:ref:`pool-mvt` pools is platform-dependent.
.. [7] :ref:`pool-mvff` pools have configurable alignment, but it may
not be smaller than :c:macro:`MPS_PF_ALIGN` (the :term:`natural
alignment` for the :term:`platform`).
.. [8] In pools with this property, each object may specify an
:term:`dependent object` which the client program
guarantees will be accessible during the scanning of the
first object. This may be used in the implementation of
:term:`weak hash tables`.
.. [9] "Remote references" are references that are stored outside the
block to which they logically belong (for example, in some kind
of auxiliary table). A pool containing remote references cannot
rely on a :term:`write barrier` to detect changed references.
.. [10] Blocks are "automatically managed" if they may be
automatically discarded when the MPS determines that they
are unreachable; they are "manually managed" if they can be
discarded when the :term:`client program` requests it. Note
that these properties are not mutually exclusive, although
the MPS does not provide a pool class that satisfies both.
.. [11] Blocks "are scanned" if the MPS :term:`scans` them for
references; blocks "must be formatted" if they are
described to the MPS by an :term:`object format`. At
present, the MPS only knows how to scan blocks using the
:term:`scan method` from an object format, but the MPS
design does not preclude pools that scan unformatted
blocks.
.. [12] A block "supports internal references" if a reference to any
location within the block is considered to be a reference to
the block. It "supports base references only" if only a
reference to the base of the block is considered to be a
reference to the block.
Writing a new pool class
========================
If none of the pool classes supplied with the MPS are quite right for
your application, don't despair: the MPS is designed to be extensible
with new pool classes, and designed so that the properties of pools
are as orthogonal as possible. So if you need a pool containing
objects that are scannable but unformatted, or movable objects which
are manually managed, or a pool all of whose objects are roots, there
is no technical reason why it should not be possible to write it.
If you'd be interested in our developing new pool classes for your
requirements, or if you've started writing a new pool class
yourself, :ref:`we'd love to hear from you <contact>`.

View file

@ -0,0 +1,187 @@
.. _pool-choose:
Choosing a pool class
=====================
This section contains a simple procedure for choosing a :term:`pool
class` based on the properties of the data you plan to store in
it. The MPS works well if you can segregate your data into a variety
of pools, choosing the most appropriate pool class for each.
.. note::
Pool classes can differ in many ways not considered here: speed,
vulnerability to fragmentation, control overhead, and so on. This
procedure gives you a decent recommendation, but an expert in the
MPS might be able to make a better one.
First, answer these questions about your data:
1. Do you need the MPS to :term:`automatically <automatic memory
management>` :term:`reclaim` :term:`unreachable` blocks?
2. Is it acceptable for the MPS to :term:`move <moving memory
manager>` blocks in memory and to place :term:`barriers (1)` on
blocks? (For example, it might not be acceptable to move a block if
it has been passed to :term:`foreign code` that remembered its
location.)
3. Do your blocks contain :term:`references` to blocks stored in
automatically managed pools (including references to other blocks
in the same pool, if it's automatically managed)? And if so, are
these references :term:`exact <exact reference>`, :term:`ambiguous
<ambiguous reference>` or :term:`weak <weak reference (1)>`?
Second, look up your answers in this table to find the recommended
pool class to use:
========== ====================== =========== ====================================
Automatic? Movable & protectable? References? Use this pool class
========== ====================== =========== ====================================
yes yes none :ref:`pool-amcz`
yes yes exact :ref:`pool-amc`
yes yes ambiguous nothing suitable
yes yes weak :ref:`pool-awl`
yes no none :ref:`pool-lo`
yes no exact :ref:`pool-ams`
yes no ambiguous nothing suitable
yes no weak nothing suitable
no *any* none :ref:`pool-mvt`
no *any* ambiguous :ref:`pool-mvt` [1]_
no *any* exact :ref:`pool-mvt` [1]_
no *any* weak :ref:`pool-mvt` [1]_
========== ====================== =========== ====================================
.. note::
.. [1] :ref:`pool-mvt` doesn't scan for references, but you can
work around this by registering your blocks as
:term:`roots` (with the appropriate :term:`rank`) just
after they are allocated, and deregistering them just
before freeing them.
.. Sources:
`<https://info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mmdoc/doc/mps/guide/pool-classes/>`_
.. _pool-properties:
Pool class properties
=====================
This table summarizes the properties of each :term:`pool class`
provided by the open source MPS. For "block" properties, "yes" means
that the property holds for *all* blocks allocated from the pool. An
entry "---" indicates that a property makes no sense for a pool class:
for example, if blocks in a pool may not contain :term:`references`,
it makes no sense to ask whether they may contain :term:`weak
references (1)`.
============================================= ===== ===== ===== ===== ===== ===== ===== ===== =====
Property AMC AMCZ AMS AWL LO MV MVFF MVT SNC
============================================= ===== ===== ===== ===== ===== ===== ===== ===== =====
Supports :c:func:`mps_alloc`? no no no no no yes yes no no
Supports :c:func:`mps_free`? no no no no no yes yes yes no
Supports allocation points? yes yes yes yes yes no yes yes yes
Supports allocation frames? yes yes yes yes yes no yes yes yes
Supports segregated allocation caches? no no no no no yes yes no no
Timing of collections? [2]_ auto auto auto auto auto --- --- --- ---
May contain references? [3]_ yes no yes yes no no no no yes
May contain exact references? [4]_ yes --- 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 var var var var
Alignment? [5]_ conf conf conf conf conf [6]_ [7]_ [6]_ conf
Dependent objects? [8]_ no --- no yes --- --- --- --- no
May use remote references? [9]_ no --- no no --- --- --- --- no
Ambiguous references keep blocks alive? no no no no no --- --- --- no
Blocks are automatically managed? [10]_ yes yes yes yes yes no no no no
Blocks are manually managed? [10]_ no no no no no yes yes yes yes
Blocks are scanned? [11]_ yes no yes yes no no no no yes
Blocks support base pointers only? [12]_ yes yes yes yes yes --- --- --- yes
Blocks support internal pointers? [12]_ no no no no no --- --- --- no
Blocks may be protected by barriers? yes no no yes no no no no no
Blocks may move? yes yes no no no no no no no
Blocks may be finalized? yes yes yes yes yes no no no no
Blocks must be formatted? [11]_ yes yes yes yes yes no no no yes
Blocks may belong to format auto-header? yes yes yes yes yes --- --- --- no
============================================= ===== ===== ===== ===== ===== ===== ===== ===== =====
.. note::
.. [2] "Timing of collections" is "auto" if :term:`garbage collection`
is under the control of the MPS, which decides when collection
should take place and performs it :term:`automatically
<automatic memory management>` and :term:`incrementally
<incremental garbage collection>`.
.. [3] Pools that may not contain references are suitable for
storing :term:`leaf objects` only.
.. [4] Pools "may contain :term:`ambiguous <ambiguous reference>` /
:term:`exact <exact reference>` / :term:`weak <weak
reference (1)>` references" if the references that the client
program fixes during scanning may include references of the
indicated :term:`rank`.
.. [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` and
:ref:`pool-mvt` pools is platform-dependent.
.. [7] :ref:`pool-mvff` pools have configurable alignment, but it may
not be smaller than :c:macro:`MPS_PF_ALIGN` (the :term:`natural
alignment` for the :term:`platform`).
.. [8] In pools with this property, each object may specify an
:term:`dependent object` which the client program
guarantees will be accessible during the scanning of the
first object. This may be used in the implementation of
:term:`weak hash tables`.
.. [9] "Remote references" are references that are stored outside the
block to which they logically belong (for example, in some kind
of auxiliary table). A pool containing remote references cannot
rely on a :term:`write barrier` to detect changed references.
.. [10] Blocks are "automatically managed" if they may be
automatically discarded when the MPS determines that they
are unreachable; they are "manually managed" if they can be
discarded when the :term:`client program` requests it. Note
that these properties are not mutually exclusive, although
the MPS does not provide a pool class that satisfies both.
.. [11] Blocks "are scanned" if the MPS :term:`scans` them for
references; blocks "must be formatted" if they are
described to the MPS by an :term:`object format`. At
present, the MPS only knows how to scan blocks using the
:term:`scan method` from an object format, but the MPS
design does not preclude pools that scan unformatted
blocks.
.. [12] A block "supports internal pointers" if a pointer to any
location within the block is considered to be a reference
to the block. It "supports base pointers only" if only a
pointer to the base of the block (or, if the block belongs
to an object format of variant auto-header, a pointer just
past the end of the header) is considered to be a reference
to the block.
Writing a new pool class
========================
If none of the pool classes supplied with the MPS are quite right for
your application, don't despair: the MPS is designed to be extensible
with new pool classes, and designed so that the properties of pools
are as orthogonal as possible. So if you need a pool containing
objects that are scannable but unformatted, or movable objects which
are manually managed, or a pool all of whose objects are roots, there
is no technical reason why it should not be possible to write it.
If you'd be interested in our developing new pool classes for your
requirements, or if you've started writing a new pool class
yourself, :ref:`we'd love to hear from you <contact>`.

View file

@ -3,30 +3,98 @@
`<https://info.ravenbrook.com/project/mps/master/manual/wiki/pool_classes.html>`_
`<https://info.ravenbrook.com/project/mps/master/design/poollo/>`_
.. index::
single: LO; introduction
single: pool class; LO
.. _pool-lo:
==============
LO (Leaf Only)
==============
Non-moving, non-protecting, automatic (collecting), Leaf Only pool class (for objects that contain no references). Unit test: locv.c. RefMan: -undocumented-.
**LO** is an :term:`automatically managed <automatic memory
management>` :term:`pool class` for :term:`leaf objects` (objects that
contain no references). It does not move or protect its objects.
This pool class should really be called "flat data that needs to be accessed by foreign code" -- it's ideal for allocating a buffer to pass to an operating system I/O call. It is not very fast. [Conversation with DRJ, 2006-07].
This pool class is intended for unstructured data that needs to be
accessed by :term:`foreign code`. It's ideal for allocating a buffer
that needs to be passed to an operating system I/O function.
(For a general-purpose leaf-only pool see AMCZ).
For leaf objects that can move and be protected, consider
:ref:`pool-amcz` instead.
-------------------
LO symbol reference
-------------------
.. index::
single: LO; properties
LO properties
-------------
* Does not support allocation via :c:func:`mps_alloc` or deallocation
via :c:func:`mps_free`.
* Supports allocation via :term:`allocation points`. If an allocation
point is created in an AMC pool, the call to :c:func:`mps_ap_create`
takes no additional parameters.
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
* Does not support :term:`segregated allocation caches`.
* Garbage collections are scheduled automatically. See
:ref:`topic-collection-schedule`.
* Blocks may not contain :term:`references`.
* Allocations may be variable in size.
* The :term:`alignment` of blocks is configurable.
* Blocks do not have :term:`dependent objects`.
* Blocks that are not :term:`reachable` from a :term:`root` are
automatically :term:`reclaimed`.
* Blocks are not :term:`scanned <scan>`. A consequence of this is that
the pool's :term:`object format` need not provide a :term:`scan
method`.
* Blocks may only be referenced by :term:`base pointers` (unless they
belong to an object format of variant auto-header).
* Blocks are not protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`. A consequence
of this is that the pool's :term:`object format` need not provide a
:term:`forward method` or an :term:`is-forwarded method`. (It also
does not need a :term:`padding method`.)
* Blocks may be registered for :term:`finalization`.
* Blocks must belong to an :term:`object format`.
.. index::
single: LO; interface
LO interface
------------
::
#include "mpsclo.h"
------------
Undocumented
------------
.. c:function:: mps_class_t mps_class_lo(void)
Return the :term:`pool class` for an LO (Leaf Only) :term:`pool`.
When creating an LO pool, :c:func:`mps_pool_create` takes one
extra argument::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_lo(),
mps_fmt_t fmt)
``fmt`` specifies the :term:`object format` for the objects
allocated in the pool.

View file

@ -1,28 +1,68 @@
.. index::
single: MV; introduction
single: pool class; MV
.. _pool-mv:
====================
MV (Manual Variable)
====================
The :term:`pool class` MV (Manual Variable) is a general-purpose class
of :term:`manually managed <manual memory management>` pools that
manage :term:`blocks` of variable size.
**MV** is a general-purpose :term:`manually managed <manual memory
management>` :term:`pool class` that manages :term:`blocks` of
variable size.
It supports allocation via :c:func:`mps_alloc` and deallocation via
:c:func:`mps_free`.
.. warning::
It does not support :term:`allocation points`.
:ref:`pool-mvt` or :ref:`pool-mvff` should be used instead.
-------------------
MV symbol reference
-------------------
.. index::
single: MV; properties
MV properties
-------------
* Support allocation via :c:func:`mps_alloc` and deallocation via
:c:func:`mps_free`.
* Does not support allocation via :term:`allocation points`.
* Does not support :term:`allocation frames`.
* Supports :term:`segregated allocation caches`.
* There are no garbage collections in this pool.
* Allocations may be variable in size.
* The :term:`alignment` of blocks is not configurable (it is the
natural :term:`word` size of the platform).
* Blocks do not have :term:`dependent objects`.
* Blocks are not automatically :term:`reclaimed`.
* Blocks are not :term:`scanned <scan>`.
* Blocks are not protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`.
* Blocks may not be registered for :term:`finalization`.
* Blocks must not belong to an :term:`object format`.
.. index::
single: MV; interface
MV interface
------------
::
#include "mpscmv.h"
.. c:function:: mps_class_t mps_class_mv(void)
Return the :term:`pool class` for an MV (Manual Variable)
@ -32,23 +72,66 @@ MV symbol reference
extra arguments::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_mvff(),
mps_class_t mps_class_mv(),
mps_size_t extend_size,
mps_size_t average_size,
mps_size_t maximum_size)
``extend_size`` is the :term:`size` of segment that the pool will
request from the :term:`arena`.
``average_size`` and ``maximum size`` are the predicted average
and maximum size of blocks that will be allocated from the pool.
These are hints to the MPS: the pool will be less efficient if
these are wrong.
------------
Undocumented
------------
.. c:function:: mps_class_t mps_class_mv_debug(void)
A :ref:`debugging <topic-debugging>` version of the MV pool
class.
When creating a debugging MV pool, :c:func:`mps_pool_create`
takes four extra arguments::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_mv_debug(),
mps_debug_option_s debug_option,
mps_size_t extend_size,
mps_size_t average_size,
mps_size_t maximum_size)
``debug_option`` specifies the debugging options. See
:c:type:`mps_debug_option_s`.
``extend_szie``, ``average_size`` and ``maximum_size`` are as
documented in :c:func:`mps_class_mv`.
.. index::
pair: MV; introspection
MV introspection
----------------
::
#include "mpscmv.h"
.. c:function:: size_t mps_mv_free_size(mps_pool_t pool)
Return the total amount of free space in an MV pool.
``pool`` is the MV pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mv_size(mps_pool_t pool)
.. c:function:: mps_class_t mps_class_mv_debug(void)
Return the total size of an MV pool.
``pool`` is the MV pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.

View file

@ -2,42 +2,94 @@
`<https://info.ravenbrook.com/project/mps/master/design/poolmvff/>`_
.. index::
single: MVFF; introduction
single: pool class; MVFF
.. _pool-mvff:
================================
MVFF (Manual Variable First Fit)
================================
**MVFF** :term:`manually manages <manual memory management>`
variable-sized, unformatted objects. It uses the :term:`first fit`
:term:`allocation policy` for blocks allocated via
:c:func:`mps_alloc`.
Buffered allocation (:c:func:`mps_reserve` and :c:func:`mps_commit`) is also supported, but in that case, the policy is rather different: buffers are filled worst-fit, and allocation is always upwards from the base. The arenaHigh parameter regulates whether new segments are acquired at high or low addresses;the slotHigh and firstFit parameters do not affect buffered allocation. Buffered and unbuffered allocation can be used at the same time, but in that case, the first allocation point must be created before any call to :c:func:`mps_alloc`.
It also supports buffered allocation (that is, allocation via
:term:`allocation points`), and in this case, the allocation policy is
different: the buffers are filled according to the :term:`worst fit`
policy, and allocation always proceeds upwards from the base.
Cached allocation (:c:macro:`MPS_SAC_ALLOC` and :c:macro:`MPS_SAC_FREE`) is also supported, but in that case,the policy is a little different: allocation from the cache follows its own policy (typicallyfirst-fit), and only when the cache needs to acquire more blocks from the underlying MVFF pool does it use the usual algorithm to choose blocks for the cache.
Buffered and unbuffered allocation can be used at the same time, but
the first allocation point must be created before any call to
:c:func:`mps_alloc`.
::
It is usually not advisable to use buffered and unbuffered allocation
on the same pool, because the worst-fit policy of buffer filling will
grab all the large blocks, leading to severe fragmentation. If you
need both forms of allocation, use two separate pools.
if(mps_pool_create(&pool, arena, mps_class_mvff(), 8 * 1024, 135, 4, 0, 0, 1)
!= MPS_RES_OK)
{
printf("Error creating pool!");
exit(2);
}
Note that using buffered allocation prevents (for obscure technical
reasons) the pool from allocating across segment boundaries. This can
cause added external fragmentation if objects are allocated that are a
significant fraction of the segment size.
.. note::
If you need to allocate large objects in an MVFF pool,
:ref:`contact us <contact>`.
It is usually not advisable to use buffered and unbuffered allocation at the same time,because the worst-fit policy of buffer filling will grab all the large blocks, leading to severe fragmentation. Use two separate pools instead.
.. index::
single: MVFF; properties
Note that using buffered allocation prevents (for obscure technical reasons) the pool from allocating across segment boundaries. This can cause added external fragmentation if objects are allocated that are a significant fraction of the segment size. (This quirk will disappear in a future version.)
MVFF properties
---------------
* Supports allocation via :c:func:`mps_alloc`.
* Supports allocation via :term:`allocation points`.
* Supports deallocation via :c:func:`mps_free`.
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
* Supports :term:`segregated allocation caches`.
* There are no garbage collections in this pool.
* Allocations may be variable in size.
* The :term:`alignment` of blocks is not configurable (it is the
natural :term:`word` size of the platform).
* Blocks do not have :term:`dependent objects`.
* Blocks are not automatically :term:`reclaimed`.
* Blocks are not :term:`scanned <scan>`.
* Blocks are not protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`.
* Blocks may not be registered for :term:`finalization`.
* Blocks must not belong to an :term:`object format`.
.. index::
single: MVFF; interface
---------------------
MVFF symbol reference
---------------------
MVFF interface
--------------
::
#include "mpscmvff.h"
.. c:function:: mps_class_t mps_class_mvff(void)
Return the :term:`pool class` for an MVFF (Manual Variable First
@ -67,15 +119,63 @@ MVFF symbol reference
to the pool's alignment. The minimum alignment supported by pools
of this class is ``sizeof(void *)``.
``slot_high``, ``arena_high``, and ``first_fit`` are undocumented
and may be set to (0, 0, 1) or (1, 1, 1). No other setting of
these parameters is recommended.
``slot_high`` is undocumented. It must have the same value as
``arena_high``.
If ``arena_high`` is true, new segments for buffered allocation
are acquired at high addresses; if false, at low addresses.
``first_fit`` is undocumented and must be set to true.
------------
Undocumented
------------
.. c:function:: mps_class_t mps_class_mvff_debug(void)
A :ref:`debugging <topic-debugging>` version of the MVFF pool
class.
When creating a debugging MVFF pool, :c:func:`mps_pool_create`
takes seven extra arguments::
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
mps_class_t mps_class_mvff_debug(),
mps_debug_option_s debug_option,
mps_size_t extend_size,
mps_size_t average_size,
mps_align_t alignment,
mps_bool_t slot_high,
mps_bool_t arena_high,
mps_bool_t first_fit)
``debug_option`` specifies the debugging options. See
:c:type:`mps_debug_option_s`.
The other arguments are the same as for :c:func:`mps_class_mvff`.
.. index::
pair: MVFF; introspection
MVFF introspection
------------------
::
#include "mpscmvff.h"
.. c:function:: size_t mps_mvff_free_size(mps_pool_t mpspool)
Return the total amount of free space in an MVFF pool.
``pool`` is the MVFF pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mvff_size(mps_pool_t pool)
.. c:function:: mps_class_t mps_class_mvff_debug(void)
Return the total size of an MVFF pool.
``pool`` is the MVFF pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.

View file

@ -2,103 +2,105 @@
`<https://info.ravenbrook.com/project/mps/master/design/poolmvt/>`_
.. index::
single: MVT; introduction
single: pool class; MVT
.. _pool-mvt:
==============================
MVT (Manual Variable Temporal)
==============================
The MVT pool class manually manages variable-sized, unformatted objects. The MVT pool uses an allocation policy termed "temporal fit". Temporal fit attempts to place consecutive allocations next to each other. It relies on delaying reuse as long as possible to permit freed blocks to coalesce, thus maximizing the number of consecutive allocations that can be co-located. Temporal fit permits a very fast allocator and a deallocator competitive in speed with all other known policies.
**MVT** :term:`manually manages <manual memory management>`
variable-sized, unformatted objects. It uses an :term:`allocation
policy` termed :dfn:`temporal fit`.
Temporal fit is intended to take advantage of knowledge of object lifetimes, either apriori knowledge or knowledge acquired by profiling. The best performance of the MVT pool will be achieved by allocating objects with similar expected deathtimes together.
.. index::
pair: MVT; temporal fit
single: allocation policy; temporal fit
Temporal fit
------------
Temporal fit attempts to place consecutive allocations next to each
other. It relies on delaying reuse as long as possible to permit freed
blocks to :term:`coalesce`, thus maximizing the number of consecutive
allocations that can be co-located. Temporal fit permits a very fast
allocator and a deallocator competitive in speed with all other known
policies.
Temporal fit is intended to take advantage of knowledge of object
:term:`lifetimes`, either *a priori* knowledge, or knowledge acquired
by profiling. The best performance will be achieved by allocating
objects with similar expected death times together.
A simple policy can be implemented to take advantage of MVT. Object
size is typically well-correlated with object life-expectancy, and
birth time plus lifetime gives death time, so allocating objects of
similar size sequentially from the same pool instance should result in
objects allocated close to each other dying at about the same time.
An application that has several classes of objects of widely differing
life expectancy will best be served by creating a different MVT pool
instance for each life-expectancy class. A more sophisticated policy
can use either the programmer's knowledge of the expected lifetime of
an objector any characteristic of objects that correlates with
lifetime to choose an appropriate pool instance to allocate in.
Allocating objects with unknown or very different deathtimes together
will pessimize the space performance of MVT.
A simple policy can be implemented to take advantage of MVT: Object size is typically well-correlated with object life-expectancy, and birthtime plus lifetime gives deathtime, so allocating objects of similar size sequentially from the same pool instance should result in objects allocated close to each other dying at about the same time.
.. index::
single: MVT; properties
An application that has several classes of objects of widely differing life expectancy will best be served by creating a different MVT pool instance for each life-expectancy class. A more sophisticated policy can use either the programmer's knowledge of the expected lifetime of an objector any characteristic of objects that correlates with lifetime to choose an appropriate pool instance to allocate in.
MVT properties
--------------
Allocating objects with unknown or very different deathtimes together will pessimize the space performance of MVT.
* Does not support allocation via :c:func:`mps_alloc`.
::
* Supports allocation via :term:`allocation points` only.
if(mps_pool_create(&amp;pool, arena, mps_class_mvt(), 8, 32, 256, 70, 20)
!= MPS_RES_OK)
{
printf("Error creating pool!");
exit(2);
}
* Supports deallocation via :c:func:`mps_free`.
* Supports :term:`allocation frames` but does not use them to improve
the efficiency of stack-like allocation.
* Does not support :term:`segregated allocation caches`.
* There are no garbage collections in this pool.
* Allocations may be variable in size.
* The :term:`alignment` of blocks is not configurable (it is the
natural :term:`word` size of the platform).
* Blocks do not have :term:`dependent objects`.
* Blocks are not automatically :term:`reclaimed`.
* Blocks are not :term:`scanned <scan>`.
* Blocks are not protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`.
* Blocks may not be registered for :term:`finalization`.
* Blocks must not belong to an :term:`object format`.
Reserve depth
.. index::
single: MVT; interface
If a pool has a stable population, or one which only grows over
the lifetime of the pool, or one which grows steadily and then
shrinks steadily, use a reserve depth of 0.
It is always safe to use a reserve depth of 0, but if the
population typically fluctuates in a range (for example, the
client program repeatedly creates and destroys a subset of blocks
in a loop), it is more efficient for the pool to retain enough
storage to satisfy that fluctuation. For example, if a pool has an
object population that typically fluctuates between 8,000 and
10,000, use a reserve depth of 2,000.
The reserve will not normally be available to other pools for
allocation, even when it is not used by the pool. If this is
undesirable, a reserve depth of 0 may be used for a pool whose
object population does vary, at a slight cost in efficiency. The
reserve does not guarantee any particular amount of allocation.
Fragmentation limit
A fragmentation limit of 100 will cause the pool to use temporal
fit (unless resources are exhausted). If the objects allocated in
the pool have similar lifetime expectancies, this mode will have
the best time- and space-efficiency. If the objects have widely
varying lifetime expectancies,this mode will be time-efficient,
but may be space-inefficient. An intermediate setting can be used
to limit the space-inefficiency of temporal fit due to varying
object life expectancies.
Allocation
The MVT pool class only supports allocation through allocation
points. See :c:func:`mps_ap_create`.
Deallocation
The MVT pool class supports explicit freeing. See :c:func:`mps_pool_free`.
Internal Notes
Need a life-expectancy parameter! How else will different instances choose their Loci?
Need an alignment parameter. Perhaps this is embedded in a format parameter (when all pools have at least a null format).
It is conceivable that a client would want to mix manual and automatic pools with the manual pool being able to be a root for the automatic. To do so, MVT would need to support formatted objects and scanning. This may be added someday.
Eventually the MM product will include profiling tools that will help determine object characteristics that correlate with object lifetime and suggest how to configure the appropriate number of MVT pool instances and what characteristics to dispatch on when choosing which instance to allocate from.
[From mail.ptw.1998-08-19.02-33(0) ]
Remember Wilson's statement that the goal of a memory manager is to exploit the regularities in allocation patterns? My intent in the interface parameters is to accept measurable regularities in object populations, then the implementation can exploit them.
Perhaps the pool should accept some description of the mean and deviation of the object sizes, object population, and object lifetimes. Is that what you are getting at? [Reserve_depth is in some sense a deviation.]
--------------------
MVT symbol reference
--------------------
MVT interface
-------------
::
#include "mpscmv2.h"
.. c:function:: mps_class_t mps_class_mvt(void)
Return the :term:`pool class` for an MVT (Manual Variable
@ -128,10 +130,28 @@ MVT symbol reference
``reserve_depth`` is the expected hysteresis of the population of
the pool. When blocks are freed, the pool will retain sufficient
storage to allocate ``reserve_depth`` blocks of ``mean_size`` for near
term allocations (rather than immediately making that storage
storage to allocate ``reserve_depth`` blocks of ``mean_size`` for
near term allocations (rather than immediately making that storage
available to other pools).
If a pool has a stable population, or one which only grows over
the lifetime of the pool, or one which grows steadily and then
shrinks steadily, use a reserve depth of 0.
It is always safe to use a reserve depth of 0, but if the
population typically fluctuates in a range (for example, the
client program repeatedly creates and destroys a subset of blocks
in a loop), it is more efficient for the pool to retain enough
storage to satisfy that fluctuation. For example, if a pool has an
object population that typically fluctuates between 8,000 and
10,000, use a reserve depth of 2,000.
The reserve will not normally be available to other pools for
allocation, even when it is not used by the pool. If this is
undesirable, a reserve depth of 0 may be used for a pool whose
object population does vary, at a slight cost in efficiency. The
reserve does not guarantee any particular amount of allocation.
``fragmentation_limit`` is a percentage in (0, 100] that can be used
to set an upper limit on the space overhead of MVT in case block
death times and allocations do not correlate well. If the free
@ -140,12 +160,42 @@ MVT symbol reference
first fit allocation policy, exploiting space more efficiently at
a cost in time efficiency. A fragmentation limit of 0 would cause
the pool to operate as a first-fit pool, at a significant cost in
time efficiency, therefore is not permitted.
time efficiency: therefore this is not permitted.
A fragmentation limit of 100 will cause the pool to use temporal
fit (unless resources are exhausted). If the objects allocated in
the pool have similar lifetime expectancies, this mode will have
the best time- and space-efficiency. If the objects have widely
varying lifetime expectancies, this mode will be time-efficient,
but may be space-inefficient. An intermediate setting can be used
to limit the space-inefficiency of temporal fit due to varying
object life expectancies.
------------
Undocumented
------------
.. index::
pair: MVT; introspection
MVT introspection
-----------------
::
#include "mpscmv2.h"
.. c:function:: size_t mps_mvt_free_size(mps_pool_t pool)
Return the total amount of free space in an MVT pool.
``pool`` is the MVT pool.
Returns the total free space in the pool, in :term:`bytes (1)`.
.. c:function:: size_t mps_mvt_size(mps_pool_t pool)
Return the total size of an MVT pool.
``pool`` is the MVT pool.
Returns the total size of the pool, in :term:`bytes (1)`. This
is the sum of allocated space and free space.

View file

@ -2,29 +2,82 @@
`<https://info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mmdoc/doc/mps/guide/stack-alloc/>`_
.. index::
single: SNC; introduction
single: pool class; SNC
.. _pool-snc:
====================
SNC (Stack No Check)
====================
An SNC pool is scannable, in that objects may contain references to objects in other pools that will keep those objects alive (depending on rank). In this sense, an SNC pool is a de-facto root.
**SNC** is a :term:`manually managed <manual memory management>`
:term:`pool class` that supports a stack-like protocol for allocation
and deallocation using :term:`allocation frames` on :term:`allocation
points`. See :ref:`topic-frame`.
Exact references may point to (the start of) objects in an SNC pool, but will have no effect on whether those objects are either scanned or kept alive.
If :c:func:`mps_ap_frame_pop` is used on an allocation point in an SNC
pool (after a corresponding call to :c:func:`mps_ap_frame_push`), then
the objects affected by the pop are effectively declared dead, and may
be reclaimed by the collector. Extant references to such objects from
reachable or *de facto* alive objects are safe, but such other objects
should be dead; that is, such references must never be used.
If :c:func:`mps_ap_frame_pop` is used on an allocation point in an SNC pool (after a corresponding call to :c:func:`mps_ap_frame_push`), then the objects affected by the pop are effectively declared dead, and may be reclaimed by the collector. Extant references to such objects from reachable or de facto alive objects are safe, but such other objects should be dead; that is, such references must never be used.
If an allocation point is created in an SNC pool, then the call to :c:func:`mps_ap_create` will take as an additional parameter the rank (of type :c:func:`mps_rank_t`) of references in the objects to be created in that allocation point. Currently, only rank exact (:c:func:`mps_rank_exact`) is supported.
.. index::
single: SNC; properties
Objects in an SNC pool may not be registered for finalization.
SNC properties
--------------
Objects in an SNC pool will not move.
* Does not support allocation via :c:func:`mps_alloc`.
* Supports allocation via :term:`allocation points` only.
* Does not support deallocation via :c:func:`mps_free`.
* Supports :term:`allocation frames`.
* Does not support :term:`segregated allocation caches`.
* 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
references`).
* There are no garbage collections in this pool.
* Allocations may be variable in size.
* The :term:`alignment` of blocks is configurable.
* Blocks do not have :term:`dependent objects`.
* Blocks are not automatically :term:`reclaimed`.
* Blocks are :term:`scanned <scan>`.
* Blocks may only be referenced by :term:`base pointers` (unless they
belong to an object format of variant auto-header).
* Blocks are not protected by :term:`barriers (1)`.
* Blocks do not :term:`move <moving garbage collector>`.
* Blocks may not be registered for :term:`finalization`. A consequence
of this is that the pool's :term:`object format` need not provide a
:term:`forward method` or an :term:`is-forwarded method`.
* Blocks must belong to an :term:`object format`, but this may not be
a format of variant auto-header.
--------------------
SNC symbol reference
--------------------
.. index::
single: SNC; interface
SNC introspection
-----------------
::
@ -47,6 +100,12 @@ SNC symbol reference
allocated in the pool. The format should provide at least the
methods scan, skip, and pad.
.. topics::
When creating an allocation point on an SNC pool,
:c:func:`mps_ap_create` takes one extra argument::
:ref:`pool-snc`.
mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool,
mps_rank_t rank)
``rank`` specifies the :term:`rank` of references in objects
allocated on this allocation point. It must be
:c:func:`mps_rank_exact`.

View file

@ -36,7 +36,7 @@ Outstanding
Compare the performance with the plain ``scheme.c``. The advanced
version better be faster!
76. Develop debugging examples that illustrates each of the warnings
76. Develop debugging examples that illustrate each of the warnings
about consistency. Also to demonstrate the "garbage collect
frequently to expose errors as soon as possible" advice.
@ -86,6 +86,27 @@ Outstanding
left out?
133. What's the purpose of ``mps_SEH_filter`` and ``mps_SEH_handler``?
Do they need to be documented?
134. What's the use case for AMS? It's suitable when you have blocks
that need to be automatically managed but can't be moved. But
when does this happen? If foreign code maintains remembers their
location then it seems unlikely that they can be automatically
managed (how can these foreign references keep the blocks
alive?).
135. Does AMS use protection? I see that it calls ``ShieldExpose`` and
``ShieldCover`` when calling the format's skip method, but not
otherwise (e.g. when calling the format's scan method). If it
does I need to update the pool choice algorithm.
Similar question for SNC? It calls ``ShieldExpose`` and
``ShieldCover`` when calling the format's pad method, but not
otherwise.
136. It seems possible that MV should not be used. What should I say
about this? Should we remove MV from the documentation
altogether.
Complete

View file

@ -24,6 +24,13 @@ pools).
Allocation frames can be used by the :term:`client program` to
efficiently implement stack-like patterns of allocation.
.. note::
All :term:`pool classes` that support :term:`allocation points`
also support pushing and popping of allocation frames, but only
the :ref:`pool-snc` pool class actually uses these frames to
manage its blocks.
.. c:type:: mps_frame_t