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:
parent
e4c420797a
commit
99cccfa252
20 changed files with 3619 additions and 19 deletions
|
|
@ -10,7 +10,6 @@ Memory Pool System
|
|||
guide/index
|
||||
topic/index
|
||||
pool/index
|
||||
reference/index
|
||||
lang
|
||||
glossary/index
|
||||
bib
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>`.
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
||||
|
|
|
|||
90
mps/manual/source/topic/frame.rst
Normal file
90
mps/manual/source/topic/frame.rst
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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>`.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
104
mps/manual/source/topic/pool.rst
Normal file
104
mps/manual/source/topic/pool.rst
Normal 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`.
|
||||
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue