mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-21 12:27:33 +00:00
Misc minor edits.
Copied from Perforce Change: 180118 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
609b815f9e
commit
86d0cd8775
9 changed files with 123 additions and 122 deletions
|
|
@ -40,7 +40,7 @@ General debugging advice
|
|||
space layout randomization`_: if you perform computation based on
|
||||
the addresses of objects, for example, hashing objects by their
|
||||
address, then ASLR will cause your hash tables to be laid out
|
||||
differently on each run, which may effect the order of memory
|
||||
differently on each run, which may affect the order of memory
|
||||
management operations.)
|
||||
|
||||
.. _address space layout randomization: http://en.wikipedia.org/wiki/Address_space_layout_randomization
|
||||
|
|
@ -50,7 +50,7 @@ General debugging advice
|
|||
are discovered. So if you have a bug that's hard to reproduce, or
|
||||
which manifests itself in different ways on different runs, you may
|
||||
be able to provoke it more reliably, or get a more consistent
|
||||
result by having a mode for testing in which you run frequent
|
||||
result, by having a mode for testing in which you run frequent
|
||||
collections (by calling :c:func:`mps_arena_collect` followed by
|
||||
:c:func:`mps_arena_release`), perhaps as frequently as every
|
||||
allocation.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Memory Pool System
|
|||
guide/index
|
||||
topic/index
|
||||
pool/index
|
||||
topic/porting
|
||||
topic/internals
|
||||
|
||||
|
||||
Appendices
|
||||
|
|
@ -27,9 +27,4 @@ Appendices
|
|||
contact
|
||||
todo
|
||||
|
||||
|
||||
Indices and tables
|
||||
##################
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
|
|
|||
|
|
@ -31,14 +31,34 @@ The AMC pool class exploits assumptions about object lifetimes and inter-connect
|
|||
If an allocation point is created in an AMC pool, the call to :c:func:`mps_ap_create` will take no additional parameters.
|
||||
|
||||
|
||||
--------------------
|
||||
AMC symbol reference
|
||||
--------------------
|
||||
AMC interface
|
||||
-------------
|
||||
|
||||
::
|
||||
|
||||
#include "mpscamc.h"
|
||||
|
||||
.. c:function:: mps_class_t mps_class_amc(void)
|
||||
|
||||
Return the :term:`pool class` for an AMC (Automatic
|
||||
Mostly-Copying) :term:`pool`.
|
||||
|
||||
When creating an AMC pool, :c:func:`mps_pool_create` takes two
|
||||
extra arguments::
|
||||
|
||||
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
|
||||
mps_class_t mps_class_amc(),
|
||||
mps_fmt_t fmt,
|
||||
mps_chain_t chain)
|
||||
|
||||
``fmt`` specifies the :term:`object format` for the objects
|
||||
allocated in the pool.
|
||||
|
||||
``chain`` specifies the :term:`generation chain` for the pool.
|
||||
|
||||
|
||||
AMC introspection
|
||||
-----------------
|
||||
|
||||
.. c:function:: void mps_amc_apply(mps_pool_t pool, mps_amc_apply_stepper_t f, void *p, size_t s)
|
||||
|
||||
|
|
@ -78,7 +98,7 @@ AMC symbol reference
|
|||
Walking the heap is "dodgy".
|
||||
|
||||
|
||||
.. c:type:: void (*mps_amc_apply_stepper_t)(mps_addr_t object, void *p, size_t s);
|
||||
.. c:type:: void (*mps_amc_apply_stepper_t)(mps_addr_t object, void *p, size_t s)
|
||||
|
||||
The type of a :term:`stepper function` for :term:`formatted
|
||||
objects <formatted object>` in an AMC pool.
|
||||
|
|
@ -92,20 +112,3 @@ AMC symbol reference
|
|||
automatically managed memory except within ``object``.
|
||||
|
||||
|
||||
.. c:function:: mps_class_t mps_class_amc(void)
|
||||
|
||||
Return the :term:`pool class` for an AMC (Automatic
|
||||
Mostly-Copying) :term:`pool`.
|
||||
|
||||
When creating an AMC pool, :c:func:`mps_pool_create` takes two
|
||||
extra arguments::
|
||||
|
||||
mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena,
|
||||
mps_class_t mps_class_amc(),
|
||||
mps_fmt_t fmt,
|
||||
mps_chain_t chain)
|
||||
|
||||
``fmt`` specifies the :term:`object format` for the objects
|
||||
allocated in the pool.
|
||||
|
||||
``chain`` specifies the :term:`generation chain` for the pool.
|
||||
|
|
|
|||
|
|
@ -19,11 +19,8 @@ that pool. You create a generation chain by preparing an array of
|
|||
kilobytes) and *predicted mortality* (between 0 and 1) of each
|
||||
generation, and passing them to :c:func:`mps_chain_create`.
|
||||
|
||||
The term *capacity* is misleading: it's actually a threshold on the
|
||||
*new size* of a generation. The :dfn:`new size` is the size of the
|
||||
newly allocated (in generation 0) or newly promoted (in other
|
||||
generations) blocks. When the new size exceeds the capacity, the MPS
|
||||
will be prepared to start collecting the generation. See
|
||||
When the size of the generation exceeds the capacity, the MPS will be
|
||||
prepared to start collecting the generation. See
|
||||
:ref:`topic-collection-schedule` below.
|
||||
|
||||
For example::
|
||||
|
|
@ -31,7 +28,6 @@ For example::
|
|||
mps_gen_param_s gen_params[] = {
|
||||
{ 1024, 0.8 },
|
||||
{ 2048, 0.4 },
|
||||
{ 4096, 0.2 },
|
||||
};
|
||||
|
||||
mps_chain_t chain;
|
||||
|
|
@ -107,8 +103,8 @@ Scheduling of collections
|
|||
-------------------------
|
||||
|
||||
The first generation in a pool's chain is the :term:`nursery
|
||||
generation`. When the nursery's "new size" exceeds its capacity, the
|
||||
MPS considers collecting the pool. (Whether it actually does so or not
|
||||
generation`. When the nursery's size exceeds its capacity, the MPS
|
||||
considers collecting the pool. (Whether it actually does so or not
|
||||
depends on which other collections on other pools are in progress.)
|
||||
|
||||
.. note::
|
||||
|
|
@ -118,31 +114,31 @@ depends on which other collections on other pools are in progress.)
|
|||
<topic-pattern-ramp>`.
|
||||
|
||||
If the MPS decides to collect a pool at all, all generations are
|
||||
collected below the first generation whose "new size" is less than its
|
||||
collected below the first generation whose size is less than its
|
||||
capacity.
|
||||
|
||||
For example, suppose that we have a pool with the following generation
|
||||
structure:
|
||||
|
||||
+------------+--------------+----------------------+----------------+
|
||||
| | Current size | Chain parameters | Predicted size |
|
||||
| +------+-------+----------+-----------+--------+-------+
|
||||
| Generation | New | Total | Capacity | Mortality | New | Total |
|
||||
+============+======+=======+==========+===========+========+=======+
|
||||
| 0 | 110 | 110 | 100 | 0.8 | 0 | 0 |
|
||||
+------------+------+-------+----------+-----------+--------+-------+
|
||||
| 1 | 210 | 210 | 200 | 0.4 | 22 | 22 |
|
||||
+------------+------+-------+----------+-----------+--------+-------+
|
||||
| 2 | 260 | 640 | 400 | 0.2 | 386 | 766 |
|
||||
+------------+------+-------+----------+-----------+--------+-------+
|
||||
| Generation | Current size | Capacity | Mortality | Predicted size |
|
||||
+============+==============+==========+===========+================+
|
||||
| 0 | 110 | 100 | 0.8 | 0 |
|
||||
+------------+--------------+----------+-----------+----------------+
|
||||
| 1 | 210 | 200 | 0.4 | 22 |
|
||||
+------------+--------------+----------+-----------+----------------+
|
||||
| 2 | 200 | 300 | 0.2 | 326 |
|
||||
+------------+--------------+----------+-----------+----------------+
|
||||
|
||||
The nursery and generation 1 both have "new size" that exceeds their
|
||||
capacity, so these generations will be collection. Generation 2 will
|
||||
not be collected (even though its total size exceeds its capacity).
|
||||
The last two columns give the predicted sizes of each generation after
|
||||
the collection: the survivors from the nursery will be promoted to
|
||||
generation 1 and the survivors from generation 1 will be promoted to
|
||||
generation 2.
|
||||
The nursery and generation 1 both have size that exceeds their
|
||||
capacity, so these generations will be collected. Generation 2 will
|
||||
not be collected this time. The last two columns give the predicted
|
||||
sizes of each generation after the collection: the survivors from the
|
||||
nursery will be promoted to generation 1 and the survivors from
|
||||
generation 1 will be promoted to generation 2.
|
||||
|
||||
When the last generation in the chain is collected, the survivors are
|
||||
promoted into an :term:`arena`\-wide "top" generation.
|
||||
|
||||
The predicted mortality is used to estimate how long the collection
|
||||
will take, and this is used in turn to decide how much work the
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ either behaviour.
|
|||
Example: ports in Scheme
|
||||
------------------------
|
||||
|
||||
In Scheme, an open file is represent by a *port*. In the toy Scheme
|
||||
In Scheme, an open file is represented by a *port*. In the toy Scheme
|
||||
example, a port is a wrapper around a Standard C file handle::
|
||||
|
||||
typedef struct port_s {
|
||||
|
|
@ -114,65 +114,71 @@ example, a port is a wrapper around a Standard C file handle::
|
|||
} port_s;
|
||||
|
||||
The Scheme procedure ``open-input-file`` takes a filename and returns
|
||||
a port::
|
||||
a port:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 21
|
||||
|
||||
/* (open-input-file filename)
|
||||
* Opens filename for input, with empty file options, and returns the
|
||||
* obtained port.
|
||||
* R6RS Standard Library 8.3.
|
||||
* See R4RS 6.10.1
|
||||
*/
|
||||
static obj_t entry_open_input_file(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
|
||||
{
|
||||
obj_t filename;
|
||||
FILE *stream;
|
||||
obj_t port;
|
||||
mps_addr_t port_ref;
|
||||
eval_args(operator->operator.name, env, op_env, operands, 1, &filename);
|
||||
unless(TYPE(filename) == TYPE_STRING)
|
||||
error("%s: argument must be a string", operator->operator.name);
|
||||
stream = fopen(filename->string.string, "r");
|
||||
if(stream == NULL)
|
||||
error("%s: cannot open input file", operator->operator.name);
|
||||
port = make_port(filename, stream);
|
||||
obj_t filename;
|
||||
FILE *stream;
|
||||
obj_t port;
|
||||
mps_addr_t port_ref;
|
||||
eval_args(operator->operator.name, env, op_env, operands, 1, &filename);
|
||||
unless(TYPE(filename) == TYPE_STRING)
|
||||
error("%s: argument must be a string", operator->operator.name);
|
||||
stream = fopen(filename->string.string, "r");
|
||||
if(stream == NULL)
|
||||
error("%s: cannot open input file", operator->operator.name);
|
||||
port = make_port(filename, stream);
|
||||
|
||||
port_ref = port;
|
||||
mps_finalize(arena, &port_ref);
|
||||
port_ref = port;
|
||||
mps_finalize(arena, &port_ref);
|
||||
|
||||
return port;
|
||||
return port;
|
||||
}
|
||||
|
||||
Each time around the read–eval–print loop, the interpreter polls the
|
||||
message queue for finalization messages, and when it finds one it
|
||||
closes the port's underlying file handle::
|
||||
closes the port's underlying file handle:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 9, 12
|
||||
|
||||
mps_message_type_t type;
|
||||
|
||||
while (mps_message_queue_type(&type, arena)) {
|
||||
mps_message_t message;
|
||||
mps_bool_t b;
|
||||
b = mps_message_get(&message, arena, type);
|
||||
assert(b); /* we just checked there was one */
|
||||
mps_message_t message;
|
||||
mps_bool_t b;
|
||||
b = mps_message_get(&message, arena, type);
|
||||
assert(b); /* we just checked there was one */
|
||||
|
||||
if (type == mps_message_type_finalization()) {
|
||||
mps_addr_t port_ref;
|
||||
obj_t port;
|
||||
mps_message_finalization_ref(&port_ref, arena, message);
|
||||
port = port_ref;
|
||||
assert(TYPE(port) == TYPE_PORT);
|
||||
printf("Port to file \"%s\" is dying. Closing file.\n",
|
||||
port->port.name->string.string);
|
||||
(void)fclose(port->port.stream);
|
||||
} else {
|
||||
/* ... handle other message types ... */
|
||||
}
|
||||
if (type == mps_message_type_finalization()) {
|
||||
mps_addr_t port_ref;
|
||||
obj_t port;
|
||||
mps_message_finalization_ref(&port_ref, arena, message);
|
||||
port = port_ref;
|
||||
assert(TYPE(port) == TYPE_PORT);
|
||||
printf("Port to file \"%s\" is dying. Closing file.\n",
|
||||
port->port.name->string.string);
|
||||
(void)fclose(port->port.stream);
|
||||
} else {
|
||||
/* ... handle other message types ... */
|
||||
}
|
||||
|
||||
mps_message_discard(arena, message);
|
||||
mps_message_discard(arena, message);
|
||||
}
|
||||
|
||||
Here's an example session showing finalization taking place:
|
||||
|
||||
.. code-block:: none
|
||||
:emphasize-lines: 14
|
||||
:emphasize-lines: 8
|
||||
|
||||
MPS Toy Scheme Example
|
||||
9960, 0> (open-input-file "scheme.c")
|
||||
|
|
@ -253,26 +259,6 @@ Cautions
|
|||
Finalization 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`.
|
||||
|
|
@ -298,6 +284,26 @@ Finalization interface
|
|||
that the C call stack be a :term:`root`.
|
||||
|
||||
|
||||
.. 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`.
|
||||
|
||||
|
||||
Finalization messages
|
||||
---------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ Reference
|
|||
location
|
||||
cache
|
||||
pattern
|
||||
frame
|
||||
debugging
|
||||
telemetry
|
||||
frame
|
||||
low
|
||||
critical
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
.. _internals:
|
||||
|
||||
Porting
|
||||
*******
|
||||
Internals
|
||||
*********
|
||||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
|
||||
plinth
|
||||
platform
|
||||
critical
|
||||
|
|
@ -126,9 +126,6 @@ Here's how this looks in operation:
|
|||
the latest Emacs pretest. All I had done was to remove the
|
||||
"Garbage collecting" message which people perceive as
|
||||
slowing Emacs down and tell them that it had been sped up.
|
||||
It is, somehow, permissible for a program to take a lot of
|
||||
time doing any other task than administrative duties like
|
||||
garbage collection.
|
||||
|
||||
|
||||
Message types
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. highlight:: none
|
||||
|
||||
.. _topic-telemetry:
|
||||
|
||||
Telemetry
|
||||
|
|
@ -84,10 +86,12 @@ program::
|
|||
The ``sort`` is useful because the events are not necessarily written
|
||||
to the telemetry file in time order, but each event starts with a
|
||||
timestamp so sorting makes a time series. The decoded events look like
|
||||
this, with the timestamp in the first column (in units of
|
||||
:c:type:`mps_clock_t`, typically 1 µs), the event type in the second
|
||||
column, and then addresses or other data related to the event in the
|
||||
remaining columns. All numbers are given in hexadecimal. ::
|
||||
this, with the timestamp in the first column, the event type in the
|
||||
second column, and then addresses or other data related to the event
|
||||
in the remaining columns. The timestamp comes from the high-resolution
|
||||
processor timer (on IA-32 and x86-64, this is the `Time Stamp Counter
|
||||
<http://en.wikipedia.org/wiki/Time_Stamp_Counter>`_). All numbers are
|
||||
given in hexadecimal. ::
|
||||
|
||||
000AE03973336E3C 2B 1003FC000 1003FD000 1003FE000
|
||||
000AE0397333BC6D 2D 1003FC000 1003FD000 1003FE000
|
||||
|
|
|
|||
Loading…
Reference in a new issue