1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 16:51:46 -07:00

Complete the conversion of the mps reference manual to restructured text, creating topic and pool pages as needed.

Copied from Perforce
 Change: 179839
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-10-11 23:46:31 +01:00
parent 1231d6982f
commit 108e18ad35
18 changed files with 550 additions and 15 deletions

View file

@ -35,6 +35,10 @@ Glossary
??
ambiguous
??
arena
??
@ -43,10 +47,22 @@ Glossary
??
assert
??
asynchronous
??
automatic
??
bitmask
??
black
??
@ -83,6 +99,10 @@ Glossary
??
condemned
??
constant root
??
@ -99,6 +119,10 @@ Glossary
??
debugging pool
??
dead
??
@ -107,6 +131,14 @@ Glossary
??
exact
??
fencepost
??
finalization
??
@ -115,6 +147,10 @@ Glossary
??
fix
??
format method
??
@ -143,6 +179,10 @@ Glossary
??
free list
??
garbage collection
??
@ -155,6 +195,14 @@ Glossary
??
incremental
??
in/out parameter
??
is-forwarded method
??
@ -179,6 +227,14 @@ Glossary
??
message queue
??
message type
??
moving
??
@ -199,6 +255,10 @@ Glossary
??
out parameter
??
padding method
??
@ -314,10 +374,38 @@ Glossary
??
stepper function
??
table root
??
tag
??
tagged value
??
telemetry filter
??
telemetry label
??
telemetry stream
??
thread
??
trace
??
@ -334,6 +422,10 @@ Glossary
??
weak
??
white
??

View file

@ -7,6 +7,8 @@ Pool reference
pool-amc
pool-amcz
pool-ams
pool-lo
pool-mvff
pool-mvt
pool-snc

View file

@ -1,8 +1,8 @@
.. _pool-amc:
=============================
Automatic Mostly-Copying pool
=============================
===================================
AMC (Automatic Mostly-Copying) pool
===================================
An AMC pool is both scannable and collectable. Objects may contain exact references to other objects that will preserve such other objects. Objects may be reclaimed if they are not reachable from a root. Objects may move during collection, unless reachable via a (direct) ambiguous reference. Objects in an AMC pool may be registered for finalization. Exact (that is, non-ambiguous)references into an object in an AMC pool must be to the start of the object.

View file

@ -1,5 +1,5 @@
.. _pool-amcz:
=========
AMCZ pool
=========
=========================================
AMCZ (Automatic Mostly-Copying Z???) pool
=========================================

View file

@ -0,0 +1,6 @@
.. _pool-ams:
===================================
AMS (Automatic Mark and Sweep) pool
===================================

View file

@ -0,0 +1,5 @@
.. _pool-lo:
===================
LO (Leaf Only) pool
===================

View file

@ -1,8 +1,8 @@
.. _pool-mvff:
===================================
Manual Variable-size First Fit pool
===================================
==========================================
MVFF (Manual Variable-size First Fit) pool
==========================================
Buffered allocation (:c:func:`mps_reserve` and :c:func:`mps_commit`) is also supported, but in that case, the policy is rather different: buffers are filled worst-fit, and allocation is always upwards from the base. The arenaHigh parameter regulates whether new segments are acquired at high or low addresses;the slotHigh and firstFit parameters do not affect buffered allocation. Buffered and unbuffered allocation can be used at the same time, but in that case, the first allocation point must be created before any call to :c:func:`mps_alloc`.

View file

@ -1,8 +1,8 @@
.. _pool-mvt:
======================================
Manual Variable-size Temporal-fit pool
======================================
============================================
MVT (Manual Variable-size Temporal-fit) pool
============================================
The MVT pool class manually manages variable-sized, unformatted objects. The MVT pool uses an allocation policy termed "temporal fit". Temporal fit attempts to place consecutive allocations next to each other. It relies on delaying reuse as long as possible to permit freed blocks to coalesce, thus maximizing the number of consecutive allocations that can be co-located. Temporal fit permits a very fast allocator and a deallocator competitive in speed with all other known policies.

View file

@ -1,8 +1,8 @@
.. _pool-snc:
===================
Stack No Check pool
===================
=========================
SNC (Stack No Check) pool
=========================
An SNC pool is scannable, in that objects may contain references to objects in other pools that will keep those objects alive (depending on rank). In this sense, an SNC pool is a de-facto root.

View file

@ -108,3 +108,115 @@ What does this mean? (from mps_sac_alloc):
MPS_SAC_FREE_FAST(sac, p, FooSIZE);
</pre>
<h4>Example</h4>
<pre>
mps_sac_t sac;
mps_sac_class_s classes[3] = { {8, 38, 1}, {136, 19, 3}, {512, 4, 1} };
res = mps_sac_create(&amp;sac, pool, 3, classes);
if (res != MPS_RES_OK) {
printf("Failed to create the allocation cache!");
exit(1);
}
</pre>
<h4>Example</h4>
<pre>
mps_sac_t sac;
mps_sac_class_s classes[3] = { {8, 38, 1}, {136, 19, 3}, {512, 4, 1} };
res = mps_sac_create(&amp;sac, pool, 3, classes);
if (res != MPS_RES_OK) {
printf("Failed to create the allocation cache!");
exit(1);
}
</pre>
.. note::
Some pools will work more efficiently with segregated
allocation caches than others. [WHICH?] In the future, the MPS might
offer pools specially optimized for particular types of cache. [WHEN?]
Segregated allocation caches work poorly with debugging pool
classes: the debugging checks only happen when blocks are
moved between the cache and the pool. This will be fixed [WHEN?], but
the speed of allocation with a debug class will always be
similar to :c:func:`mps_alloc`, rather than cached speed.
<h4>Example</h4>
<pre>
res = mps_sac_create(&amp;sac, pool, 3, classes);
if (res != MPS_RES_OK) {
printf("Failed to create the allocation cache!");
exit(1);
}
/* Use sac. */
mps_sac_destroy(sac);
mps_pool_destroy(pool);
</pre>
<h4>Example</h4>
<pre>
mps_sac_t sac_small, sac_large;
res = mps_sac_create(&amp;sac_small, pool, 3, small_classes);
if (res != MPS_RES_OK) {
printf("Failed to create the small allocation cache!");
exit(1);
}
res = mps_sac_create(&amp;sac_large, pool, 3, large_classes);
if (res != MPS_RES_OK) {
printf("Failed to create the large allocation cache!");
exit(1);
}
/* Use sac_small. */
mps_sac_flush(sac_small);
/* Use sac_large. */
mps_sac_flush(sac_large);
/* Use sac_small. */
</pre>
<h4>Example</h4>
<pre>
mps_sac_t sac;
mps_sac_class_s classes[3] = { {8, 38, 1}, {136, 19, 3}, {512, 4, 1} };
res = mps_sac_create(&amp;sac, pool, 3, classes);
if (res != MPS_RES_OK) {
printf("Failed to create the allocation cache!");
exit(1);
}
</pre>

View file

@ -0,0 +1,8 @@
.. _topic-collection:
==================
Garbage collection
==================

View file

@ -0,0 +1,18 @@
.. _topic-debugging:
===============
Debugging pools
===============
<h4>Example</h4>
<pre>
static mps_pool_debug_option_s debugOptions = { (void *)"postpost", 8 };
if(mps_pool_create(&amp;pool, arena, mps_class_ams_debug(),
&amp;debugOptions, 8192, 135, 8)
!= MPS_RES_OK) {
printf("Error creating pool!"); exit(2);
}
</pre>

View file

@ -34,3 +34,21 @@ Error handing
}
</pre>
<h4>Example</h4>
<pre>
mps_addr_t p;
mps_res_t res;
res = mps_alloc(&amp;p, pool, sizeof(struct spong));
if(res != MPS_RES_OK) {
handle_memory_error(res);
abort();
}
</pre>
For more examples, s ee doc.mps.ref-man.if-conv.

View file

@ -19,3 +19,21 @@ Note that there is no guarantee that finalization will be prompt.
Note that there will be no attempt to finalize objects in the context of :c:func:`mps_arena_destroy` or :c:func:`mps_pool_destroy`. :c:func:`mps_pool_destroy` should therefore not be invoked on pools containing objects registered for finalization.
Not all pool classes support finalization of objects. In general only pools that manage objects whose liveness is determined by garbage collection will support finalization of objects. For more information, see the Pool Class Catalog.
<h4>Example</h4>
<pre>
{
mps_message_type_t type;
if(mps_message_queue_type(&amp;type, arena)) {
if(type == mps_message_type_finalization()) {
process_finalization_message_from_queue();
} else {
unknown_message_type();
}
}
}
</pre>

View file

@ -7,6 +7,7 @@ Topic reference
arena
allocation
collection
error
format
scanning
@ -20,3 +21,5 @@ Topic reference
platform
telemetry
message
debugging

View file

@ -18,3 +18,33 @@ Messages
printf("Collection started at %ul.\n", (unsigned long)posted_at);
}
</pre>
<h4>Example</h4>
<pre>
{
mps_message_t message;
if(mps_message_get(&amp;message, arena, mps_message_type_gc())) {
size_t live, condemned, not_condemned;
live = mps_message_gc_live_size(arena, message);
condemned = mps_message_gc_condemned_size(arena, message);
not_condemned = mps_message_gc_not_condemned_size(arena,message);
mps_message_discard(arena, message);
process_collection_stats(live, condemned, not_condemned);
}
}
</pre>
<pre>
{
mps_message_t message;
if(mps_message_get(&amp;message, arena, mps_message_type_gc_start())) {
printf("Collection started; reason: %s\n",
mps_message_gc_start_why(arena, message));
}
}
</pre>

View file

@ -25,3 +25,220 @@ unprotect the relevant pages.</p>
<p>This feature is far too technical for most of our clients: we should think about producing some guidelines on how to use it. - pekka 1998-01-27</p>
<p>There may be problems if the client wants the OS to access the root. Lots of OSes can't cope with writing to protected pages. So we'll need to document that caveat too. drj 1998-05-20</p>
<h4>Example</h4>
<pre>
static mps_root_t mmRoot;
int main(void)
{
mps_res_t res;
/* ... */
res = mps_root_create(&amp;mmRoot, arena, MPS_RANK_EXACT, (mps_rm_t)0,
&amp;rootScanner, NULL, 0);
/* see doc of mps_root_scan_t for definition of rootScanner */
if(res != MPS_RES_OK)
exit(1);
/* ... */
}
</pre>
.. note::
Unless the rank of the root is not :c:macro:`MPS_RANK_AMBIG`,
the contents of the root have to be valid whenever a
:term:`garbage collection` happens. That is, all the
references fixed by the root scanning function have to be
references to actual objects or null pointers. If you're using
:term:`asynchronous` garbage collection, this could be as soon
as the root is registered, so the root has to be valid when it
is registered. As with an ordinary :term:`scan method`, a root
scanning function is allowed to fix references which point to
memory not managed by the MPS. These references will be
ignored.
<h4>Example</h4>
<pre>
static mps_root_t mmRoot;
SegmentDescriptor DataSegment;
int main(void)
{
mps_res_t res;
/* ... */
res = mps_root_create_fmt(&amp;mmRoot, arena, MPS_RANK_EXACT, (mps_rm_t)0,
&amp;scan_objs,
(mps_addr_t)DataSegment.base,
(mps_addr_t) (DataSegment.base + SegmentLength) );
/* see doc of mps_fmt_scan_t for definition of scan_objs */
if(res != MPS_RES_OK)
exit( EXIT_FAILURE );
/* ... */
}
</pre>
<h4>Example</h4>
<pre>
typedef struct {
mps_root_t mmRoot;
mps_thr_t thread;
/* ... */
} ThreadLocals;
void InitThread(ThreadLocals *thr)
{
/* This is a hack to find the bottom of the stack. */
void *stackBottom=&amp;stackBottom;
mps_thread_reg(&amp;thr-&gt;thread, arena);
mps_root_create_reg(&amp;thr-&gt;mmRoot, arena, MPS_RANK_AMBIG, (mps_rm_t) 0,
thr-&gt;thread, mps_stack_scan_ambig, stackBottom, 0);
/* ... */
}
</pre>
<h4>Example</h4>
<pre>
static mps_root_t mmRoot;
Object *Objects[rootCOUNT];
int main(void)
{
mps_res_t res;
/* ... */
res = mps_root_create_table(&amp;mmRoot, arena, MPS_RANK_EXACT, (mps_rm_t)0,
(mps_addr_t) &amp;Objects, rootCOUNT );
if(res != MPS_RES_OK)
exit(1);
/* ... */
}
</pre>
<h4>Example</h4>
<pre>
#define tagMASK 0x0003
static mps_root_t mmRoot;
Object *Objects[rootCOUNT];
int main(void)
{
mps_res_t res;
/* ... */
res = mps_root_create_table_masked(&amp;mmRoot, arena, MPS_RANK_EXACT, (mps_rm_t)0,
(mps_addr_t)&amp;Objects, rootCOUNT,
(mps_word_t)tagMASK);
if(res != MPS_RES_OK)
exit(1);
/* ... */
}
</pre>
<h4>Example</h4>
<pre>
static StackFrame *stackBottom;
/* root scanner for an imaginary interpreter for a stack-oriented language */
static mps_res_t rootScanner(mps_ss_t ss, void * p, size_t s)
{
StackFrame *frame;
size_t i;
mps_res_t res;
UNUSED(p);
UNUSED(s);
for(frame = stackBottom; frame != NULL; frame = frame-&gt;next)
for(i = frame-&gt;size; i &gt; 0; --i) {
res = mps_fix(ss, &amp;frame-&gt;locals[i]);
if(res != MPS_RES_OK) return res;
}
return res;
}
</pre>
<h4>Example</h4>
<pre>
typedef struct {
mps_root_t mmRoot;
mps_thr_t thread;
/* ... */
} ThreadLocals;
void InitThread(ThreadLocals *thr)
{
/* This is a hack to find the bottom of the stack. */
void *stackBottom=&amp;stackBottom;
mps_thread_reg(&amp;thr-&gt;thread, arena);
mps_root_create_reg(&amp;thr-&gt;mmRoot, arena, MPS_RANK_AMBIG, (mps_rm_t)0,
thr-&gt;thread, mps_stack_scan_ambig, stackBottom, 0)
/* ... */
}
</pre>
<h4>Example</h4>
<pre>
mps_thr_t this_thread;
mps_res_t res;
res = mps_thread_reg(&amp;this_thread, space);
if(res != MPS_RES_OK) return res;
</pre>

View file

@ -3,3 +3,9 @@
=========
Telemetry
=========
Typical uses of telemtry labels include:
- Label pools with a human-meaningful name;
- Label allocated objects with their type or class.