1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 08:41:47 -07:00

Distribute symbol reference into the topics.

Copied from Perforce
 Change: 179974
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-10-19 18:09:10 +01:00
parent e4c420797a
commit 99cccfa252
20 changed files with 3619 additions and 19 deletions

View file

@ -10,7 +10,6 @@ Memory Pool System
guide/index
topic/index
pool/index
reference/index
lang
glossary/index
bib

View file

@ -1,6 +1,5 @@
.. _topic-allocation:
==========
Allocation
==========
@ -52,7 +51,7 @@ These notes on Allocation Points were written by RHSK between 2006-06-07 and 200
[Note: some constraints may be mentioned only here, and not yet in other places they should be mentioned, such as the Reference Manual. Notably, the client's obligation to ensure there are no exact references to a failed new-object, before it calls mps_ap_trip, is suspected to be new. RHSK 2006-06-13]
------------
Introduction
------------
@ -308,3 +307,249 @@ Although this User's Guide explains the protocol in terms of the pre-packaged ma
For further discussion of Allocation Points, see Allocation Points -- Internals in the Wiki.
Interface
---------
.. c:function:: mps_res_t mps_alloc(mps_addr_t *p_o, mps_pool_t pool, size_t size, ...)
Allocate a :term:`block` of memory in a :term:`pool`.
``p_o`` points to a location that will hold the address of the
allocated block.
``pool`` the pool to allocate in.
``size`` is the :term:`size` of the block to allocate. If it is
unaligned, it will be rounded up to the pool's :term:`alignment`
(unless the pool documentation says otherwise).
Some pool classes require additional arguments to be passed to
:c:func:`mps_alloc`. See the documentation for the pool class.
.. note::
There's an alternative function :c:func:`mps_alloc_v` that
takes its extra arguments using the standard :term:`C`
``va_list`` mechanism.
.. c:function:: mps_res_t mps_alloc_v(mps_addr_t *p_o, mps_pool_t pool, size_t size, va_list args)
An alternative to :c:func:`mps_alloc` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism.
.. c:function:: mps_res_t mps_ap_create(mps_ap_t *ap_o, mps_pool_t pool, ...)
Create an :term:`allocation point` in a :term:`pool`.
``ap_o`` points to a location that will hold the address of the
allocation point, if successful.
``pool`` is the pool.
Returns :c:macro:`MPS_RES_OK` if successful, or another
:term:`result code` if not.
Some pool classes require additional arguments to be passed to
:c:func:`mps_ap_create`. See the documentation for the pool class.
.. note::
There's an alternative function :c:func:`mps_ap_create_v` that
takes its extra arguments using the standard :term:`C`
``va_list`` mechanism.
.. c:function:: mps_res_t mps_ap_create_v(mps_ap_t *ap_o, mps_pool_t pool, va_list args)
An alternative to :c:func:`mps_ap_create` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism.
.. c:function:: void mps_ap_destroy(mps_ap_t ap)
Destroy an :term:`allocation point`.
``ap`` is the allocation point to destroy.
Destroying an allocation point has no effect on blocks that were
allocated from it, so long as they were successfully
:term:`committed (2)` by :c:func:`mps_commit`.
.. c:function:: mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t ap, size_t size)
Reserve a :term:`block` of memory on an :term:`allocation point`.
:c:func:`mps_ap_fill` has same interface as :c:func:`mps_reserve`.
.. note::
:c:func:`mps_ap_fill` must only be called according to the
:term:`allocation point protocol`.
.. c:type:: mps_ap_s
The type of the structure used to represent :term:`allocation
points <allocation point>`::
typedef struct mps_ap_s {
mps_addr_t init;
mps_addr_t alloc;
mps_addr_t limit;
/* ... internal fields ... */
} mps_ap_s;
``init`` is the limit of initialized memory.
``alloc`` is the limit of allocated memory.
``limit`` is the limit of available memory.
An allocation point is an interface to a :term:`pool` which
provides very fast allocation, and defers the need for
synchronization in a multi-threaded environment.
Create an allocation point for a pool by calling
:c:func:`mps_ap_create`, and allocate memory via one by calling
:c:func:`mps_reserve` and :c:func:`mps_commit`.
.. c:type:: mps_ap_t
The type of :term:`allocation points <allocation point>`. It is an
alias (via the C ``typedef`` mechanism) for a pointer to
:c:type:`mps_ap_s`.
.. c:function:: mps_bool_t mps_ap_trip(mps_ap_t ap, mps_addr_t p, size_t size)
:term:`Commit <committed (2)>` a reserved :term:`block` on an
:term:`allocation point`.
:c:func:`mps_ap_trip` has the same interface as :c:func:`mps_commit`.
.. note::
:c:func:`mps_ap_trip` must only be called according to the
:term:`allocation point protocol`.
.. c:function:: mps_bool_t mps_commit(mps_ap_t ap, mps_addr_t p, size_t size)
:term:`Commit <committed (2)>` a reserved :term:`block` on an
:term:`allocation point`.
``ap`` is an allocation point.
``p`` points to a block that was reserved by :c:func:`mps_reserve`
but has not yet been committed.
``size`` is the :term:`size` of the block to allocate. It must be
the same size that was passed to :c:func:`mps_reserve`.
If :c:func:`mps_commit` returns true, the block was successfully
committed, which means that the :term:`client program` may use it,
create references to it, and rely on references from it. It also
means that the MPS may scan it, move it, protect it, or reclaim it
(if ``ap`` was attached to a pool with those features).
If :c:func:`mps_commit` returns false, the block was not
committed. This means that the client program must not create
references to the block, rely on references from it, or otherwise
use it. It is normal to attempt the reserve operation again when
this happens.
It is very rare for :c:func:`mps_commit` to return false: this
only happens if there was a :term:`flip` between the call to
:c:func:`mps_reserve` and the call to
:c:func:`mps_commit`. Nonetheless, it can happen, so it is
important not to perform operations with side effects (that you
aren't prepared to repeat) between calling :c:func:`mps_reserve`
and :c:func:`mps_commit`. Also, the shorter the interval, the less
likely :c:func:`mps_commit` is to return false.
.. note::
:c:func:`mps_commit` must only be called according to the
:term:`allocation point protocol`.
.. c:function:: void mps_free(mps_pool_t pool, mps_addr_t addr, size_t size)
Free a :term:`block` of memory to a :term:`pool`.
``pool`` is the pool the block belongs to.
``addr`` is the address of the block to be freed.
``size`` is the :term:`size` of the block to be freed. If it is
unaligned, it will be rounded up to the pool's :term:`alignment`
(unless the pool documentation says otherwise).
The freed block of memory becomes available for allocation by the
pool, or the pool might decide to make it available to other
pools, or it may be returned to the operating system.
.. note::
:c:func:`mps_free` takes a ``size`` parameter because it is
most efficient to do so. In most programs, the type of an
object is known at the point in the code that frees it, hence
the size is trivially available. In such programs, storing the
size on the MPS side would cost time and memory, and make it
hard to get good virtual memory behaviour (as it is, the
deallocation code doesn't have to touch the dead object at
all).
.. c:function:: mps_res_t mps_reserve(mps_addr_t *p_o, mps_ap_t ap, size_t size)
Reserve a :term:`block` of memory on an :term:`allocation point`.
``p_o`` points to a location that will hold the address of the
reserve block.
``ap`` is the allocation point.
``size`` is the :term:`size` of the block to allocate. It must be
a multiple of the :term:`alignment` of the pool (or of the pool's
:term:`object format` if it has one).
Returns :c:macro:`MPS_RES_OK` if the block was reserved
successfully, or another :term:`result code` if not.
The reserved block may be initialized but must not otherwise be
used until after it has been :term:`committed (2)` via a
successful call to :c:func:`mps_commit`.
.. note::
:c:func:`mps_reserve` must only be called according to the
:term:`allocation point protocol`.
:c:func:`mps_reserve` is implemented as a macro for speed. It
may evaluate its arguments multiple times.
There is an alternative, :c:func:`MPS_RESERVE_BLOCK`, which
may generate faster code, but may only be used in statement
context (not as an expression), and requires an lvalue instead
of a pointer to a location to store the result.
.. c:function:: MPS_RESERVE_BLOCK(mps_res_t res_v, mps_addr_t *p_v, mps_ap_t ap, size_t size)
An alternative to :c:func:`mps_reserve`. It may generate faster
code than :c:func:`mps_reserve`, but it may only be used in
statement context (not as an expression), and it requires an
lvalue instead of a pointer to a location to store the result.
The second arguemnt is an lvalue ``p_v``, which is assigned the
address of the reserved block. It takes an additional first
argument, the lvalue ``res_v``, which is assigned the
:term:`result code`.

View file

@ -1,6 +1,5 @@
.. _topic-arena:
======
Arenas
======
@ -104,8 +103,600 @@ Arenas do not interact. However, they may conflict with each other in terms of r
------------------------------
Using idle time for collection
------------------------------
See <http://info.ravenbrook.com/mail/2003/01/03/14-13-25/0.txt>
Interface
---------
.. c:function:: void mps_arena_clamp(mps_arena_t arena)
Put an :term:`arena` into the :term:`clamped state`.
``arena`` is the arena to clamp.
In the clamped state, no object motion will occur and the
staleness of :term:`location dependencies <location dependency>`
will not change. All references to objects loaded while the arena
is clamped will keep the same binary representation until after it
is released by calling :c:func:`mps_arena_release`.
In a clamped arena, incremental collection may still occur, but it
will not be visible to the mutator and no new collections will
begin. Space used by unreachable objects will not be recycled
until the arena is unclamped.
.. c:type:: mps_arena_class_t
The type of :term:`arena classes <arena class>`.
.. c:function:: void mps_arena_collect(mps_arena_t arena)
Collect an arena and put it into the :term:`parked state`.
``arena`` is the arena to collect.
The collector attempts to recycle as many unreachable objects as
possible and reduce the size of the arena as much as possible
(though in some cases it may increase because it becomes more
fragmented). Note that the collector may not be able to recycle
some objects (such as those near the destination of ambiguous
references) even though they are not reachable.
If you do not want the arena to remain in the parked state, you
must explicitly call :c:func:`mps_arena_release` afterwards.
.. c:function:: size_t mps_arena_commit_limit(mps_arena_t arena)
Return the current :term:`commit limit` for
an arena.
``arena`` is the arena to return the commit limit for.
Returns the commit limit in :term:`bytes <byte (1)>`. The commit
limit controls how much memory the MPS can obtain from the
operating system, and can be changed by calling
:c:func:`mps_arena_commit_limit_set`.
.. c:function:: mps_res_t mps_arena_commit_limit_set(mps_arena_t arena, size_t limit)
Change the :term:`commit limit` for an :term:`arena`.
``arena`` is the arena to change the commit limit for.
``limit`` is the new commit limit in :term:`bytes <byte (1)>`.
Returns :c:macro:`MPS_RES_OK` if successful, or another
:term:`result code` if not.
If successful, the commit limit for ``arena`` is set to ``limit``. The
commit limit controls how much memory the MPS will obtain from the
operating system. The commit limit cannot be set to a value that
is lower than the number of bytes that the MPS is using. If an
attempt is made to set the commit limit to a value greater than or
equal to that returned by :c:func:`mps_arena_committed` then it
will succeed. If an attempt is made to set the commit limit to a
value less than that returned by :c:func:`mps_arena_committed`
then it will succeed only if the amount committed by the MPS can
be reduced by reducing the amount of spare committed memory; in
such a case the spare committed memory will be reduced
appropriately and the attempt will succeed.
.. note::
:c:func:`mps_arena_commit_limit_set` puts a limit on all
memory committed by the MPS. The :term:`spare committed
memory` can be limited separately with
:c:func:`mps_arena_spare_commit_limit_set`. Note that "spare
committed" memory is subject to both limits; there cannot be
more spare committed memory than the spare commit limit, and
there can't be so much spare committed memory that there is
more committed memory than the commit limit.
.. c:function:: size_t mps_arena_committed(mps_arena_t arena)
Return the total :term:`committed <mapped>` memory for an
:term:`arena`.
``arena`` is the arena.
Returns the total amount of memory that has been committed to RAM
by the MPS, in :term:`bytes <byte (1)>`.
The committed memory is generally larger than the sum of the sizes
of the allocated :term:`blocks <block>`. The reasons for this are:
* some memory is used internally by the MPS to manage its own data
structures and to record information about allocated blocks
(such as free lists, page tables, colour tables, statistics, and
so on);
* operating systems (and hardware) typically restrict programs to
requesting and releasing memory with a certain granularity (for
example, :term:`pages <page>`), so extra memory is committed
when this rounding is necessary;
* there might also be :term:`spare committed memory`: see
:c:func:`mps_arena_spare_committed`.
The amount of committed memory is a good measure of how much
virtual memory resource ("swap space") the MPS is using from the
operating system.
The function :c:func:`mps_arena_committed` may be called whatever
state the the arena is in (:term:`unclamped <unclamped state>`,
:term:`clamped <clamped state>`, or :term:`parked <parked
state>`). If it is called when the arena is in the unclamped state
then the value may change after this function returns. A possible
use might be to call it just after :c:func:`mps_arena_collect` to
(over-)estimate the size of the heap.
If you want to know how much memory the MPS is using then you're
probably interested in the value ``mps_arena_committed() -
mps_arena_spare_committed()``.
The amount of committed memory can be limited with the function
:c:func:`mps_arena_commit_limit`.
.. c:function:: mps_res_t mps_arena_create(mps_arena_t *arena_o, mps_arena_class_t arena_class, ...)
Create an :term:`arena`.
``arena_o`` points to a location that will hold a pointer to the new
arena.
``arena_class`` is the :term:`arena class`.
Some arena classes require additional arguments to be passed to
:c:func:`mps_arena_create`. See the documentation for the arena
class.
Returns :c:macro:`MPS_RES_OK` if the arena is created
successfully, or another :term:`result code` otherwise.
The arena persists until it is destroyed by calling
:c:func:`mps_arena_destroy`.
.. note::
There's an alternative function :c:func:`mps_arena_create_v`
that takes its extra arguments using the standard :term:`C`
``va_list`` mechanism.
.. c:function:: mps_res_t mps_arena_create_v(mps_arena_t *arena_o, mps_arena_class_t arena_class, va_list args)
An alternative to :c:func:`mps_arena_create` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism.
.. c:function:: void mps_arena_destroy(mps_arena_t arena)
Destroy an :term:`arena`.
``arena`` is the arena to destroy.
This function checks the consistency of the arena, flushes the
:term:`telemetry stream` and destroys the arena's internal control
structures. Additionally, :term:`virtual memory arenas <virtual
memory arena>` return their reserved address space to the
operating system if possible.
It is an error to destroy an arena without first destroying all
:term:`generation chains <generation chain>`, :term:`object
formats <object format>`, :term:`pools <pool>` and :term:`roots
<root>` created in the arena, and deregistering all :term:`threads
<thread>` registered with the arena.
.. c:function:: void mps_arena_expose(mps_arena_t arena)
Ensure that the MPS is not protecting any :term:`page` in the
:term:`arena` with a :term:`read barrier` or :term:`write
barrier`.
``mps_arena`` is the arena to expose.
This is expected to only be useful for debugging. The arena is
left in the :term:`clamped state`.
Since barriers are used during a collection, calling this function
has the same effect as calling :c:func:`mps_arena_park`: all
collections are run to completion, and the arena is clamped so
that no new collections begin. The MPS also uses barriers to
maintain :term:`remembered sets <remembered set>`, so calling this
function will effectively destroy the remembered sets and any
optimization gains from them.
Calling this function is time-consuming: any active collections
will be run to completion; and the next collection will have to
recompute all the remembered sets by scanning the entire arena.
The recomputation of the remembered sets can be avoided by calling
:c:func:`mps_arena_unsafe_expose_remember_protection` instead of
:c:func:`mps_arena_expose`, and by calling
:c:func:`mps_arena_unsafe_restore_protection` before calling
:c:func:`mps_arena_release`. Those functions have unsafe aspects
and place restrictions on what the :term:`client program` can do
(basically no exposed data can be changed).
.. c:function:: mps_res_t mps_arena_extend(mps_arena_t arena, mps_addr_t base, size_t size)
Extend a :term:`client arena` with another block of memory.
``base`` is the :term:`address` of the block of memory that will be
managed by the arena.
``size`` is its :term:`size`.
Return :c:macro:`MPS_RES_OK` if successful, or another
:term:`result code` if it fails.
.. c:function:: mps_bool_t mps_arena_has_addr(mps_arena_t arena, mps_addr_t addr)
Test whether an :term:`address` is managed by an :term:`arena`.
``arena`` is an arena.
``addr`` is an address.
Returns true if ``addr`` is managed by ``arena``; false otherwise.
An arena manages a portion of :term:`address space`. No two arenas
overlap, so for any particular address this function will return
true for at most one arena. In general, not all addresses are
managed by some arena; in other words, some addresses will not be
managed by any arena. This is what allows the MPS to cooperate
with other memory managers, shared object loaders, memory mapped
file input/ouput, and so on: it does not steal the whole address
space.
The result from this function is valid only at the instant at
which the function returned. In some circumstances the result may
immediately become invalidated (for example, a :term:`garbage
collection` may occur, the address in question may become free,
the arena may choose to unmap the address and return storage to
the operating system). For reliable results call this function
whilst the arena is in the :term:`parked state`.
.. c:function:: void mps_arena_park(mps_arena_t arena)
Put an :term:`arena` into the :term:`parked state`.
``arena`` is the arena to park.
While an arena is parked, no object motion will occur and the
staleness of :term:`location dependencies <location dependency>`
will not change. All references to objects loaded while the arena
is parked will keep the same binary representation until after it
is released.
Any current collection is run to completion before the arena is
parked, and no new collections will start. When an arena is in the
parked state, it is necessarily not in the middle of a collection.
.. c:function:: void mps_arena_release(mps_arena_t arena)
Puts an arena into the :term:`unclamped state`.
``arena`` is the arena to unclamp.
While an arena is unclamped, :term:`garbage collection`, object
motion, and other background activity can take place.
.. seealso::
:ref:`topic-collection`.
.. c:function:: size_t mps_arena_reserved(mps_arena_t arena)
Return the total :term:`address space` reserved by an
:term:`arena`, in :term:`bytes <byte (1)>`.
``arena`` is the arena.
For a :term:`virtual memory arena`, this is the total address space
reserved via the operating system's virtual memory interface.
For a :term:`client arena`, this is the sum of the usable portions
of the chunks of memory passed to the arena by the :term:`client
program` via :c:func:`mps_arena_create` and
:c:func:`mps_arena_extend`.
.. note::
For a client arena, the reserved address may be lower than the
sum of the ``size`` arguments passed to
:c:func:`mps_arena_create` and :c:func:`mps_arena_extend`,
because the arena may be unable to use the whole of each chunk
for reasons of alignment.
.. c:function:: size_t mps_arena_spare_commit_limit(mps_arena_t arena)
Return the current :term:`spare commit limit` for an
:term:`arena`.
``arena`` is the arena to return the spare commit limit for.
Returns the spare commit limit in :term:`bytes <byte (1)>`. The
spare commit limit can be changed by calling
:c:func:`mps_arena_spare_commit_limit_set`.
.. c:function:: void mps_arena_spare_commit_limit_set(mps_arena_t arena, size_t limit)
Change the :term:`spare commit limit` for an :term:`arena`.
``arena`` is the arena to change the spare commit limit for.
``limit`` is the new spare commit limit in :term:`bytes <byte (1)>`.
The spare commit limit is the maximum amount of :term:`spare
committed memory` the MPS is allowed to have. Setting it to a
value lower than the current amount of spare committed memory
causes spare committed memory to be uncommitted so as to bring the
value under the limit. In particular, setting it to 0 will mean
that the MPS will have no spare committed memory.
Non-virtual-memory arena classes (for example, a :term:`client
arena`) do not have spare committed memory. For these arenas, this
function functions sets a value but has no other effect.
Initially the spare commit limit is a configuration-dependent
value. The value of the limit can be retrieved by the function
:c:func:`mps_arena_spare_commit_limit`.
.. c:function:: size_t mps_arena_spare_committed(mps_arena_t arena)
Return the total :term:`spare committed memory` for an
:term:`arena`.
``arena`` is the arena.
Returns the number of bytes of spare committed memory.
Spare committed memory is memory which the arena is managing as
free memory (not in use by any pool and not otherwise in use for
internal reasons) but which remains committed (mapped to RAM by
the operating system). It is used by the arena to (attempt to)
avoid calling the operating system to repeatedly map and unmap
areas of :term:`virtual memory` as the amount of memory in use
goes up and down. Spare committed memory is counted as committed
memory by :c:func:`mps_arena_committed` and is restricted by
:c:func:`mps_arena_commit_limit`.
The amount of "spare committed" memory can be limited by calling
:c:func:`mps_arena_spare_commit_limit_set`, and the value of that
limit can be retrieved with
:c:func:`mps_arena_spare_commit_limit`. This is analogous to the
functions for limiting the amount of :term:`committed <mapped>`
memory.
.. c:function:: mps_res_t mps_arena_start_collect(mps_arena_t arena)
Request an :term:`arena` to start a full :term:`collection cycle`.
``arena`` is the arena.
Returns :c:macro:`MPS_RES_OK` if a collection is started, or
another :term:`result code` if not.
This function puts ``arena`` into the :term:`unclamped state` and
requests that it start a full collection cycle. The call to
:c:func:`mps_arena_start_collect` returns quickly, leaving the
collection to proceed incrementally (as for a collection that is
scheduled automatically).
.. note::
Contrast with :c:func:`mps_arena_collect`, which does not
return until the collection has completed.
.. c:function:: mps_bool_t mps_arena_step(mps_arena_t arena, double interval, double multiplier)
Request an :term:`arena` to do some work during a period where the
:term:`client program` is idle.
``arena`` is the arena.
``interval`` is the time, in seconds, the MPS is permitted to
take. It must not be negative, but may be ``0.0``.
``multiplier`` is the number of further similar calls that the
client program expects to make during this idle period.
Returns true if there was work for the MPS to do in ``arena``
(regardless of whether or not it did any) or false if there was
nothing to do.
:c:func:`mps_arena_step` allows the client program to make use of
idle time to do some garbage collection, for example when it is
waiting for interactive input. The MPS makes every effort to
return from this function within ``interval`` seconds, but cannot
guarantee to do so, as it may need to call your own scanning
code. It uses ``multiplier`` to decide whether to commence
long-duration operations that consume CPU (such as a full
collection): it will only start such an operation if it is
expected to be completed within ``multiplier * interval`` seconds.
If the arena was in the :term:`parked state` or the :term:`clamped
state` before :c:func:`mps_arena_step` was called, it is in the
clamped state afterwards. It it was in the :term:`unclamped
state`, it remains there.
.. c:type:: mps_arena_t
The type of :term:`arenas <arena>`.
An arena is responsible for requesting :term:`memory (3)` from
the operating system, making it available to :term:`pools <pool>`,
and for :term:`garbage collection`.
.. c:function:: void mps_arena_unsafe_expose_remember_protection(mps_arena_t arena)
Ensure that the MPS is not protecting any :term:`page` in the
:term:`arena` with a :term:`read barrier` or :term:`write
barrier`. In addition, request the MPS to remember some parts of its
internal state so that they can be restored later.
``mps_arena`` is the arena to expose.
This function is the same as :c:func:`mps_arena_expose`, but
additionally causes the MPS to remember its protection state. The
remembered protection state can optionally be restored later by
calling the :c:func:`mps_arena_unsafe_restore_protection` function.
This is an optimization that avoids the MPS having to recompute
all the remembered sets by scanning the entire arena.
However, restoring the remembered protections is only safe if the
contents of the exposed pages have not been changed; therefore
this function should only be used if you do not intend to change
the pages, and the remembered protection must only be restored if
the pages have not been changed.
The MPS will only remember the protection state if resources
(memory) are available. If memory is low then only some or
possibly none of the protection state will be remembered, with a
corresponding necessity to recompute it later. The MPS provides no
mechanism for the :term:`client program` to determine whether the
MPS has in fact remembered the protection state.
The remembered protection state, if any, is discarded after
calling calling :c:func:`mps_arena_unsafe_restore_protection`, or
as soon as the arena leaves the :term:`clamped state` by calling
:c:func:`mps_arena_release`.
.. c:function:: void mps_arena_unsafe_restore_protection(mps_arena_t arena)
Restore the remembered protection state for an :term:`arena`.
``mps_arena`` is the arena to restore the protection state for.
This function restores the protection state that the MPS has
remembered when the :term:`client program` called
:c:func:`mps_arena_unsafe_expose_remember_protection`. The purpose
of remembering and restoring the protection state is to avoid the
need for the MPS to recompute all the :term:`remembered sets
<remembered set>` by scanning the entire arena, that occurs when
:c:func:`mps_arena_expose` is used, and which causes the next
:term:`garbage collection` to be slow.
The client program must not change the exposed data between the
call to :c:func:`mps_arena_unsafe_expose_remember_protection` and
:c:func:`mps_arena_unsafe_restore_protection`. If the client
program has changed the exposed data then
:c:func:`mps_arena_unsafe_restore_protection` must not be called:
in this case simply call :c:func:`mps_arena_release`.
Calling this function does not release the arena from the clamped
state: :c:func:`mps_arena_release` must be called to continue
normal collections.
Calling this function causes the MPS to forget the remember
protection state; as a consequence the same remembered state
cannot be restored more than once.
.. c:function:: mps_word_t mps_collections(mps_arena_t arena)
Return the number of :term:`collection cycles <collection cycle>`
that have been completed on an :term:`arena` since it was created.
``arena`` is the arena.
Arena classes
-------------
.. c:function:: mps_arena_class_t mps_arena_class_cl(void)
::
#include "mpsacl.h"
Return the :term:`arena class` for a :term:`client arena`.
A client arena gets its managed memory from the :term:`client
program`. This memory chunk is passed when the arena is created.
When creating a client arena, :c:func:`mps_arena_create` takes two
extra arguments::
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t mps_arena_class_cl,
size_t size, mps_addr_t base)
``base`` is the :term:`address` of the chunk of memory that will
be managed by the arena.
``size`` is its :term:`size`.
If the chunk is too small to hold the internal arena structures,
:c:func:`mps_arena_create` returns :c:macro:`MPS_RES_MEMORY`. In
this case, you need to use a (much) larger chunk.
.. c:function:: mps_arena_class_t mps_arena_class_vm(void)
::
#include "mpsavm.h"
Return the :term:`arena class` for a :term:`virtual memory arena`.
A virtual memory arena uses the operating system's :term:`virtual
memory` interface to allocate memory. The chief consequence of
this is that the arena can manage many more virtual addresses than
it needs to commit memory to. This gives it flexibility as to
where to place :term:`blocks <block>`, which reduces
:term:`fragmentation` and helps make :term:`garbage collection`
more efficient.
When creating a virtual memory arena, :c:func:`mps_arena_create`
takes one extra argument::
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t arena_class_vm(),
size_t size)
``size`` is the initial amount of virtual address space, in
:term:`bytes <byte (1)>`, that the arena will reserve (this space
is initially reserved so that the arena can subsequently use it
without interference from other parts of the program, but most of
it is not committed, so it don't require any RAM or backing
store). The arena may allocate more virtual address space beyond
this initial reservation as and when it deems it necessary. The
MPS is most efficient if you reserve an address space that is
several times larger than your peak memory usage.
If the MPS fails to reserve adequate address space to place the
arena in, :c:func:`mps_arena_create` returns
:c:macro:`MPS_RES_RESOURCE`. Possibly this means that other parts
of the program are reserving too much virtual memory.
If the MPS fails to allocate memory for the internal arena
structures, :c:func:`mps_arena_create` returns
:c:macro:`MPS_RES_MEMORY`. Either ``size`` was far too small or you
ran out of swap space.

View file

@ -1,6 +1,5 @@
.. _topic-cache:
=================
Allocation caches
=================
@ -146,3 +145,289 @@ What does this mean? (from mps_sac_alloc):
mps_sac_flush(sac_large);
/* Use sac_small. */
Interface
---------
.. c:function:: mps_res_t mps_sac_alloc(mps_addr_t *p_o, mps_sac_t sac, size_t size, mps_bool_t has_reservoir_permit)
Allocate a :term:`block` using a :term:`segregated allocation
cache`. If no suitable block exists in the cache, ask for more
memory from the associated :term:`pool`.
``p_o`` points to a location that will hold the address of the
allocated block.
``sac`` is the segregated allocation cache.
``size`` is the :term:`size` of the block to allocate. It does not
have to be one of the :term:`sizes classes <size class>` of the
cache; nor does it have to be aligned.
``has_reservoir_permit`` should be false.
Returns :c:macro:`MPS_RES_OK` if successful: in this case the
address of the allocated block is ``*p_o``. The allocated block
can be larger than requested. Blocks not matching any size class
are allocated from the next largest class, and blocks larger than
the largest size class are simply allocated at the requested size
(rounded up to alignment, as usual).
Returns :c:macro:`MPS_RES_MEMORY` if there wasn't enough memory,
:c:macro:`MPS_RES_COMMIT_LIMIT` if the :term:`commit limit` was
exceeded, or :c:macro:`MPS_RES_RESOURCE` if it ran out of
:term:`virtual memory`.
.. note::
There's also a macro :c:func:`MPS_SAC_ALLOC_FAST` that does
the same thing. The macro is faster, but generates more code
and does less checking.
The :term:`client program` is responsible for synchronizing
the access to the cache, but if the cache decides to access
the pool, the MPS will properly synchronize with any other
:term:`threads <thread>` that might be accessing the same
pool.
Blocks allocated through a segregated allocation cache should
only be freed through a segregated allocation cache with the
same :term:`class structure`. Calling :c:func:`mps_free` on
them can cause :term:`memory leaks <memory leak>`, because the
size of the block might be larger than you think. Naturally,
the cache must also be attached to the same pool.
.. c:function:: MPS_SAC_ALLOC_FAST(mps_res_t res_v, mps_addr_t *p_v, mps_sac_t sac, size_t size, mps_bool_t has_reservoir_permit)
A macro alternative to :c:func:`mps_sac_alloc`. It is faster than
the function, but generates more code, does less checking.
It takes an lvalue ``p_v`` which is assigned the address of the
allocated block (instead of a pointer to a location to store
it). It takes an additional first argument, the lvalue ``res_v``,
which is assigned the :term:`result code`.
.. note::
:c:func:`MPS_SAC_ALLOC_FAST` may evaluate its arguments
multiple times, except for ``has_reservoir_permit``, which it
evaluates at most once, and only if it decides to access the
pool.
.. c:macro:: MPS_SAC_CLASS_LIMIT
The number of :term:`size classes <size class>` that
:c:func:`mps_sac_create` is guaranteed to accept.
More might be accepted: in fact, there might not be any limit in
the implementation on the maximum number of size classes, but if
you specify more than this many, you should be prepared to handle
the :term:`result code` :c:macro:`MPS_RES_LIMIT`.
.. c:function:: void mps_sac_free(mps_sac_t sac, mps_addr_t p, size_t size)
Free a :term:`block` using a :term:`segregated allocation
cache`. If the cache would become too full, some blocks may be
returned to the associated :term:`pool`.
``sac`` is the segregated allocation cache.
``p`` points to the block to be freed. This block must have been
allocated through a segregated allocation cache with the same
:term:`class structure`, attached to the same pool. (Usually,
you'd use the same cache to allocate and deallocate a block, but
the MPS is more flexible.)
``size`` is the :term:`size` of the block. It should be the size
that was specified when the block was allocated (the cache knows
what the real size of the block is).
.. note::
The :term:`client program` is responsible for synchronizing
the access to the cache, but if the cache decides to access
the pool, the MPS will properly synchronize with any other
:term:`threads <thread>` that might be accessing the same
pool.
There's also a macro :c:func:`MPS_SAC_FREE_FAST` that does the
same thing. The macro is faster, but generates more code and
does no checking.
:c:func:`mps_sac_free` does very little checking: it's
optimized for speed. :term:`Double frees <double free>` and
other mistakes will only be detected when the cache is flushed
(either by calling :c:func:`mps_sac_flush` or automatically),
and may not be detected at all, if intervening operations have
obscured symptoms.
.. c:function:: MPS_SAC_FREE_FAST(mps_sac_t sac, mps_addr_t p, size_t size)
A macro alternative to :c:func:`mps_sac_free` that is faster than
the function but does no checking. The arguments are identical to
the function.
.. c:type:: mps_sac_class_s
The type of the structure describing a :term:`size class` in a
:term:`segregated allocation cache`. ::
typedef struct mps_sac_class_s {
size_t mps_block_size;
size_t mps_cached_count;
unsigned mps_frequency;
} mps_sac_class_s;
An array of these structures must be passed to
:c:func:`mps_sac_create` when creating a segregated allocation
cache.
``mps_block_size`` is the maximum :term:`size` of any :term:`block`
in this size class. It must be a multiple of the alignment of the
:term:`alignment` of the :term:`pool` to which the cache belongs.
``mps_cached_count`` is the number of blocks of this size class to
cache. It is advice to the MPS on how many blocks to cache, not an
absolute limit. The cache policy tries to accommodate fluctuations
in the population and minimize the cost of responding to client
requests; the purpose of this parameter is to limit how much
memory the :term:`client program` is willing to set aside for this
purpose. However, a ``cached_count`` of zero prevents any caching of
blocks falling into that size class.
``mps_frequency`` is a number that describes the frequency of
requests (allocation and deallocation combined) in this size class
relative to the other size classes in the cache.
.. c:function:: mps_res_t mps_sac_create(mps_sac_t *sac_o, mps_pool_t pool, size_t classes_count, mps_sac_class_s *classes)
Create a :term:`segregated allocation cache` for a :term:`pool`.
``sac_o`` points to a location that will hold the address of the
segregated allocation cache.
``pool`` is the pool the cache is attached to.
``classes_count`` is the number of :term:`size classes <size class>`
in the cache.
``classes`` points to an array describing the size classes in the
cache.
Returns :c:macro:`MPS_RES_OK` if the segregated allocation cache
is created successfully. Returns :c:macro:`MPS_RES_MEMORY` or
:c:macro:`MPS_RES_COMMIT_LIMIT` when it fails to allocate memory
for the internal cache structure. Returns :c:macro:`MPS_RES_LIMIT`
if you ask for too many size classes: in this case, combine some
small adjacent classes. Returns :c:macro:`MPS_RES_PARAM` if the
pool doesn't support segregated allocation caches.
After this function returns, the array of size classes pointed to
be ``classes`` is no longer needed and may be discarded. The
segregated allocation cache pointed to by ``sac_o`` persists until
it is destroyed by calling :c:func:`mps_sac_destroy`.
This function creates an allocation cache whose :term:`free list`
is segregated into the given size classes. The cache can get more
memory from the given pool, or return memory to it.
Segregated allocation caches can be associated with any pool that
supports :term:`manual <manual memory management>` allocation with
the functions :c:func:`mps_alloc` and :c:func:`mps_free`.
The size classes are described by an array of element type
:c:func:`mps_sac_class_s`. This array is used to initialize the
segregated allocation cache, and is not needed
after:c:func:`mps_sac_create` returns. The following constraints
apply to the array:
* You must specify at least one size class.
* All size classes must have different sizes.
* The size classes must be given in the order of increasing size.
* The smallest size must be at least as large as ``sizeof(void *)``.
* Each size must be a multiple of the :term:`alignment` of the
pool.
* There might be a limit on how many classes can be described, but
it will be at least :c:macro:`MPS_SAC_CLASS_LIMIT`.
The MPS automatically provides an "overlarge" size class for
arbitrarily large allocations above the largest size class
described. Allocations falling into the overlarge size class are
not cached.
Any allocations whose size falls between two size classes are
allocated from the larger size class.
.. note::
Too many size classes will slow down allocation; too few size
classes waste more space in internal fragmentation. It is
assumed that overlarge allocations are rare; otherwise, you
would add another size class for them, or even create separate
allocation caches or pools for them.
.. warning::
Segregated allocation caches work poorly with debugging pool
classes: the debugging checks only happen when blocks are
moved between the cache and the pool.
.. c:function:: void mps_sac_destroy(mps_sac_t sac)
Destroy a :term:`segregated allocation cache`.
``sac`` is the segregated allocation cache to destroy.
Returns all memory in the cache to the associated :term:`pool`.
The pool might then return some memory to the :term:`arena`, but
that's up to the pool's usual policy.
Destroying the cache has no effect on blocks allocated through it.
.. c:function:: void mps_sac_flush(mps_sac_t sac)
Flush a :term:`segregated allocation cache`, returning all memory
held in it to the associated :term:`pool`.
``sac`` is the segregated allocation cache to flush.
This is something that you'd typically do when you know you won't
be using the segregated allocation cache for awhile, but want to
hold on to the cache itself. Destroying a cache has the effect of
flushing it.
Flushing the segregated allocation cache might well cause the pool
to return some memory to the :term:`arena`, but that's up to the
pool's usual policy.
Note that the MPS might also decide to take memory from the
segregated allocation cache without the :term:`client program`
requesting a flush.
.. note::
The :term:`client program` is responsible for synchronizing
the access to the cache, but if the cache decides to access
the pool, the MPS will properly synchronize with any other
:term:`threads <thread>` that might be accessing the same
pool.
.. c:type:: mps_sac_t
The type of :term:`segregated allocation caches <segregated
allocation cache>`.

View file

@ -1,8 +1,68 @@
.. _topic-collection:
==================
Garbage collection
==================
Interface
---------
.. c:function:: mps_res_t mps_chain_create(mps_chain_t *chain_o, mps_arena_t arena, size_t gen_count, mps_gen_param_s *gen_params)
Create a :term:`generation chain`.
``chain_o`` points to a location that will hold a pointer to the
new generation chain.
``arena`` is the arena to which the generation chain will belong.
``gen_count`` is the number of :term:`generations <generation>` in
the chain.
``gen_params`` points to an array describing the generations.
Returns :c:macro:`MPS_RES_OK` if the generation chain is created
successfully, or another :term:`result code` if it fails.
The generation chain persists until it is destroyed by calling
:c:func:`mps_chain_destroy`.
.. c:function:: void mps_chain_destroy(mps_chain_t chain)
Destroy a :term:`generation chain`.
``chain`` is the generation chain.
.. c:type:: mps_chain_t
The type of :term:`generation chains <generation chain>`. A
generation chain describes the structure of :term:`generations
<generation>` in a :term:`pool`.
.. c:type:: mps_gen_param_s
The type of the structure used to specify a :term:`generation` in
a :term:`generation chain`. ::
typedef struct mps_gen_param_s {
size_t mps_capacity;
double mps_mortality;
} mps_gen_param_s;
``mps_capacity`` is the capacity of the generation, in
:term:`kilobytes <kilobyte>`.
``mps_mortality`` is the predicted mortality of the generation:
the proportion (between 0 and 1) of blocks in the generation that
are expected to be :term:`dead` when the generation is collected.
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 discussed in the guide :ref:`guide-perf`.

View file

@ -1,6 +1,5 @@
.. _topic-debugging:
===============
Debugging pools
===============
@ -18,3 +17,85 @@ Debugging pools
exit(2);
}
Interface
---------
.. c:function:: void mps_pool_check_fenceposts(mps_pool_t pool)
Check all the :term:`fenceposts <fencepost>` in a :term:`pool`.
``pool`` is the pool whose fenceposts are to be checked.
If a corrupted fencepost is found, the MPS will :term:`assert
<assertion>`. It is only useful to call this on a :term:`debugging
pool` that has fenceposts turned on. It does nothing on
non-debugging pools.
.. c:function:: void mps_pool_check_free_space(mps_pool_t mps_pool)
Check all the free space in a :term:`pool` for :term:`overwriting
errors <overwriting error>`
``pool`` is the pool whose free space is to be checked.
If corrupted free space is found, the MPS will :term:`assert
<assertion>`. It is only useful to call this on a :term:`debugging
pool` that has free space splatting turned on. It does nothing on
non-debugging pools.
.. c:type:: mps_pool_debug_option_s
The type of the structure used to pass options to
:c:func:`mps_pool_create` for debugging :term:`pool classes <pool
class>`. ::
typedef struct mps_pool_debug_option_s {
void *fence_template;
size_t fence_size;
void *free_template;
size_t free_size;
} mps_pool_debug_option_s;
``fence_template`` points to a template for :term:`fenceposts
<fencepost>`.
``fence_size`` is the :term:`size` of ``fence_template`` in
:term:`bytes <byte (1)>`, or zero if the debugging pool should not
use fenceposts.
``free_template`` points to a template for splatting free space.
``free_size`` is the :term:`size` of ``free_template`` in bytes, or
zero if the debugging pool should not splat free space.
Both ``fence_size`` and ``free_size`` must be a multiple of the
:term:`alignment` of the :term:`pool`, and also a multiple of the
alignment of the pool's :term:`object format` if it has one.
The debugging pool will copy the ``fence_size`` bytes pointed to by
``fence_template`` in a repeating pattern onto each fencepost during
allocation, and it will copy the bytes pointed to by
``free_template`` in a repeating pattern over free space after the
space is reclaimed.
The MPS may not always use the whole of a template: it may use
pieces smaller than the given size, for example to pad out part of
a block that was left unused because of alignment requirements.
Fencepost and free space templates allow the :term:`client
program` to specify patterns:
* that mimic illegal data values;
* that cause bus errors if wrongly interpreted as pointers;
* that cause assertions to fire if wrongly interpreted as data values;
* that contain an instruction sequence that wold cause the program
to signal an error or stop if wrongly interpreted as executable
code.

View file

@ -1,6 +1,5 @@
.. _topic-error:
=============
Error handing
=============
@ -40,3 +39,144 @@ There's some documentation at //info.ravenbrook.com/project/mps/doc/2002-06-18/o
}
For more examples, see doc.mps.ref-man.if-conv.
Interface
---------
.. c:type:: mps_res_t
The type of :term:`result codes <result code>`. It is an alias
(via the :term:`C` ``typedef`` mechanism) for ``int``, provided for
convenience and clarity.
A result code indicates the success or failure of an operation,
along with the reason for failure. As with error numbers in Unix,
the meaning of a result code depends on the call that returned it.
Refer to the documentation of the function for the exact meaning
of each result code.
The result codes are:
* :c:macro:`MPS_RES_OK`: operation succeeded.
* :c:macro:`MPS_RES_FAIL`: operation failed.
* :c:macro:`MPS_RES_IO`: an input/output error occurred.
* :c:macro:`MPS_RES_LIMIT`: an internal limitation was exceeded.
* :c:macro:`MPS_RES_MEMORY`: needed memory could not be obtained.
* :c:macro:`MPS_RES_RESOURCE`: a needed resource could not be
obtained.
* :c:macro:`MPS_RES_UNIMPL`: operation is not implemented.
* :c:macro:`MPS_RES_COMMIT_LIMIT`: the arena's :term:`commit
limit` would be exceeded.
* :c:macro:`MPS_RES_PARAM`: an invalid parameter was passed.
.. c:macro:: MPS_RES_COMMIT_LIMIT
A :term:`result code` indicating that an operation could not be
completed as requested without exceeding the :term:`commit limit`.
You need to deallocate something to make more space, or increase
the commit limit by calling :c:func:`mps_arena_commit_limit_set`.
.. c:macro:: MPS_RES_FAIL
A :term:`result code` indicating that something went wrong that
does not fall under the description of any other result code. The
exact meaning depends on the function that returned this result
code.
.. c:macro:: MPS_RES_IO
A :term:`result code` indicating that an input/output error
occurred. The exact meaning depends on the function that returned
this result code.
.. c:macro:: MPS_RES_LIMIT
A :term:`result code` indicating that an operation could not be
completed as requested because of an internal limitation of the
MPS. The exact meaning depends on the function that returned this
result code.
.. c:macro:: MPS_RES_MEMORY
A :term:`result code` indicating that an operation could not be
completed because there wasn't enough memory available.
You need to deallocate something or allow the :term:`garbage
collector` to reclaim something to free enough memory, or expand
the :term:`arena` (if you're using an arena for which that does
not happen automatically).
.. note::
Failing to acquire enough memory because the :term:`commit
limit` would have been exceeded is indicated by returning
:c:macro:`MPS_RES_COMMIT_LIMIT`, not ``MPS_RES_MEMORY``.
Running out of :term:`address space` (as might happen in
:term:`virtual memory` systems) is indicated by returning
:c:macro:`MPS_RES_RESOURCE`, not ``MPS_RES_MEMORY``.
.. c:macro:: MPS_RES_OK
A :term:`result code` indicating that an operation succeeded.
If a function takes an :term:`out parameter` or an :term:`in/out
parameter`, this parameter will only be updated if
:c:macro:`MPS_RES_OK` is returned. If any other result code is
returned, the parameter will be left untouched by the function.
:c:macro:`MPS_RES_OK` is zero.
.. c:macro:: MPS_RES_PARAM
A :term:`result code` indicating that an operation could not be
completed as requested because an invalid parameter was passed to
the operation. The exact meaning depends on the function that
returned this result code.
.. c:macro:: MPS_RES_RESOURCE
A :term:`result code` indicating that an operation could not be
completed as requested because the MPS could not obtain a needed
resource. The resource in question depends on the operation.
Two special cases have their own result codes: when the MPS runs
out of committed memory, it returns :c:macro:`MPS_RES_MEMORY`, and
when it cannot proceed without exceeding the :term:`commit limit`,
it returns :c:macro:`MPS_RES_COMMIT_LIMIT`.
This result code can be returned when the MPS runs out of
:term:`virtual memory`. If this happens, you need to reclaim
memory within your process (as for the result code
:c:macro:`MPS_RES_MEMORY`), or terminate other processes running
on the same machine.
.. c:macro:: MPS_RES_UNIMPL
A :term:`result code` indicating that an operation, or some vital
part of it, is not implemented.
This might be returned by functions that are no longer supported,
or by operations that are included for future expansion, but not
yet supported.

View file

@ -1,6 +1,5 @@
.. _topic-finalization:
============
Finalization
============
@ -31,3 +30,86 @@ Not all pool classes support finalization of objects. In general only pools tha
unknown_message_type();
}
}
Interface
---------
.. c:function:: mps_res_t mps_definalize(mps_arena_t arena, mps_addr_t *ref)
Deregister a :term:`block` for :term:`finalization`.
``arena`` is the arena in which the block lives.
``ref`` points to a :term:`reference` to the block to be
deregistered for finalization.
Returns :c:macro:`MPS_RES_OK` if successful, or
:c:macro:`MPS_RES_FAIL` if the block was not previously registered
for finalization.
.. note::
This function receives a pointer to a reference. This is to
avoid placing the restriction on the :term:`client program`
that the C call stack be a :term:`root`.
.. c:function:: mps_res_t mps_finalize(mps_arena_t arena, mps_addr_t *ref)
Register a :term:`block` for :term:`finalization`.
``arena`` is the arena in which the block lives.
``ref`` points to a :term:`reference` to the block to be
registered for finalization.
Returns :c:macro:`MPS_RES_OK` if successful, or another
:term:`result code` if not.
This function registers the block pointed to by ``*ref`` for
finalization. This block must have been allocated from a
:term:`pool` in ``arena``. Violations of this constraint may not
be checked by the MPS, and may be unsafe, causing the MPS to crash
in undefined ways.
.. note::
This function receives a pointer to a reference. This is to
avoid placing the restriction on the :term:`client program`
that the C call stack be a :term:`root`.
.. c:function:: void mps_message_finalization_ref(mps_addr_t *ref_o, mps_arena_t arena, mps_message_t message)
Returns the finalization reference for a finalization message.
``ref_o`` points to a location that will hold the finalization
reference.
``arena`` is the :term:`arena` which posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
not yet discarded. It must be a finalization message: see
:c:func:`mps_message_type_finalization`.
The reference returned by this method is a reference to the block
that was originally registered for :term:`finalization` by a call
to :c:func:`mps_finalize`.
.. note::
The reference returned is subject to the normal constraints,
such as might be imposed by a :term:`moving <moving garbage
collector>` collection, if appropriate. For this reason, it is
stored into the location pointed to by ``ref_o`` in order to
enable the :term:`client program` to place it directly into
scanned memory, without imposing the restriction that the C
stack be a :term:`root`.
The message itself is not affected by invoking this method.
Until the client program calls :c:func:`mps_message_discard`
to discard the message, it will refer to the object and
prevent its reclamation.

View file

@ -1,6 +1,5 @@
.. _topic-format:
==============
Object formats
==============
@ -128,3 +127,440 @@ See //info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mmdoc/proto
mps_pool_destroy(pool);
mps_format_destroy(format);
}
Interface
---------
.. c:function:: mps_bool_t mps_addr_fmt(mps_fmt_t *fmt_o, mps_arena_t arena, mps_addr_t addr)
Determine the :term:`object format` to which an address belongs.
``fmt_o`` points to a location that will hold the address of the
object format, if one is found.
``arena`` is the arena whose object formats will be considered.
``addr`` is the address.
If ``addr`` is the address of a location inside a block allocated
from a pool in ``arena``, and that pool has an object format, then
update the location pointed to by ``fmt_o`` with the address of
the object format, and return true.
If ``addr`` is the address of a location inside a block allocated
from a pool in ``arena``, but that pool has no object format,
return false.
If ``addr`` points to a location that is not managed by ``arena``,
return false.
If none of the above conditions is satisfied,
:c:func:`mps_addr_fmt` may return either true or false.
.. note::
This function might return a false positive by returning true
if you ask about an address that happens to be inside memory
managed by a pool with an object format, but which is not
inside a block allocated by that pool. It never returns a
false negative.
.. c:function:: void mps_arena_formatted_objects_walk(mps_arena_t arena, mps_formatted_objects_stepper_t f, void *p, size_t s)
Visit all :term:`formatted objects <formatted object>` in an
:term:`arena`.
``arena`` is the arena whose formatted objects you want to visit.
``f`` is a formatted objects stepper function. It will be called for
each formatted object in the arena. See
:c:type:`mps_formatted_objects_stepper_t`.
``p`` and ``s`` are arguments that will be passed to ``f`` each time it
is called. This is intended to make it easy to pass, for example,
an array and its size as parameters.
Each :term:`pool class` determines for which objects the stepper
function is called. Typically, all validly formatted objects are
visited. During a :term:`trace` this will in general be only the
:term:`black` objects, though the :ref:`pool-lo` pool, for
example, will walk all objects since they are validly formatted
whether they are black or :term:`white`. :term:`Padding objects
<padding object>` may be visited at the pool class's discretion:
the :term:`client program` should handle this case.
The function ``f`` may not allocate memory or access any
automatically-managed memory except within ``object``.
.. seealso::
:ref:`topic-arena`.
.. note::
Walking the heap is "dodgy".
.. c:type:: mps_fmt_A_s
The type of the structure used to create an :term:`object format`
of variant A. ::
typedef struct mps_fmt_A_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_A_s;
Broadly speaking, object formats of variant A are suitable for use
in :term:`copying <copying garbage collection>` or :term:`moving
<moving garbage collector>` :term:`pools <pool>`.
``align`` is an integer value specifying the alignment of objects
allocated with this format. It should be large enough to satisfy
the alignment requirements of any field in the objects, and it
must not be larger than the pool alignment.
``scan`` is a :term:`scan method` that identifies references
within objects belonging to this format. See
:c:type:`mps_fmt_scan_t`.
``skip`` is a :term:`skip method` that skips over objects
belonging to this format. See :c:type:`mps_fmt_skip_t`.
``copy`` is not used. (In older versions of the MPS it was a
:term:`copy method` that copied objects belonging to this
format.)
``fwd`` is a :term:`forward method` that stores relocation
information for an object belonging to this format that has moved.
See :c:type:`mps_fmt_fwd_t`.
``isfwd`` is a :term:`is-forwarded method` that determines if an
object belonging to this format has been moved. See
:c:type:`mps_fmt_isfwd_t`.
``pad`` is a :term:`padding method` that creates :term:`padding
objects <padding object>` belonging to this format. See
:c:type:`mps_fmt_pad_t`.
.. c:type:: mps_fmt_auto_header_s
The type of the structure used to create an :term:`object format`
of variant auto_header. ::
typedef struct mps_fmt_auto_header_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
size_t mps_headerSize;
} mps_fmt_auto_header_s;
Variant auto_header is the same as variant A except for the
removal of the unused ``copy`` method, and the addition of the
``mps_headerSize`` field. See :c:type:`mps_fmt_A_s`.
Broadly speaking, the object formats of this variant are suitable
for use in :term:`automatic memory management` for objects with
:term:`headers <in-band header>` (hence the name). More precisely,
this variant is intended for formats where the :term:`client
program's <client program>` pointers point some distance into the
memory :term:`block` containing the object. This typically happens
when the objects have a common header used for memory management
or class system purposes, but this situation also arises when the
low bits of a pointer are used for a tag. The MPS does not care
what the reason is, only about the offset of the pointer in
relation to the memory block.
``mps_headerSize`` is the size of the header, that is, the offset of
a client pointer from the base of the memory block.
.. note::
For technical reasons, formatted objects must be longer than
the header. In other words, objects consisting of only a
header are not supported.
Even if the header size is larger than or equal to
:term:`alignment`, the :term:`padding method` must still be
able to create :term:`padding objects <padding object>` down
to the alignment size.
Variant auto_header is only supported by :ref:`pool-amc` and
:ref:`pool-amcz`.
.. c:type:: mps_fmt_B_s
The type of the structure used to create an :term:`object format`
of variant B. ::
typedef struct mps_fmt_B_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
mps_fmt_class_t mps_class;
} mps_fmt_B_s;
Variant B is the same as variant A except for the addition of the
``mps_class`` method. See :c:type:`mps_fmt_A_s`.
.. c:type:: mps_addr_t (*mps_fmt_class_t)(mps_addr_t addr)
The type of the class method of an :term:`object format`.
``addr`` is the address of the object whose class is of interest.
Returns an address that is related to the class or type of the
object, or a null pointer if this is not possible.
It is recommended that a null pointer be returned for
:term:`padding objects <padding object>` and :term:`forwarding
objects <forwarding object>`.
.. c:function:: mps_res_t mps_fmt_create_A(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_A_s *fmt_A)
Create an :term:`object format` of variant A.
``fmt_o`` points to a location that will hold the address of the new
object format.
``arena`` is the arena in which to create the format.
``fmt_A`` points to a description of an object format of variant A.
Returns :c:macro:`MPS_RES_OK` if successful. The MPS may exhaust
some resource in the course of :c:func:`mps_fmt_create_A` and will
return an appropriate :term:`result code` if so.
After this function returns, the object format description pointed
to be ``fmt_A`` is no longer needed and may be discarded. The object
format pointed to by ``fmt_o`` persists until it is destroyed by
calling :c:func:`mps_fmt_destroy`.
.. c:function:: mps_res_t mps_fmt_create_B(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_B_s *fmt_B)
Create an :term:`object format` of variant B.
``fmt_o`` points to a location that will hold the address of the new
object format.
``arena`` is the arena in which to create the format.
``fmt_B`` points to a description of an object format of variant B.
Returns :c:macro:`MPS_RES_OK` if successful. The MPS may exhaust
some resource in the course of :c:func:`mps_fmt_create_B` and will
return an appropriate :term:`result code` if so.
.. c:function:: mps_res_t mps_fmt_create_auto_header(mps_fmt_t *fmt_o, mps_arena_t arena, mps_fmt_auto_header_s *fmt_ah)
Create an :term:`object format` of variant auto_header.
``fmt_o`` points to a location that will hold the address of the new
object format.
``arena`` is the arena in which to create the format.
``fmt_ah`` points to a description of an object format of variant
auto_header.
Returns :c:macro:`MPS_RES_OK` if successful. The MPS may exhaust
some resource in the course of
:c:func:`mps_fmt_create_auto_header` and will return an
appropriate :term:`result code` if so.
.. c:function:: void mps_fmt_destroy(mps_fmt_t fmt)
Destroy an :term:`object format`.
``fmt`` is the object format to destroy.
It is an error to destroy an object format if there exists a
:term:`pool` using the format. The pool must be destroyed first.
.. c:type:: void (*mps_fmt_fwd_t)(mps_addr_t old, mps_addr_t new)
The type of the :term:`forward method` of an :term:`object format`.
``old`` is the address of an object.
``new`` is the address to where the object has been moved.
The MPS calls the forward method for an object format when it has
relocated an object belonging to that format. The forward method
must replace the object at ``old`` with a :term:`forwarding marker`
that points to the address 'new'. The forwarding marker must meet
the following requirements:
1. It must be possible for the MPS to call other methods in the
object format (the :term:`scan method`, the :term:`skip method`
and so on) with the address of a forwarding marker as the
argument.
2. The forwarding marker must not be bigger than the original
object.
3. It must be possible for the :term:`is-forwarded method` of the
object format to distinguish the forwarding marker from
ordinary objects, and the is-forwarded method method must
return the address ``new``. See :c:type:`mps_fmt_isfwd_t`.
.. note::
This method is never invoked by the :term:`garbage collector`
on an object in a :term:`non-moving <non-moving garbage
collector>` :term:`pool`.
.. c:type:: mps_addr_t (*mps_fmt_isfwd_t)(mps_addr_t addr)
The type of the :term:`is-forwarded method` of an :term:`object
format`.
``addr`` is the address of a candidate object.
If the ``addr`` is the address of a :term:`forwarding object`, return
the address where the object was moved to. This must be the value
of the ``new`` argument supplied to the :term:`forward method` when
the object was moved. If not, return a null pointer.
.. note::
This method is never invoked by the :term:`garbage collector`
on an object in a :term:`non-moving <non-moving garbage
collector>` :term:`pool`.
.. c:type:: void (*mps_fmt_pad_t)(mps_addr_t addr, size_t size)
The type of the :term:`padding method` of an :term:`object
format`.
``addr`` is the address at which to create a :term:`padding object`.
``size`` is the :term:`size` of the padding object to be created.
The MPS calls a padding method when it wants to create a padding
object. Typically the MPS creates padding objects to fill in
otherwise unused gaps in memory; they allow the MPS to pack
objects into fixed-size units (such as operating system
:term:`pages <page>`).
The padding method must create a padding object of the specified
size at the specified address. The size can be any aligned (to the
format alignment) size. A padding object must be acceptable to
other methods in the format (the :term:`scan method`, the
:term:`skip method`, and so on).
.. c:type:: mps_res_t (*mps_fmt_scan_t)(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
The type of the :term:`scan method` of an :term:`object format`.
``ss`` is the :term:`scan state`. It must be passed to
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END` to delimit a
sequence of fix operations, and to the functions
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2` when fixing a
:term:`reference`.
``base`` points to the first :term:`formatted object` in the block
of memory to be scanned.
``limit`` points to the location just beyond the end of the block to
be scanned. Note that there might not be any object at this
location.
Returns a :term:`result code`. If a fix function returns a value
other than :c:macro:`MPS_RES_OK`, the scan method must return that
value, and may return without fixing any further references.
Generally, itis better if it returns as soon as possible. If the
scanning is completed successfully, the function should return
:c:macro:`MPS_RES_OK`.
The scan method for an object format is called when the MPS needs
to scan objects in a block of memory containing objects belonging
to that format. The scan method is called with a scan state and
the base and limit of the block of objects to scan. It must then
indicate references within the objects by calling
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2`.
.. seealso::
:ref:`topic-scanning`.
.. c:type:: mps_addr_t (*mps_fmt_skip_t)(mps_addr_t addr)
The type of the :term:`skip method` of an :term:`object format`.
``addr`` is the address of the object to be skipped.
Returns the address of the "next object". In an object format
without headers (for example, a format of variant A), this is the
address just past the end of this object. In an object format with
headers (for example, a format of variant auto_header), it's the
address just past where the header of next object would be, if
there were one. It is always the case that the difference between
``addr`` and the return value is the size of the block containing
the object.
A skip method is not allowed to fail.
.. note::
The MPS uses this method to determine the size of objects (by
subtracting ``addr`` from the result) as well as skipping over
them.
.. c:type:: mps_fmt_t
The type of an :term:`object format`.
.. c:type:: void (*mps_formatted_objects_stepper_t)(mps_addr_t addr, mps_fmt_t fmt, mps_pool_t pool, void *p, size_t s)
The type of a :term:`formatted objects <formatted object>`
:term:`stepper function`.
A function of this type can be passed to
:c:func:`mps_arena_formatted_objects_walk`, in which case it will
be called for each formatted object in an :term:`arena`. It
receives five arguments:
``addr`` is the address of the object.
``fmt`` is the :term:`object format` for that object.
``pool`` is the :term:`pool` to which the object belongs.
``p`` and ``s`` are the corresponding values that were passed to
:c:func:`mps_arena_formatted_objects_walk`.
.. seealso::
:ref:`topic-arena`.

View file

@ -0,0 +1,90 @@
.. _topic-frame:
Allocation frames
=================
Allocation frames are deprecated, starting with version 1.111.
Interface
---------
.. c:function:: mps_res_t mps_ap_frame_pop(mps_ap_t ap, mps_frame_t frame)
Declare that a set of :term:`blocks <block>` in a
:term:`allocation frame` are :term:`dead` or likely to be dead,
and pop the frame from the :term:`allocation point's <allocation
point>` frame stack.
``ap`` is the allocation point in which ``frame`` was pushed.
``frame`` is the allocation frame whose blocks are likely to be
dead.
Returns a :term:`result code`.
This function pops ``frame``, making its parent the current
frame. Popping invalidates ``frame`` and all frames pushed since
``frame``. Popping ``frame`` also makes a declaration about the set of
blocks which were allocated in ``frame`` and all frames which were
pushed since ``frame``.
The interpretation of this declaration depends on the :term:`pool`
that the allocation point belongs to. Typically, :term:`manual
<manual memory management>` pool classes use this declaration to
mean that the blocks are dead and their space can be reclaimed
immediately, whereas :term:`automatic <automatic memory
management>` pool classes use this declaration to mean that the
blocks are likely to be mostly dead, and may use this declaration
to alter its collection decisions. See the documentation for the
pool class.
In general a frame other than the current frame can be popped (all
frames pushed more recently will be invalidated as well, as
described above), but a pool class may impose the restriction that
only the current frame may be popped. This restriction means that
every push must have a corresponding pop. See the documentation
for the pool class.
It is illegal to pop frames out of order (so the sequence "A =
push; B = push; pop A; pop B" is illegal) or to pop the same frame
twice (so the sequence "A = push, pop A, pop A" is illegal).
.. deprecated:: 1.111
.. c:function:: mps_res_t mps_ap_frame_push(mps_frame_t *frame_o, mps_ap_t ap)
Declare a new :term:`allocation frame` and push it onto an
:term:`allocation point's <allocation point>` frame stack.
``frame_o`` points to a location that will hold the new frame if the
function is successful.
``ap`` is the allocation point in which the new frame is declared.
Returns a :term:`result code`. The creation of new frames (which
is implicit in the action of this function) can consume resources,
so this function can fail because there are insufficient
resources, or if the correct protocol is not followed by the
:term:`client program`.
.. deprecated:: 1.111
.. c:type:: mps_frame_t
The type of :term:`allocation frames <allocation frame>`.
An allocation frame is a marker that can pushed onto an
:term:`allocation point` by calling :c:func:`mps_ap_frame_push`,
and then popped by calling :c:func:`mps_ap_frame_pop` to indicate
that all blocks allocated on the allocation point are :term:`dead`
(in the case of :term:`manual <manual memory management>` pools),
or very likely dead (in the case of :term:`automatic <automatic
memory management>` pools).
Allocation frames can be used by the :term:`client program` to
efficiently implement stack-like patterns of allocation.
.. deprecated:: 1.111

View file

@ -1,11 +1,12 @@
Topic reference
***************
Reference
*********
.. toctree::
:numbered:
interface
arena
pool
allocation
collection
error
@ -23,3 +24,4 @@ Topic reference
debugging
location
thread
frame

View file

@ -10,4 +10,48 @@ conventions used by the MPS.
It also covers our policy for support for the external symbols.
Interface
---------
.. c:type:: mps_addr_t
The type of :term:`addresses <address>` managed by the MPS, and
also the type of :term:`references <reference>`.
It is used in the MPS interface for any pointer that is under the
control of the MPS. In accordance with standard :term:`C`
practice, null pointers of type :c:type:`mps_addr_t` will never be
used to represent a reference to a block.
.. topics::
:ref:`topic-platform`.
.. c:type:: mps_align_t
The type of an :term:`alignment`. It is an integral type
equivalent to ``size_t``. An alignment must be a positive power of
2.
.. c:type:: mps_bool_t
The type of a Boolean value. It is an integral type equivalent to
``int``.
When used as an input parameter to the MPS, a value of 0 means
"false" and any other value means "true". As an output parameter
or function return from the MPS, 0 means "false", and 1 means
"true".
.. c:type:: mps_word_t
An unsigned integral type that is the same size as an
:term:`object pointer`, so that ``sizeof(mps_word_t) ==
sizeof(void*)``.
The exact identity of this type is
:term:`platform`\-dependent. Typical identities are ``unsigned
long`` and ``unsigned __int_64``.2

View file

@ -1,7 +1,156 @@
.. _topic-location:
===================
Location dependency
===================
See //info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mmdoc/doc/mps/guide/ld/index.html
Interface
---------
.. c:function:: void mps_ld_add(mps_ld_t ld, mps_arena_t arena, mps_addr_t addr)
Add a dependency on a :term:`block` to a :term:`location
dependency`.
``ld`` is a location dependency.
``arena`` is the :term:`arena` to which ``addr`` belongs.
``addr`` is the address of the block.
After calling :c:func:`mps_ld_add`, and until ``ld`` is passed to
:c:func:`mps_ld_reset`, the call ::
mps_ld_isstale(ld, arena, addr)
will return true if the block has moved.
.. note::
It is an error to call :c:func:`mps_ld_add` on the same
location dependency with addresses from two different arenas.
If you need to test for staleness against multiple arenas,
then you need at least one location dependency for each arena.
:c:func:`mps_ld_add` is not thread-safe with respect to
:c:func:`mps_ld_add`, :c:func:`mps_ld_merge`, or
:c:func:`mps_ld_reset` on the same location dependency, but it
is thread-safe with respect to :c:func:`mps_ld_isstale`
operations. This means that calls to :c:func:`mps_ld_add` from
different :term:`threads <thread>` must interlock if they are
using the same location dependency. The practical upshot of
this is that there should be a lock associated with each
location dependency.
.. c:function:: mps_bool_t mps_ld_isstale(mps_ld_t ld, mps_arena_t arena, mps_addr_t addr)
Determine if any of the depdencies in a :term:`location
dependency` are stale with respect to an :term:`arena`.
``ld`` is the location dependency.
``arena`` is the arena to test for staleness against. It must be
the same arena that was passed to all calls to
:c:func:`mps_ld_add` on ``ld``.
``addr`` is an address that may appear in :term:`telemetry
<telemetry stream>` events related to this call (it will *not* be
tested for staleness).
The location dependency is examined to determine whether any of
the dependencies encapsulated in it have been made stale with
respect to ``arena``. If any of the dependencies encapsulated in
the location dependency are stale (that is, the blocks whose
location has been depended on have been moved by ``arena``) then
:c:func:`mps_ld_isstale` will return true. If there have been no
calls to :c:func:`mps_ld_add` on ``ld`` since the last call to
:c:func:`mps_ld_reset`, then :c:func:`mps_ld_isstale` will return
false. :c:func:`mps_ld_isstale` may return any value in other
circumstances (but will strive to return false if the objects
encapsulated in the location dependency have not moved).
.. note::
:c:func:`mps_ld_isstale` may report a false positive
(returning true despite none of the added addresses having
being moved by the arena) but never a false negative
(returning false when an added address has been moved).
:c:func:`mps_ld_isstale` is thread-safe with respect to itself
and with respect to :c:func:`mps_ld_add`, but not with respect
to :c:func:`mps_ld_reset`.
.. c:function:: void mps_ld_merge(mps_ld_t dest_ld, mps_arena_t arena, mps_ld_t src_ld)
Merge one :term:`location dependency` into another.
``dest_ld`` is the destination of the merge.
``arena`` is the :term:`arena` .
``src_ld`` is the source of the merge.
The effect of this is to add all the addresses that were added to
``src_ld`` to the ``dest_ld``.
:c:func:`mps_ld_merge` has the same thread-safety properties as
:c:func:`mps_ld_add`.
.. c:function:: void mps_ld_reset(mps_ld_t ld, mps_arena_t arena)
Reset a :term:`location dependency`.
``ld`` is the location dependency.
``arena`` is an arena.
After this call, ``ld`` encapsulates no dependencies. After the
call to :c:func:`mps_ld_reset` and prior to any call to
:c:func:`mps_ld_add` on ``ld``, :c:func:`mps_ld_isstale` on ``ld``
will return false for all arenas.
:c:func:`mps_ld_reset` is not thread-safe with respect to any
other location dependency function.
.. c:type:: mps_ld_s
The type of the structure used to represent a :term:`location
dependency`. ::
typedef struct mps_ld_s {
mps_word_t w0, w1;
} mps_ld_s;
It is an opaque structure type: it is supplied so that the
:term:`client program` can inline the structure (because its size
is known), but the client not access it other than through the
functions :c:func:`mps_ld_add`, :c:func:`mps_ld_isstale`,
:c:func:`mps_ld_merge`, and :c:func:`mps_ld_reset`.
.. c:type:: mps_ld_t
The type of :term:`location dependencies <location dependency>`.
It is an alias (via the :term:`C` ``typedef`` mechanism) for a
pointer to :c:type:`mps_ld_s`.
A location dependency records the fact that the :term:`client
program` depends on the bit patterns of some :term:`references
<reference>` (and not merely on the :term:`block` to which the
reference refers), and provides a function
(:c:func:`mps_ld_isstale`) to find out whether any of these
references have been changed because a block has been
:term:`moved <moving garbage collector>`.
A typical use is in the implementation of a hash table whiches
hashes blocks by hashing their addresses. After a block has moved,
the hash table needs to be rehashed, otherwise it will not be
found in the table.

View file

@ -1,6 +1,5 @@
.. _topic-message:
========
Messages
========
@ -33,3 +32,349 @@ Messages
printf("Collection started; reason: %s\n",
mps_message_gc_start_why(arena, message));
}
Interface
---------
.. c:function:: mps_clock_t mps_message_clock(mps_arena_t arena, mps_message_t message)
Returns the time at which the MPS posted a :term:`message`.
``arena`` is the :term:`arena` which posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
not yet discarded.
If ``message`` belongs to one of the following supported message,
return the time at which the MPS posted the message:
* :c:type:`mps_message_type_gc`;
* :c:type:`mps_message_type_gc_start`.
For other message types, the value returned is always zero.
Messages are asynchronous: they are posted by the MPS, wait on a
queue, and are later collected by the :term:`client program`. Each
message (of the supported message types) records the time that it
was posted, and this is what :c:func:`mps_message_clock` returns.
The time returned is the :c:func:`mps_clock_t` value returned by
the library function :c:func:`mps_clock` at the time the message
was posted. You can subtract one clock value from another to get
the time interval between the posting of two messages.
.. c:function:: void mps_message_discard(mps_arena_t arena, mps_message_t message)
Indicate to the MPS that the :term:`client program` has no further
use for a :term:`message` and the MPS can now reclaim any storage
associated with the message.
``arena`` is the :term:`arena` which posted the message.
``message`` is the message. After this call, ``message`` is invalid
and should not be passed as an argument to any message functions.
Messages are essentially :term:`manually <manual memory
management>` managed. This function allows the MPS to reclaim
storage associated with messages. If the client does not discard
messages then the resources used may grow without bound.
As well as consuming resources, messages may have other effects
that require them to be tidied by calling this function. In
particular finalization messages refer to a :term:`finalized
block`, and prevent the object from being reclaimed (subject to
the usual :term:`garbage collection` liveness analysis). A
finalized block cannot be reclaimed until all its finalization
messages have been discarded. See
:c:func:`mps_message_type_finalization`.
.. seealso::
:ref:`topic-finalization`.
.. c:function:: size_t mps_message_gc_condemned_size(mps_arena_t arena, mps_message_t message)
Return the "condemned size" property of a :term:`message`.
``arena`` is the arena which posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
not yet discarded. It must be a garbage collection message: see
:c:func:`mps_message_type_gc`.
The "condemned size" property is the approximate :term:`size` of
the :term:`condemned set` in the :term:`garbage collection` that
generated the message.
.. seealso::
:ref:`topic-collection`.
.. c:function:: size_t mps_message_gc_live_size(mps_arena_t arena, mps_message_t message)
Return the "live size" property of a :term:`message`.
``arena`` is the arena which posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
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
that survived the :term:`garbage collection` that generated the
message.
.. seealso::
:ref:`topic-collection`.
.. c:function:: size_t mps_message_gc_not_condemned_size(mps_arena_t arena, mps_message_t message)
Return the "not condemned size" property of a :term:`message`.
``arena`` is the arena which posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
not yet discarded. It must be a garbage collection message: see
: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 <pool>`, but
were not in the :term:`condemned set` in the :term:`garbage
collection` that generated the message.
.. seealso::
:ref:`topic-collection`.
.. c:function:: const char *mps_message_gc_start_why(mps_arena_t arena, mps_message_t message)
Return a string that describes why the :term:`garbage collection`
that posted a :term:`message` started.
``arena`` is the arena which posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
not yet discarded. It must be a garbage collection message: see
:c:func:`mps_message_type_gc`.
Returns a pointer to a string that is describes (in English) why
this collection started. The contents of the string must not be
modified by the client. The string and the pointer are valid until
the message is discarded with :c:func:`mps_message_discard`.
.. seealso::
:ref:`topic-collection`.
.. c:function:: mps_bool_t mps_message_get(mps_message_t *message_o, mps_arena_t arena, mps_message_type_t message_type)
Get a :term:`message` of a specified type from the :term:`message
queue` for an :term:`arena`.
``message_o`` points to a location that will hold the address of the
message if the function succeeds.
``arena`` is the arena.
``message_type`` is the type of message to return.
If there is at least one message of the specified type on the
message queue of the specified arena, then this function removes
one such message from the queue, stores a pointer to the message
in the location pointed to by ``message_o``, and returns true.
Otherwise it returns false.
.. c:function:: mps_bool_t mps_message_poll(mps_arena_t arena)
Determine whether there are currently any :term:`messages
<message>` on a :term:`message queue` for an :term:`arena`.
``arena`` is the arena whose message queue will be polled.
Returns true if there is at least one message on the message queue
for ``arena``, or false if the message queue is empty.
.. note::
If you are interested in a particular type of message, it is
usually simpler to call :c:func:`mps_message_get`.
.. c:function:: mps_bool_t mps_message_queue_type(mps_message_type_t *message_type_o, mps_arena_t arena)
Determine whether there are currently any :term:`messages
<message>` on a :term:`message queue` for an :term:`arena`, and
return the :term:`message type` of the first message, if any.
``message_type_o`` points to a location that will hold the message
type of the first message on the queue, if any.
``arena`` is the arena whose message queue will be polled.
If there is at least one message on the message queue of ``arena``,
then this function returns true, and also writes the message type
of the first message on the queue into the location pointed to by
``message_type_o``. If there are no messages on the message queue,
it returns false.
.. c:type:: mps_message_t
The type of a :term:`message`.
Messages are :term:`manually <manual memory management>` managed.
They are created at the instigation of the MPS (but see
:c:func:`mps_message_type_enable`), and are deleted by the
:term:`client program` by calling :c:func:`mps_message_discard`.
An :term:`arena` has a :term:`message queue` from which messages
can be obtained by calling :c:func:`mps_message_get`.
An :c:func:`mps_message_t` is a :term:`reference` into MPS managed
memory, and can safely be :term:`fixed <fix>`.
.. c:function:: mps_message_type_t mps_message_type(mps_arena_t arena, mps_message_t message)
Return the :term:`message type` of a :term:`message`.
``arena`` is the arena that posted the message.
``message`` is a message retrieved by :c:func:`mps_message_get` and
not yet discarded.
.. c:function:: void mps_message_type_disable(mps_arena_t arena, mps_message_type_t message_type)
Restore an :term:`arena` to the default state whereby
:term:`messages <message>` of the specified :term:`message type`
are not posted, reversing the effect of an earlier call to
:c:func:`mps_message_type_enable`.
``arena`` is an arena.
``message_type`` is the message type to be disabled.
Any existing messages of the specified type are flushed from the
:term:`message queue` of ``arena``.
.. note::
It is permitted to call this function when ``message_type`` is
already disabled, in which case it has no effect.
.. c:function:: void mps_message_type_enable(mps_arena_t arena, mps_message_type_t message_type)
Enable an :term:`arena` to post :term:`messages <message>` of a
specified :term:`message type`.
``arena`` is an arena.
``message_type`` is the message type to be disabled.
This function tells the MPS that ``arena`` may post messages of
``message_type`` to its :term:`message queue`. By default, the MPS
does not generate any messages of any type.
A :term:`client program` that enables messages for a message type
must access messages by calling :c:func:`mps_message_get` and
discard them by calling :c:func:`mps_message_discard`, or the
message queue may consume unbounded resources.
The client program may disable the posting of messages by calling
:c:func:`mps_message_type_disable`.
.. note::
It is permitted to call this function when ``message_type`` is
already enabled, in which case it has no effect.
.. c:function:: mps_message_type_t mps_message_type_finalization(void)
Return the :term:`message type` of finalization messages.
Finalization messages are used by the MPS to implement
:term:`finalization`. When the MPS detects that a block that has
been registered for finalization (by calling
:c:func:`mps_finalize`) is finalizable, it finalizes it by posting
a :term:`message` of this type.
Note that there might be delays between the block becoming
finalizable, the MPS detecting that, and the message being
posted.
In addition to the usual methods applicable to messages,
finalization messages support the
:c:func:`mps_message_finalization_ref` method which returns a
reference to the block that was registered for finalization.
.. seealso::
:ref:`topic-finalization`.
.. c:function:: mps_message_type_t mps_message_type_gc(void)
Return the :term:`message type` of garbage collection statistic
messages.
Garbage collection statistic messages are used by the MPS to give
the :term:`client program` information about a :term:`garbage
collection` that has taken place. Such information may be useful in
analysing the client program's memory usage over time.
The access methods specific to a message of this type are:
* :c:func:`mps_message_gc_live_size` returns the total size of the
:term:`condemned set` that survived the garbage collection that
generated the message;
* :c:func:`mps_message_gc_condemned_size` returns the approximate
size of :term:`condemned set` in the garbage collection that
generated the message;
* :c:func:`mps_message_gc_not_condemned_size` returns the
approximate size of the set of objects that were in collected
:term:`pools <pool>`, but were not condemned in the garbage
collection that generated the message.
.. seealso::
:ref:`topic-collection`.
.. c:function:: mps_message_type_t mps_message_type_gc_start(void)
Return the :term:`message type` of garbage collection start
messages.
Garbage collection start messages contain information about why
the :term:`garbage collection` started.
The access method specific to a :term:`message` of this message
type is:
* :c:func:`mps_message_gc_start_why` returns a string that
describes why the garbage collection started.
.. seealso::
:ref:`topic-collection`.
.. c:type:: mps_message_type_t
The type of :term:`message types <message type>`.

View file

@ -1,6 +1,5 @@
.. _topic-pattern:
===================
Allocation patterns
===================
@ -37,3 +36,110 @@ See //info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mmdoc/proto
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
Interface
---------
.. c:function:: mps_alloc_pattern_t mps_alloc_pattern_ramp(void)
Return an :term:`allocation pattern` indicating that allocation
will follow a :term:`ramp pattern`.
This indicates to the MPS that most of the blocks allocated after
the call to :c:func:`mps_ap_alloc_pattern_begin` are likely to be
:term:`dead` by the time of the corresponding call to
:c:func:`mps_ap_alloc_pattern_end`.
.. c:function:: mps_alloc_pattern_t mps_alloc_pattern_ramp_collect_all(void)
Return an :term:`allocation pattern` indicating that allocation
will follow a :term:`ramp pattern`, and that the next
:term:`garbage collection` following the ramp should be a full
collection.
This indicates to the MPS that most of the blocks allocated after
the call to :c:func:`mps_ap_alloc_pattern_begin` are likely to be
:term:`dead` by the time of the corresponding call to
:c:func:`mps_ap_alloc_pattern_end`.
This allocation pattern may nest with, but should not otherwise
overlap with, allocation patterns of type
:c:func:`mps_alloc_pattern_ramp`. In this case, the MPS may defer
the full collection until after all ramp allocation patterns have
ended.
.. c:type:: mps_alloc_pattern_t
The type of :term:`allocation patterns <allocation pattern>`.
An allocation pattern is a hint to the MPS to expect a particular
pattern of allocation on an :term:`allocation point`. The MPS may
use this hint to schedule its decisions as to when and what to
collect.
There are two allocation patterns,
:c:func:`mps_alloc_pattern_ramp` and
:c:func:`mps_alloc_pattern_ramp_collect_all`.
.. c:function:: mps_res_t mps_ap_alloc_pattern_begin(mps_ap_t ap, mps_alloc_pattern_t alloc_pattern)
Start a period of allocation that behaves according to an
:term:`allocation pattern`. The period persists until a
corresponding call to :c:func:`mps_ap_alloc_pattern_end`.
``ap`` is the :term:`allocation point` in which the patterned
allocation will occur.
``alloc_pattern`` is the allocation pattern.
Returns :c:macro:`MPS_RES_OK` if the allocation pattern is
supported by this allocation point. At present this is always the
case, but in future this function may return another :term:`result
code` if the allocation pattern is not supported by the allocation
point.
If :c:func:`mps_ap_alloc_pattern_begin` is used multiple times on
the same allocation point without intervening calls to
:c:func:`mps_ap_alloc_pattern_end`, the calls match in a
stack-like way, outermost and innermost: that is, allocation
patterns may nest, but not otherwise overlap.
Some allocation patterns may additionally support overlap: if so,
the documentation for the individual pattern types will specify
this.
.. c:function:: mps_res_t mps_ap_alloc_pattern_end(mps_ap_t ap, mps_alloc_pattern_t alloc_pattern)
End a period of allocation on an :term:`allocation point` that
behaves according to an :term:`allocation pattern`.
``ap`` is the allocation point in which the patterned allocation
occurred.
``alloc_pattern`` is the allocation pattern.
Returns :c:macro:`MPS_RES_OK` if the period of allocation was
successfully ended, or :c:macro:`MPS_RES_FAIL` if there was no
corresponding call to :c:func:`mps_ap_alloc_pattern_begin`.
.. c:function:: mps_res_t mps_ap_alloc_pattern_reset(mps_ap_t ap)
End all :term:`patterned allocation <allocation pattern>` on an
:term:`allocation point`.
``ap`` is the allocation point on which to end all patterned
allocation.
Returns :c:macro:`MPS_RES_OK`. It may fail in future if certain
allocation patterns cannot be ended for that allocation point at
that point in time.
This function may be used to recover from error conditions.

View file

@ -0,0 +1,104 @@
.. _topic-pool:
Pools
=====
Interface
---------
.. c:function:: mps_bool_t mps_addr_pool(mps_pool_t *pool_o, mps_arena_t arena, mps_addr_t addr)
Determine the :term:`pool` to which an address belongs.
``pool_o`` points to a location that will hold the address of the
pool, if one is found.
``arena`` is the arena whose pools will be considered.
``addr`` is the address.
If ``addr`` is the address of a location inside a block allocated
from a pool in ``arena``, then update the location pointed to by
``pool_o`` with the address of the pool, and return true.
If ``addr`` points to a location that is not managed by ``arena``,
return false.
If neither of the above conditions is satisfied,
:c:func:`mps_addr_pool` may return either true or false.
.. note::
This function might return a false positive by returning true
if you ask about an address that happens to be inside memory
managed by a pool, but which is not inside a block allocated
by that pool. It never returns a false negative.
.. c:type:: mps_class_t
The type of :term:`pool classes <pool class>`.
.. c:function:: mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena, mps_class_t class, ...)
Create a :term:`pool` in an :term:`arena`.
``pool_o`` points to a location that will hold a pointer to the new
pool.
``arena`` is the arena in which to create the pool.
``class`` is the :term:`pool class` of the new pool.
Some pool classes require additional arguments to be passed to
:c:func:`mps_pool_create`. See the documentation for the pool
class.
Returns :c:macro:`MPS_RES_OK` if the pool is created successfully,
or another :term:`result code` otherwise.
The pool persists until it is destroyed by calling
:c:func:`mps_pool_destroy`.
.. note::
There's an alternative function :c:func:`pool_create_v` that
takes its extra arguments using the standard :term:`C`
``va_list`` mechanism.
.. c:function:: mps_res_t mps_pool_create_v(mps_pool_t *pool_o, mps_arena_t arena, mps_class_t class, va_list args)
An alternative to :c:func:`mps_pool_create` that takes its extra
arguments using the standard :term:`C` ``va_list`` mechanism.
.. c:function:: void mps_pool_destroy(mps_pool_t pool)
Destroy a :term:`pool`.
``pool`` is the pool to destroy.
This function checks the consistency of the pool, destroys the
pool's internal control structures and causes the pool's memory to
be returned to the :term:`arena` for reuse by other pools, or to
be returned to the operating system. Blocks allocated from the
pool may no longer be used.
It is an error to destroy a pool without first destroying all
:term:`allocation points <allocation point>` and :term:`segregated
allocation caches <segregated allocation cache>` created in the
pool.
.. c:type:: mps_pool_t
The type of :term:`pools <pool>`.
A pool is responsible for requesting memory from the :term:`arena`
and making it available to the :term:`client program` via
:c:func:`mps_alloc` or via an :term:`allocation point`.

View file

@ -1,6 +1,5 @@
.. _topic-root:
=====
Roots
=====
@ -169,3 +168,388 @@ There may be problems if the client wants the OS to access the root. Lots of OSe
return res;
}
Interface
---------
.. c:function:: void mps_arena_roots_walk(mps_arena_t arena, mps_roots_stepper_t f, void *p, size_t s)
Visit references in registered :term:`roots <root>` in an
:term:`arena`.
``arena`` is the arena whose roots you want to visit.
``f`` is a function that will be called for each reference to an
object in an :term:`automatically <automatic memory management>`
managed :term:`pool class` that was found in a registered root
beloging to the arena. It takes four arguments: ``ref`` is the
address of a reference to an object in the arena, ``root`` is the
root in which ``ref`` was found, and ``p`` and ``s`` are the
corresponding arguments that were passed to
:c:func:`mps_arena_roots_walk`.
``p`` and ``s`` are arguments that will be passed to ``f`` each time it
is called. This is intended to make it easy to pass, for example,
an array and its size as parameters.
This function may only be called when the arena is in the
:term:`parked state`.
.. seealso::
:ref:`topic-arena`.
.. note::
If a root is :term:`ambiguous <ambiguous root>` then the
reference might not be to the start of an object; the
:term:`client program` should handle this case. There is no
guarantee that the reference corresponds to the actual
location that holds the pointer to the object (since this
might be a register, for example), but the actual location
will be passed if possible. This may aid analysis of roots via
a debugger.
.. c:function:: mps_rank_t mps_rank_ambig(void)
Return the :term:`rank` of :term:`ambiguous roots <ambiguous
root>`.
.. c:function:: mps_rank_t mps_rank_exact(void)
Return the :term:`rank` of :term:`exact roots <exact root>`.
.. c:type:: mps_rank_t
The type of :term:`ranks <rank>`. It is an alias (via the
:term:`C` ``typedef`` mechanism) for ``unsigned int``, provided
for convenience and clarity.
.. c:function:: mps_rank_t mps_rank_weak(void)
Return the :term:`rank` of :term:`weak roots <weak root>`.
.. c:type:: mps_res_t (*mps_reg_scan_t)(mps_ss_t ss, mps_thr_t thr, void *p, size_t s)
The type of a root scanning function for roots created with
:c:func:`mps_root_create_reg`.
``ss`` is the :term:`scan state`. It must be passed to
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END` to delimit a
sequence of fix operations, and to the functions
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2` when fixing a
:term:`reference`.
``thr`` is the :term:`thread`.
``p`` and ``s`` are the corresponding values that were passed to
:c:func:`mps_root_create_reg`.
Returns a :term:`result code`. If a fix function returns a value
other than :c:macro:`MPS_RES_OK`, the scan method must return that
value, and may return without fixing any further references.
Generally, itis better if it returns as soon as possible. If the
scanning is completed successfully, the function should return
:c:macro:`MPS_RES_OK`.
A root scan method is called whenever the MPS needs to scan the
root. It must then indicate references within the root by calling
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2`.
.. seealso::
:ref:`topic-scanning`.
.. note::
:term:`Client programs <client program>` are not expected to
write scanning functions of this type. The built-in MPS
function :c:func:`mps_stack_scan_ambig` should be used.
.. c:macro:: MPS_RM_CONST
The :term:`root mode` for :term:`constant roots <constant root>`.
This tells the MPS that the :term:`client program` will not change
the :term:`root` after it is registered: that is, scanning the
root will produce the same set of :term:`references <reference>`
every time. Furthermore, for roots registered by
:c:func:`mps_root_create_fmt` and :c:func:`mps_root_create_table`,
the client program will not write to the root at all.
.. note::
Currently ignored by the MPS.
.. c:macro:: MPS_RM_PROT
The :term:`root mode` for :term:`protectable roots <protectable
root>`. This tells the MPS that it may place a :term:`write
barrier` on any :term:`page` which any part of the :term:`root`
covers. No :term:`format method` or :term:`scan method` (except
for the one for this root) may write data in this root. They may
read it.
.. note::
You must not specify ``MPS_RM_PROT`` on a root allocated by
the MPS.
No page may contain parts of two or more protectable roots.
You mustn't specify ``MPS_RM_PROT`` if the :term:`client
program` or anything other than (this instance of) the MPS is
going to protect or unprotect the relevant pages.
.. c:type:: mps_rm_t
The type of :term:`root modes <root mode>`.
A root mode describes whether a :term:`root` is :term:`constant
<constant root>`, :term:`protectable <protectable root>`, or both,
and lets the MPS know whether it may place a :term:`barrier (1)`
on the root.
It should be the sum of some subset of :c:macro:`MPS_RM_CONST` and
:c:macro:`MPS_RM_PROT`, or zero (meaning neither constant or
protectable).
.. note::
As of version 1.110, the MPS does not place barriers on roots,
and so does not make use of the root mode. The feature may be
added in a future release.
.. c:function:: mps_res_t mps_root_create(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_root_scan_t root_scan, void *p, size_t s)
Register a :term:`root` that consists of the :term:`references
<reference>` fixed by a scanning function.
``root_o`` points to a location that will hold the address of the
new root description.
``arena`` is the arena.
``rank`` is the :term:`rank` of references in the root.
``rm`` is the :term:`root mode`.
``root_scan`` is the root scanning function. See
:c:type:`mps_root_scan_t`.
``p`` and ``s`` are arguments that will be passed to ``root_scan`` each
time it is called. This is intended to make it easy to pass, for
example, an array and its size as parameters.
Returns :c:macro:`MPS_RES_OK` if the root was registered
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
description could not be allocated, or another :term:`result code`
if there was another error.
The registered root destription persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. c:function:: mps_res_t mps_root_create_fmt(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_fmt_scan_t fmt_scan, mps_addr_t base, mps_addr_t limit)
Register a :term:`root` that consists of the :term:`references
<reference>` fixed by a scanning function in a block of
:term:`formatted objects <formatted object>`.
``root_o`` points to a location that will hold the address of the
new root description.
``arena`` is the arena.
``rank`` is the :term:`rank` of references in the root.
``rm`` is the :term:`root mode`.
``fmt_scan`` is a scanning function. See :c:type:`mps_fmt_scan_t`.
``base`` is the address of the base of the block of formatted
objects.
``limit`` is the address just beyond the end of the block of
formatted objects.
Returns :c:macro:`MPS_RES_OK` if the root was registered
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
description could not be allocated, or another :term:`result code`
if there was another error.
The registered root destription persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. note::
This is like :c:func:`mps_root_create_table`, except you get
to supply your own scanning function, and like
:c:func:`mps_root_create`, except the scanning function takes
a different argument list, and the MPS knows the location of
the root.
.. c:function:: mps_res_t mps_root_create_reg(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_reg_scan_t reg_scan, void *p, size_t s)
Register a :term:`root` that consists of the :term:`references
<reference>` fixed in a :term:`thread's <thread>` stack by a
scanning function.
``root_o`` points to a location that will hold the address of the
new root description.
``arena`` is the arena.
``rank`` is the :term:`rank` of references in the root.
``rm`` is the :term:`root mode`.
``thr`` is the thread.
``reg_scan`` is a scanning function. See :c:type:`mps_reg_scan_t`.
``p`` and ``s`` are arguments that will be passed to ``reg_scan`` each
time it is called. This is intended to make it easy to pass, for
example, an array and its size as parameters.
Returns :c:macro:`MPS_RES_OK` if the root was registered
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
description could not be allocated, or another :term:`result code`
if there was another error.
The registered root destription persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. note::
It is not supported for :term:`Client programs <client
program>` to pass their own scanning functions to this
function. The built-in MPS function
:c:func:`mps_stack_scan_ambig` must be used.
.. c:function:: mps_res_t mps_root_create_table(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count)
Register a :term:`root` that consists of a vector of
:term:`references <reference>`.
``root_o`` points to a location that will hold the address of the
new root description.
``arena`` is the arena.
``rank`` is the :term:`rank` of references in the root.
``rm`` is the :term:`root mode`.
``base`` points to a vector of references.
``count`` is the number of references in the vector.
Returns :c:macro:`MPS_RES_OK` if the root was registered
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
description could not be allocated, or another :term:`result code`
if there was another error.
The registered root destription persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. c:function:: mps_res_t mps_root_create_table_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_word_t mask)
Register a :term:`root` that consists of a vector of :term:`tagged
references <tagged reference>`.
``root_o`` points to a location that will hold the address of the
new root description.
``arena`` is the arena.
``rank`` is the :term:`rank` of references in the root.
``rm`` is the :term:`root mode`.
``base`` points to a vector of tagged references.
``count`` is the number of tagged references in the vector.
``mask`` is a :term:`bitmask` whose set bits specify the location of
the :term:`tag`. References are assumed to have a tag of zero: any
value in the vector with a non-zero tag is ignored.
Returns :c:macro:`MPS_RES_OK` if the root was registered
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
description could not be allocated, or another :term:`result code`
if there was another error.
The registered root destription persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. c:function:: void mps_root_destroy(mps_root_t root)
Deregister a :term:`root` and destroy its description.
``root`` is the root.
.. c:type:: typedef mps_res_t (*mps_root_scan_t)(mps_ss_t ss, void *p, size_t s)
The type of root scanning functions for :c:func:`mps_root_create`.
``ss`` is the :term:`scan state`. It must be passed to
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END` to delimit a
sequence of fix operations, and to the functions
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2` when fixing a
:term:`reference`.
``p`` and ``s`` are the corresponding values that were passed to
:c:func:`mps_root_create`.
Returns a :term:`result code`. If a fix function returns a value
other than :c:macro:`MPS_RES_OK`, the scan method must return that
value, and may return without fixing any further references.
Generally, itis better if it returns as soon as possible. If the
scanning is completed successfully, the function should return
:c:macro:`MPS_RES_OK`.
.. c:type:: void (*mps_roots_stepper_t)(mps_addr_t *ref, mps_root_t root, void *p, size_t s)
The type of a :term:`root` :term:`stepper function`.
A function of this type can be passed to
:c:func:`mps_arena_roots_walk`, in which case it will be called
for each reference into the :term:`arena` from a root registered
with the arena. It receives four arguments:
``ref`` points to a reference in a root. The reference points to
something in the arena. If the root is :term:`exact <exact
reference>` then the reference points to the start of an allocated
block, but if the root is :term:`ambiguous <ambiguous reference>`
it might point to somewhere in the middle of an allocated block.
``root`` is the description of the root which contains ``ref``.
``p`` and ``s`` are the corresponding values that were passed to
:c:func:`mps_arena_roots_walk`.
.. c:type:: mps_root_t
The type of :term:`root` descriptions.
The :term:`arena` uses root descriptions to find :term:`references
<reference>` within the :term:`client program's <client program>`
roots.

View file

@ -1,6 +1,5 @@
.. _topic-scanning:
========
Scanning
========
@ -143,3 +142,238 @@ The macro returns :c:macro:`MPS_RES_OK` if it was successful, in which case the
return res;
}
Interface
---------
.. c:function:: mps_res_t mps_fix(mps_ss_t ss, mps_addr_t *ref_io)
Tell the MPS about a :term:`reference`, and possibly update it.
This function must only be called from within a :term:`scan
method`.
``ss`` is the :term:`scan state` that was passed to the scan method.
``ref_io`` points to the reference.
Returns :c:macro:`MPS_RES_OK` if successful: in this case the
reference may have been updated (see the topic
:ref:`topic-moving`), and the scan method must continue to scan
the :term:`block`. If it returns any other result, the scan method
must return that result as soon as possible, without fixing any
further references.
.. deprecated:: 1.110
Use :c:func:`MPS_SCAN_BEGIN`, :c:func:`MPS_FIX12`, and
:c:func:`MPS_SCAN_END` instead.
.. topics::
:ref:`topic-scanning` and :ref:`topic-moving`.
.. note::
If your reference is :term:`tagged <tagged reference>`, you
must remove the tag before calling :c:func:`mps_fix`, and
restore the tag to the (possibly updated) reference
afterwards. (There is an exception for references to objects
belonging to a format of variant auto_header: these references
must not subtract the header size.)
If you want to call this between :c:func:`MPS_SCAN_BEGIN` and
:c:func:`MPS_SCAN_END`, you must use :c:func:`MPS_FIX_CALL`
to ensure that the scan state is passed correctly.
.. c:function:: mps_bool_t MPS_FIX1(mps_ss_t ss, mps_addr_t ref)
Tell the MPS about a :term:`reference`. This macro must only be
used within a :term:`scan method`, between
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`.
``ss`` is the :term:`scan state` that was passed to the scan method.
``ref`` is the reference.
Returns a truth value (:c:type:`mps_bool_t`) indicating whether
the reference is likely to be interesting to the MPS. If it
returns false, the scan method must continue scanning the
:term:`block`. If it returns true, the scan method must invoke
:c:func:`MPS_FIX2`, to fix the reference.
.. note::
If your reference is :term:`tagged <tagged reference>`, you
must remove the tag before calling :c:func:`MPS_FIX1`.
In the common case where the scan method does not need to do
anything between :c:func:`MPS_FIX1` and :c:func:`MPS_FIX2`,
you can use the convenience macro :c:func:`MPS_FIX12`.
.. c:function:: MPS_FIX12(mps_ss_t ss, mps_addr_t *ref_io)
Tell the MPS about a :term:`reference`, and possibly update it.
This macro must only be used within a :term:`scan method`, between
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`.
``ss`` is the :term:`scan state` that was passed to the scan method.
``ref_io`` points to the reference.
Returns :c:macro:`MPS_RES_OK` if successful: in this case the
reference may have been updated (see the topic
:ref:`topic-moving`), and the scan method must continue to scan
the :term:`block`. If it returns any other result, the scan method
must return that result as soon as possible, without fixing any
further references.
.. note::
If your reference is :term:`tagged <tagged reference>`, you
must remove the tag before calling :c:func:`MPS_FIX2`, and
restore the tag to the (possibly updated) reference
afterwards. (There is an exception for references to objects
belonging to a format of variant auto_header: these references
must not subtract the header size.)
The macro :c:func:`MPS_FIX12` is a convenience for the common
case where :c:func:`MPS_FIX1` is immediately followed by
:c:func:`MPS_FIX2`.
.. c:function:: MPS_FIX2(mps_ss_t ss, mps_addr_t *ref_io)
Tell the MPS about a :term:`reference`, and possibly update it.
This macro must only be used within a :term:`scan method`,
between :c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`.
``ss`` is the :term:`scan state` that was passed to the scan method.
``ref_io`` points to the reference.
Returns :c:macro:`MPS_RES_OK` if successful: in this case the
reference may have been updated (see the topic
:ref:`topic-moving`), and the scan method must continue to scan
the :term:`block`. If it returns any other result, the scan method
must return that result as soon as possible, without fixing any
further references.
.. note::
If your reference is :term:`tagged <tagged reference>`, you
must remove the tag before calling :c:func:`MPS_FIX2`, and
restore the tag to the (possibly updated) reference
afterwards. (There is an exception for references to objects
belonging to a format of variant auto_header: these references
must not subtract the header size.)
In the common case where the scan method does not need to do
anything between :c:func:`MPS_FIX1` and :c:func:`MPS_FIX2`,
you can use the convenience macro :c:func:`MPS_FIX12`.
.. c:function:: MPS_FIX_CALL(ss, call)
Call a function from within a :term:`scan method`, between
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`, passing
the :term:`scan state` correctly.
``ss`` is the scan state that was passed to the scan method.
``call`` is an expression containing a function call where ``ss``
is one of the arguments.
Returns the result of evaluating the expression ``call``.
Between :c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`, the
scan state is in a special state, and must not be passed to a
function. If you really need to do so, for example because you
have a structure shared between two :term:`object formats <object
format>`, you must wrap the call with :c:func:`MPS_FIX_CALL` to
ensure that the scan state is passed correctly.
In example below, the scan method ``obj_scan`` fixes the object's
``left`` and ``right`` references, but delegates the scanning of
references inside the object's ``data`` member to the function
``data_scan``. In order to ensure that the scan state is passed
correctly to ``data_scan``, the call must be wrapped in
:c:func:`MPS_FIX_CALL`. ::
mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
{
Object *obj;
mps_res_t res;
MPS_SCAN_BEGIN(ss) {
for (obj = base; obj < limit; obj++) {
if (MPS_FIX12(ss, &obj->left) != MPS_RES_OK)
return res;
MPS_FIX_CALL(ss, res = data_scan(ss, &obj->data));
if (res != MPS_RES_OK)
return res;
if (MPS_FIX12(ss, &obj->right) != MPS_RES_OK)
return res;
}
} MPS_SCAN_END(ss);
return MPS_RES_OK;
}
.. c:function:: MPS_SCAN_BEGIN(mps_ss_t ss)
Within a :term:`scan method`, set up local information required
by :c:func:`MPS_FIX1`, :c:func:`MPS_FIX2` and
:c:func:`MPS_FIX12`. The local information persists until
:c:func:`MPS_SCAN_END`.
``ss`` is the :term:`scan state` that was passed to the scan method.
.. note::
Between :c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`,
the scan state is in a special state, and must not be passed
to a function. If you really need to do so, for example
because you have an embedded structure shared between two scan
methods, you must wrap the call with :c:func:`MPS_FIX_CALL` to
ensure that the scan state is passed correctly.
.. c:function:: MPS_SCAN_END(mps_ss_t ss)
Within a :term:`scan method`, terminate a block started by
:c:func:`MPS_SCAN_BEGIN`.
``ss`` is the :term:`scan state` that was passed to the scan
method.
.. note::
:c:func:`MPS_SCAN_END` ensures that the scan is completed, so
successful termination of a scan must invoke it. However, in
case of an error it is allowed to return from the scan
method without invoking :c:func:`MPS_SCAN_END`.
Between :c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END`, the
scan state is in a special state, and must not be passed to a
function. If you really need to do so, for example because you
have an embedded structure shared between two scan methods, you
must wrap the call with :c:func:`MPS_FIX_CALL` to ensure that the
scan state is passed correctly.
.. c:type:: mps_ss_t
The type of :term:`scan states <scan state>`.
A scan state represents the state of the current :term:`scan`. The
MPS passes a scan state to the :term:`scan method` of an
:term:`object format` when it needs to :term:`scan` for
:term:`references <reference>` within a region of memory. The
scan method must pass the scan state to :c:func:`MPS_SCAN_BEGIN`
and :c:func:`MPS_SCAN_END` to delimit a sequence of fix
operations, and to the functions :c:func:`MPS_FIX1` and
:c:func:`MPS_FIX2` when fixing a :term:`reference`.

View file

@ -1,6 +1,5 @@
.. _topic-telemetry:
=========
Telemetry
=========
@ -9,3 +8,110 @@ Typical uses of telemetry labels include:
- Label pools with a human-meaningful name;
- Label allocated objects with their type or class.
Interface
---------
.. c:function:: mps_word_t mps_telemetry_control(mps_word_t reset_mask, mps_word_t flip_mask)
Update and return the :term:`telemetry filter`.
``reset_mask`` is a :term:`bitmask` indicating the bits in the
telemetry filter that should be reset.
``flip_mask`` is a bitmask indicating the bits in the telemetry
filter whose value should be flipped after the resetting.
Returns the previous value of the telemetry filter, prior to the
reset and the flip.
The parameters ``reset_mask`` and ``flip_mask`` allow the
specification of any binary operation on the filter control. For
typical operations, the parameters should be set as follows:
============ ============== =============
Operation ``reset_mask`` ``flip_mask``
============ ============== =============
``set(M)`` ``M`` ``M``
------------ -------------- -------------
``reset(M)`` ``M`` ``0``
------------ -------------- -------------
``flip(M)`` ``0`` ``M``
------------ -------------- -------------
``read()`` ``0`` ``0``
============ ============== =============
The significance of the bits is liable to change, but the current
meanings (zero being the least significant bit) are:
0. per space or :term:`arena`;
1. per :term:`pool`;
2. per :term:`trace` or scan;
3. per :term:`page` (segment);
4. per :term:`reference` or :term:`fix`;
5. per allocation, :term:`block`, or :term:`object`;
6. "user" events: see :c:func:`mps_telemetry_intern`.
.. c:function:: void mps_telemetry_flush(void)
Flush the internal event buffers into the :term:`telemetry stream`.
This function also calls :c:func:`mps_io_flush` on the event
stream itself. This ensures that even the latest events are now
properly recorded, should the :term:`client program` terminate
(uncontrollably as a result of a bug, for example) or some
interactive tool require access to the telemetry stream. You could
even try calling this from a debugger after a problem.
.. c:function:: mps_word_t mps_telemetry_intern(char *label)
Registers a string with the MPS, and receives a :term:`telemetry
label`, suitable for passing to :c:func:`mps_telemetry_label`.
``label`` is a NUL-terminated string way. Its length should not
exceed 256 characters, including the terminating NUL.
Returns a telemetry label: a unique identifier that may be used to
represent the string in future.
The intention of this function is to provide an identifier that
can be used to concisely represent a string for the purposes of
:c:func:`mps_telemetry_label`.
.. note::
The appropriate setting must be turned on in the
:term:`telemetry filter` (via :c:func:`mps_telemetry_control`)
before this function is invoked; the associated event is of
the "user" kind.
.. c:function:: void mps_telemetry_label(mps_addr_t addr, mps_word_t label)
Associate a telemetry label returned from
:c:func:`mps_telemetry_intern` with an address.
``addr`` is an address.
``label`` is a telemetry label returned from
:c:func:`mps_telemetry_intern`.
The label will be associated with the address when it appears in
the :term:`telemetry stream`.
.. note::
The "user" kind must be set in the :term:`telemetry filter`
via :c:func:`mps_telemetry_control`.

View file

@ -4,4 +4,121 @@ Threads
=======
Interface
---------
.. c:function:: mps_reg_scan_t mps_stack_scan_ambig
A root scanning function for :term:`ambiguous <ambiguous
reference>` scanning of :term:`threads <thread>`, suitable for
passing to :c:func:`mps_root_create_reg`.
It scans all integer registers and everything on the stack of the
thread given, and can therefore only be used with :term:`ambiguous
roots <ambiguous root>`. It only scans locations that are at, or
higher on the stack (that is, more recently added), the stack
bottom that was passed to :c:func:`mps_thread_reg`. References
are assumed to be represented as machine words, and are required
to be 4-byte-aligned; unaligned values are ignored.
.. seealso::
:ref:`topic-platform`, :ref:`topic-root`.
.. note::
The MPS provides this function because it's hard to write: it
depends on the operating system, the architecture, and in some
cases the compiler.
.. c:function:: mps_res_t mps_thread_reg(mps_thr_t *thr_o, mps_arena_t arena)
Register the current :term:`thread` with an :term:`arena`.
``thr_o`` points to a location that will hold the address of the
registered thread description, if successful.
``arena`` is the arena.
Returns :c:macro:`MPS_RES_OK` if successful, or another
:term:`result code` if not.
A thread must be registered with an arena if it ever uses a
pointer to a location in an :term:`automatically managed
<automatic memory management>` :term:`pool` belonging to that
arena.
.. note::
It is recommended that all threads be registered with all
arena.
.. c:function:: void mps_thread_dereg(mps_thr_t thr)
Deregister a :term:`thread <thread>`.
``thr`` is the description of the thread.
After calling this function, the thread whose registration with an
:term:`arena` was recorded in ``thr`` must not use a pointer to a
location in an :term:`automatically managed <automatic memory
management>` :term:`pool` belonging to that arena.
.. note::
It is recommended that threads be deregistered only when they
are just about to exit.
.. c:type:: mps_thr_t
The type of registered :term:`thread` descriptions.
In a multi-threaded environment where :term:`incremental garbage
collection` is used, threads must be registered with the MPS by
calling :c:func:`mps_thread_reg` so that the MPS can suspend them
as necessary in order to have exclusive access to their state.
Even in a single-threaded environment it may be necessary to
register a thread with the MPS so that its stack can be registered
as a :term:`root` by calling :c:func:`mps_root_create_reg`.
.. c:function:: void mps_tramp(void **r_o, mps_tramp_t f, void *p, size_t s)
Call a function via the MPS trampoline.
``r_o`` points to a location that will store the result of calling
``f``.
``f`` is the function to call.
``p`` and ``s`` are arguments that will be passed to ``f`` each
time it is called. This is intended to make it easy to pass, for
example, an array and its size as parameters.
The MPS relies on :term:`barriers <barrier (1)>` to protect memory
that is in an inconsistent state. On some operating systems,
barrier hits generate exceptions that have to be caught by a
handler that is on the stack. On these operating systems, any code
that uses memory managed by the MPS must be called from inside
such an exception handler, that is, inside a call to
:c:func:`mps_tramp`.
If you have multiple threads that run code that uses memory
managed by the MPS, each thread must execute such code inside a
call to :c:func:`mps_tramp`.
.. c:type:: void *(*mps_tramp_t)(void *p, size_t s)
The type of a function called by :c:func:`mps_tramp`.
``p`` and ``s`` are the corresponding arguments that were passed
to :c:func:`mps_tramp`.