1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-26 07:11:34 -08:00
emacs/mps/manual/html/topic/allocation.html
Gareth Rees 6cbd932e05 Updated manual html
Copied from Perforce
 Change: 182092
 ServerID: perforce.ravenbrook.com
2013-05-22 19:26:41 +01:00

715 lines
No EOL
68 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>6. Allocation &mdash; Memory Pool System 1.111.0 documentation</title>
<link rel="stylesheet" href="../_static/mps.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.111.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="top" title="Memory Pool System 1.111.0 documentation" href="../index.html" />
<link rel="up" title="Reference" href="index.html" />
<link rel="next" title="7. Object formats" href="format.html" />
<link rel="prev" title="5. Pools" href="pool.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="format.html" title="7. Object formats"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="pool.html" title="5. Pools"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" accesskey="U">Reference</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="allocation">
<span id="topic-allocation"></span><span id="index-0"></span><h1>6. Allocation<a class="headerlink" href="#allocation" title="Permalink to this headline"></a></h1>
<div class="section" id="manual-allocation">
<span id="index-1"></span><h2>6.1. Manual allocation<a class="headerlink" href="#manual-allocation" title="Permalink to this headline"></a></h2>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">Not all <a class="reference internal" href="../glossary/p.html#term-pool-class"><em class="xref std std-term">pool classes</em></a> support this interface:
<a class="reference internal" href="../glossary/a.html#term-automatic-memory-management"><em class="xref std std-term">automatically managed</em></a> pools
typically support none of it, and even <a class="reference internal" href="../glossary/m.html#term-manual-memory-management"><em class="xref std std-term">manually managed</em></a> pools may not support the whole
interface. Consult the pool class documentation for details. For
example, the <a class="reference internal" href="../pool/mvt.html#pool-mvt"><em>MVT (Manual Variable Temporal)</em></a> pool class supports deallocation via
<a class="reference internal" href="#mps_free" title="mps_free"><tt class="xref c c-func docutils literal"><span class="pre">mps_free()</span></tt></a> but allocation must use allocation points, as
described below.</p>
</div>
<dl class="function">
<dt id="mps_alloc">
<a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a> <tt class="descname">mps_alloc</tt><big>(</big><a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;*p_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em>&nbsp;pool</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#mps_alloc" title="Permalink to this definition"></a></dt>
<dd><p>Allocate a <a class="reference internal" href="../glossary/b.html#term-block"><em class="xref std std-term">block</em></a> of memory in a <a class="reference internal" href="../glossary/p.html#term-pool"><em class="xref std std-term">pool</em></a>.</p>
<p><tt class="docutils literal"><span class="pre">p_o</span></tt> points to a location that will hold the address of the
allocated block.</p>
<p><tt class="docutils literal"><span class="pre">pool</span></tt> the pool to allocate in.</p>
<p><tt class="docutils literal"><span class="pre">size</span></tt> is the <a class="reference internal" href="../glossary/s.html#term-size"><em class="xref std std-term">size</em></a> of the block to allocate. If it is
unaligned, it will be rounded up to the pool&#8217;s <a class="reference internal" href="../glossary/a.html#term-alignment"><em class="xref std std-term">alignment</em></a>
(unless the pool documentation says otherwise).</p>
</dd></dl>
<dl class="function">
<dt id="mps_free">
void <tt class="descname">mps_free</tt><big>(</big><a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em>&nbsp;pool</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;addr</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#mps_free" title="Permalink to this definition"></a></dt>
<dd><p>Free a <a class="reference internal" href="../glossary/b.html#term-block"><em class="xref std std-term">block</em></a> of memory to a <a class="reference internal" href="../glossary/p.html#term-pool"><em class="xref std std-term">pool</em></a>.</p>
<p><tt class="docutils literal"><span class="pre">pool</span></tt> is the pool the block belongs to.</p>
<p><tt class="docutils literal"><span class="pre">addr</span></tt> is the address of the block to be freed.</p>
<p><tt class="docutils literal"><span class="pre">size</span></tt> is the <a class="reference internal" href="../glossary/s.html#term-size"><em class="xref std std-term">size</em></a> of the block to be freed. If it is
unaligned, it will be rounded up to the pool&#8217;s <a class="reference internal" href="../glossary/a.html#term-alignment"><em class="xref std std-term">alignment</em></a>
(unless the pool documentation says otherwise).</p>
<p>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.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last"><a class="reference internal" href="#mps_free" title="mps_free"><tt class="xref c c-func docutils literal"><span class="pre">mps_free()</span></tt></a> takes a <tt class="docutils literal"><span class="pre">size</span></tt> 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 because of the need
to touch the object in order to free it. As it is, the
deallocation code doesn&#8217;t have to touch the dead object at
all.</p>
</div>
</dd></dl>
</div>
<div class="section" id="allocation-points">
<span id="index-2"></span><h2>6.2. Allocation points<a class="headerlink" href="#allocation-points" title="Permalink to this headline"></a></h2>
<p><a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">Allocation points</em></a> provide fast, <a class="reference internal" href="../glossary/i.html#term-inline-allocation-1"><em class="xref std std-term">inline</em></a>, nearly <a class="reference internal" href="../glossary/l.html#term-lock-free"><em class="xref std std-term">lock-free</em></a> allocation.
They allow code to allocate without calling an allocation function:
this is vital for performance in languages or programs that allocate
many small objects. They must be used according to the
<a class="reference internal" href="#topic-allocation-point-protocol"><em>Allocation point protocol</em></a>.</p>
<dl class="type">
<dt id="mps_ap_t">
<tt class="descname">mps_ap_t</tt><a class="headerlink" href="#mps_ap_t" title="Permalink to this definition"></a></dt>
<dd><p>The type of <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation points</em></a>. It is a
<a class="reference internal" href="../glossary/t.html#term-transparent-type"><em class="xref std std-term">transparent alias</em></a> for a pointer to
<a class="reference internal" href="#mps_ap_s" title="mps_ap_s"><tt class="xref c c-type docutils literal"><span class="pre">mps_ap_s</span></tt></a>.</p>
</dd></dl>
<dl class="function">
<dt id="mps_ap_create_k">
<a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a> <tt class="descname">mps_ap_create_k</tt><big>(</big><a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;*ap_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em>&nbsp;pool</em>, <a class="reference internal" href="keyword.html#mps_arg_s" title="mps_arg_s">mps_arg_s</a><em>&nbsp;args[]</em><big>)</big><a class="headerlink" href="#mps_ap_create_k" title="Permalink to this definition"></a></dt>
<dd><p>Create an <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation point</em></a> in a <a class="reference internal" href="../glossary/p.html#term-pool"><em class="xref std std-term">pool</em></a>.</p>
<p><tt class="docutils literal"><span class="pre">ap_o</span></tt> points to a location that will hold the address of the
allocation point, if successful.</p>
<p><tt class="docutils literal"><span class="pre">pool</span></tt> is the pool.</p>
<p><tt class="docutils literal"><span class="pre">args</span></tt> are <a class="reference internal" href="../glossary/k.html#term-keyword-argument"><em class="xref std std-term">keyword arguments</em></a> specific to the pool class
to which <tt class="docutils literal"><span class="pre">pool</span></tt> belong. See the documentation for that pool
class. (Most pool classes don&#8217;t take any keyword arguments; in
those cases you can pass <a class="reference internal" href="keyword.html#mps_args_none" title="mps_args_none"><tt class="xref c c-macro docutils literal"><span class="pre">mps_args_none</span></tt></a>.)</p>
<p>Returns <a class="reference internal" href="error.html#MPS_RES_OK" title="MPS_RES_OK"><tt class="xref c c-macro docutils literal"><span class="pre">MPS_RES_OK</span></tt></a> if successful, or another
<a class="reference internal" href="../glossary/r.html#term-result-code"><em class="xref std std-term">result code</em></a> if not.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">An allocation point must not be used by more than one
<a class="reference internal" href="../glossary/t.html#term-thread"><em class="xref std std-term">thread</em></a>: each thread must create its own allocation
point or points.</p>
</div>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">There&#8217;s an alternative function <a class="reference internal" href="#mps_ap_create_v" title="mps_ap_create_v"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_create_v()</span></tt></a> that
takes its extra arguments using the standard <a class="reference internal" href="../mmref/lang.html#term-c"><em class="xref std std-term">C</em></a>
<tt class="docutils literal"><span class="pre">va_list</span></tt> mechanism.</p>
</div>
</dd></dl>
<dl class="function">
<dt id="mps_ap_create">
<a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a> <tt class="descname">mps_ap_create</tt><big>(</big><a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;*ap_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em>&nbsp;pool</em>, ...<big>)</big><a class="headerlink" href="#mps_ap_create" title="Permalink to this definition"></a></dt>
<dd><div class="admonition-deprecated admonition">
<p class="first admonition-title">Deprecated</p>
<p>starting with version 1.112.</p>
<p class="last">Use <a class="reference internal" href="#mps_ap_create_k" title="mps_ap_create_k"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_create_k()</span></tt></a> instead: the <a class="reference internal" href="../glossary/k.html#term-keyword-argument"><em class="xref std std-term">keyword
arguments</em></a> interface is more reliable and produces better
error messages.</p>
</div>
<p>An alternative to <a class="reference internal" href="#mps_ap_create_k" title="mps_ap_create_k"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_create_k()</span></tt></a> that takes its extra
arguments using the standard <a class="reference internal" href="../mmref/lang.html#term-c"><em class="xref std std-term">C</em></a> variable argument list
mechanism.</p>
</dd></dl>
<dl class="function">
<dt id="mps_ap_create_v">
<a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a> <tt class="descname">mps_ap_create_v</tt><big>(</big><a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;*ap_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em>&nbsp;pool</em>, va_list<em>&nbsp;args</em><big>)</big><a class="headerlink" href="#mps_ap_create_v" title="Permalink to this definition"></a></dt>
<dd><div class="admonition-deprecated admonition">
<p class="first admonition-title">Deprecated</p>
<p>starting with version 1.112.</p>
<p class="last">Use <a class="reference internal" href="#mps_ap_create_k" title="mps_ap_create_k"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_create_k()</span></tt></a> instead: the <a class="reference internal" href="../glossary/k.html#term-keyword-argument"><em class="xref std std-term">keyword
arguments</em></a> interface is more reliable and produces better
error messages.</p>
</div>
<p>An alternative to <a class="reference internal" href="#mps_ap_create_k" title="mps_ap_create_k"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_create_k()</span></tt></a> that takes its extra
arguments using the standard <a class="reference internal" href="../mmref/lang.html#term-c"><em class="xref std std-term">C</em></a> <tt class="docutils literal"><span class="pre">va_list</span></tt> mechanism.</p>
</dd></dl>
<dl class="function">
<dt id="mps_ap_destroy">
void <tt class="descname">mps_ap_destroy</tt><big>(</big><a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;ap</em><big>)</big><a class="headerlink" href="#mps_ap_destroy" title="Permalink to this definition"></a></dt>
<dd><p>Destroy an <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation point</em></a>.</p>
<p><tt class="docutils literal"><span class="pre">ap</span></tt> is the allocation point to destroy.</p>
<p>Destroying an allocation point has no effect on blocks that were
allocated from it, so long as they were successfully
<a class="reference internal" href="../glossary/c.html#term-committed-2"><em class="xref std std-term">committed<sup>(2)</sup></em></a> by <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>.</p>
</dd></dl>
</div>
<div class="section" id="allocation-point-protocol">
<span id="topic-allocation-point-protocol"></span><span id="index-3"></span><h2>6.3. Allocation point protocol<a class="headerlink" href="#allocation-point-protocol" title="Permalink to this headline"></a></h2>
<p>This protocol is designed to work with <a class="reference internal" href="../glossary/i.html#term-incremental-garbage-collection"><em class="xref std std-term">incremental garbage
collection</em></a> and multiple <a class="reference internal" href="../glossary/t.html#term-thread"><em class="xref std std-term">threads</em></a>, where between any
two instructions in the <a class="reference internal" href="../glossary/c.html#term-client-program"><em class="xref std std-term">client program</em></a>, the MPS may run part
of a <a class="reference internal" href="../glossary/g.html#term-garbage-collection"><em class="xref std std-term">garbage collection</em></a>, <a class="reference internal" href="../glossary/m.html#term-moving-memory-manager"><em class="xref std std-term">move</em></a>
blocks in memory, rewrite pointers, and reclaim space. In order to
reliably handle this, the allocation point protocol consists of (at
least) two steps, a <em>reserve</em> followed by a <em>commit</em>.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">The description of the protocol assumes that you have declared
your threads&#8217; <a class="reference internal" href="../glossary/c.html#term-control-stack"><em class="xref std std-term">control stacks</em></a> and <a class="reference internal" href="../glossary/r.html#term-register"><em class="xref std std-term">registers</em></a> to be
<a class="reference internal" href="../glossary/a.html#term-ambiguous-root"><em class="xref std std-term">ambiguous roots</em></a>, by passing <a class="reference internal" href="root.html#mps_stack_scan_ambig" title="mps_stack_scan_ambig"><tt class="xref c c-func docutils literal"><span class="pre">mps_stack_scan_ambig()</span></tt></a>
to <a class="reference internal" href="root.html#mps_root_create_reg" title="mps_root_create_reg"><tt class="xref c c-func docutils literal"><span class="pre">mps_root_create_reg()</span></tt></a>. This is the simplest way to
write a client, but other scenarios are possible. Please
<a class="reference internal" href="../contact.html#contact"><em>contact us</em></a> if your use case is not covered here
(for example, if you need an exact collector).</p>
</div>
<p>When the client program is initializing a newly allocated object, you
can think of it as being &#8220;in a race&#8221; with the MPS. Until the object is
initialized, the MPS cannot manage it in the usual way: in particular,
it cannot ensure that the new object remains correct if other objects
move during its initialization. So if other objects <em>do</em> move, the MPS
tells the client program that it has &#8220;lost the race&#8221;: the
partially-initialized object may be invalid, and the client must
initialize it again from scratch.</p>
<p>The allocation point protocol is as follows:</p>
<ol class="arabic">
<li><p class="first">Call <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> to reserve a block of memory on an
allocation point. The size of the block must be a multiple of the
<a class="reference internal" href="../glossary/a.html#term-alignment"><em class="xref std std-term">alignment</em></a> of the pool in which the allocation point was
created.</p>
<p>If <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> returns <a class="reference internal" href="error.html#MPS_RES_OK" title="MPS_RES_OK"><tt class="xref c c-macro docutils literal"><span class="pre">MPS_RES_OK</span></tt></a>, go to step 2.</p>
<p>Otherwise, the block cannot be reserved (this might happen if the
MPS is out of memory).</p>
</li>
<li><p class="first">Initialize the block. During this step the block must not be
referenced by an <a class="reference internal" href="../glossary/e.html#term-exact-reference"><em class="xref std std-term">exact reference</em></a>, and references stored in
it must not be followed.</p>
<p>The block need not be initialized completely, but if the pool has
an <a class="reference internal" href="../glossary/o.html#term-object-format"><em class="xref std std-term">object format</em></a>, then by the end of this step, the block
must be capable of being passed to the format&#8217;s <a class="reference internal" href="../glossary/s.html#term-scan-method"><em class="xref std std-term">scan method</em></a>
and <a class="reference internal" href="../glossary/s.html#term-skip-method"><em class="xref std std-term">skip method</em></a>.</p>
</li>
<li><p class="first">Call <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> to attempt to commit the object to the
care of the MPS.</p>
<p>If <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> returns true, this means that the object is
valid, and is now under the management of the MPS. The client program
may rely on references stored in the object, and may store references
to the new object in its other objects.</p>
<p>If <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> returns false, this means that the block is
invalid. It is usual in this case to go back to step 1 and re-reserve
and re-initialize it, but other courses of action are permitted.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">In this case, the reason the block is invalid because a
<a class="reference internal" href="../glossary/f.html#term-flip"><em class="xref std std-term">flip</em></a> took place after the call to
<a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> and before the call to
<a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>. This means that references in the block
may point to the old location of blocks that moved.</p>
</div>
</li>
</ol>
<p>The usual implementation of the allocation point protocol in <a class="reference internal" href="../mmref/lang.html#term-c"><em class="xref std std-term">C</em></a>
is thus:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">mps_addr_t</span> <span class="n">p</span><span class="p">;</span>
<span class="n">obj_t</span> <span class="n">obj</span><span class="p">;</span>
<span class="k">do</span> <span class="p">{</span>
<span class="n">mps_res_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">mps_reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span> <span class="n">ap</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="cm">/* handle the error */</span><span class="p">;</span>
<span class="cm">/* p is now an ambiguous reference to the reserved block */</span>
<span class="n">obj</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
<span class="cm">/* initialize obj */</span>
<span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">mps_commit</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">size</span><span class="p">));</span>
<span class="cm">/* obj is now valid and managed by the MPS */</span>
</pre></div>
</div>
<p>It is not necessary to worry about going around this loop many times:
<a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> can fail at most once per thread per
<a class="reference internal" href="../glossary/f.html#term-flip"><em class="xref std std-term">flip</em></a>.</p>
<dl class="function">
<dt id="mps_reserve">
<a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a> <tt class="descname">mps_reserve</tt><big>(</big><a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;*p_o</em>, <a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;ap</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#mps_reserve" title="Permalink to this definition"></a></dt>
<dd><p>Reserve a <a class="reference internal" href="../glossary/b.html#term-block"><em class="xref std std-term">block</em></a> of memory on an <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation point</em></a>.</p>
<p><tt class="docutils literal"><span class="pre">p_o</span></tt> points to a location that will hold the address of the
reserved block.</p>
<p><tt class="docutils literal"><span class="pre">ap</span></tt> is the allocation point.</p>
<p><tt class="docutils literal"><span class="pre">size</span></tt> is the <a class="reference internal" href="../glossary/s.html#term-size"><em class="xref std std-term">size</em></a> of the block to allocate. It must be
a multiple of the <a class="reference internal" href="../glossary/a.html#term-alignment"><em class="xref std std-term">alignment</em></a> of the pool (or of the pool&#8217;s
<a class="reference internal" href="../glossary/o.html#term-object-format"><em class="xref std std-term">object format</em></a> if it has one).</p>
<p>Returns <a class="reference internal" href="error.html#MPS_RES_OK" title="MPS_RES_OK"><tt class="xref c c-macro docutils literal"><span class="pre">MPS_RES_OK</span></tt></a> if the block was reserved
successfully, or another <a class="reference internal" href="../glossary/r.html#term-result-code"><em class="xref std std-term">result code</em></a> if not.</p>
<p>The reserved block may be initialized but must not otherwise be
used</p>
<p>Until it has been <a class="reference internal" href="../glossary/c.html#term-committed-2"><em class="xref std std-term">committed<sup>(2)</sup></em></a> via a successful call to
<a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>, the reserved block may be:</p>
<ul class="simple">
<li>initialized;</li>
<li>referenced by an <a class="reference internal" href="../glossary/a.html#term-ambiguous-reference"><em class="xref std std-term">ambiguous reference</em></a>;</li>
</ul>
<p>but:</p>
<ul class="simple">
<li>it must not be referenced by an <a class="reference internal" href="../glossary/e.html#term-exact-reference"><em class="xref std std-term">exact reference</em></a>;</li>
<li>references stored in it must not be followed;</li>
<li>it is not scanned, moved, or protected (even if it belongs to a
pool with these features).</li>
</ul>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p><a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> must only be called according to the
<a class="reference internal" href="#topic-allocation-point-protocol"><em>Allocation point protocol</em></a>.</p>
<p><a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> is implemented as a macro for speed. It
may evaluate its arguments multiple times.</p>
<p class="last">There is an alternative, <a class="reference internal" href="#MPS_RESERVE_BLOCK" title="MPS_RESERVE_BLOCK"><tt class="xref c c-func docutils literal"><span class="pre">MPS_RESERVE_BLOCK()</span></tt></a>, which
may generate faster code on some compilers.</p>
</div>
</dd></dl>
<dl class="function">
<dt id="MPS_RESERVE_BLOCK">
<tt class="descname">MPS_RESERVE_BLOCK</tt><big>(</big><a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a><em>&nbsp;res_v</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;*p_v</em>, <a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;ap</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#MPS_RESERVE_BLOCK" title="Permalink to this definition"></a></dt>
<dd><p>An alternative to <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a>. On compilers that do not
perform common-subexpression elimination, it may generate faster
code than <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> (but may not). It may only be used
in statement context (not as an expression).</p>
<p>The second argument is an lvalue <tt class="docutils literal"><span class="pre">p_v</span></tt>, which is assigned the
address of the reserved block. It takes an additional first
argument, the lvalue <tt class="docutils literal"><span class="pre">res_v</span></tt>, which is assigned the
<a class="reference internal" href="../glossary/r.html#term-result-code"><em class="xref std std-term">result code</em></a>.</p>
</dd></dl>
<dl class="function">
<dt id="mps_commit">
<a class="reference internal" href="interface.html#mps_bool_t" title="mps_bool_t">mps_bool_t</a> <tt class="descname">mps_commit</tt><big>(</big><a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;ap</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;p</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#mps_commit" title="Permalink to this definition"></a></dt>
<dd><p><a class="reference internal" href="../glossary/c.html#term-committed-2"><em class="xref std std-term">Commit</em></a> a reserved <a class="reference internal" href="../glossary/b.html#term-block"><em class="xref std std-term">block</em></a> on an
<a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation point</em></a>.</p>
<p><tt class="docutils literal"><span class="pre">ap</span></tt> is an allocation point.</p>
<p><tt class="docutils literal"><span class="pre">p</span></tt> points to a block that was reserved by <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a>
but has not yet been committed.</p>
<p><tt class="docutils literal"><span class="pre">size</span></tt> is the <a class="reference internal" href="../glossary/s.html#term-size"><em class="xref std std-term">size</em></a> of the block to allocate. It must be
the same size that was passed to <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a>.</p>
<p>If <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> returns true, the block was successfully
committed, which means that the <a class="reference internal" href="../glossary/c.html#term-client-program"><em class="xref std std-term">client program</em></a> 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 <tt class="docutils literal"><span class="pre">ap</span></tt> was attached to a pool with those features).</p>
<p>If <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> 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.</p>
<p>It is very rare for <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> to return false: this
only happens if there was a <a class="reference internal" href="../glossary/f.html#term-flip"><em class="xref std std-term">flip</em></a> between the call to
<a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> and the call to
<a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>. Nonetheless, it can happen, so it is
important not to perform operations with side effects (that you
aren&#8217;t prepared to repeat) between calling <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a>
and <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>. Also, the shorter the interval, the less
likely <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> is to return false.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p><a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> must only be called according to the
<a class="reference internal" href="#topic-allocation-point-protocol"><em>Allocation point protocol</em></a>.</p>
<p class="last"><a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> is implemented as a macro for speed. It
may evaluate its arguments multiple times.</p>
</div>
</dd></dl>
</div>
<div class="section" id="example-allocating-a-symbol">
<span id="index-4"></span><h2>6.4. Example: allocating a symbol<a class="headerlink" href="#example-allocating-a-symbol" title="Permalink to this headline"></a></h2>
<div class="highlight-c"><div class="highlight"><pre><span class="k">typedef</span> <span class="k">struct</span> <span class="n">symbol_s</span> <span class="p">{</span>
<span class="n">type_t</span> <span class="n">type</span><span class="p">;</span> <span class="cm">/* TYPE_SYMBOL */</span>
<span class="kt">size_t</span> <span class="n">length</span><span class="p">;</span> <span class="cm">/* length of symbol string (excl. NUL) */</span>
<span class="kt">char</span> <span class="n">string</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="cm">/* symbol string, NUL terminated */</span>
<span class="p">}</span> <span class="n">symbol_s</span><span class="p">,</span> <span class="o">*</span><span class="n">symbol_t</span><span class="p">;</span>
<span class="n">symbol_t</span> <span class="nf">make_symbol</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">length</span><span class="p">,</span> <span class="kt">char</span> <span class="n">string</span><span class="p">[])</span>
<span class="p">{</span>
<span class="n">symbol_t</span> <span class="n">symbol</span><span class="p">;</span>
<span class="n">mps_addr_t</span> <span class="n">addr</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="n">offsetof</span><span class="p">(</span><span class="n">symbol_s</span><span class="p">,</span> <span class="n">string</span><span class="p">)</span> <span class="o">+</span> <span class="n">length</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="k">do</span> <span class="p">{</span>
<span class="n">mps_res_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">mps_reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="n">addr</span><span class="p">,</span> <span class="n">ap</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;out of memory in make_symbol&quot;</span><span class="p">);</span>
<span class="n">symbol</span> <span class="o">=</span> <span class="n">addr</span><span class="p">;</span>
<span class="n">symbol</span><span class="o">-&gt;</span><span class="n">type</span> <span class="o">=</span> <span class="n">TYPE_SYMBOL</span><span class="p">;</span>
<span class="n">symbol</span><span class="o">-&gt;</span><span class="n">length</span> <span class="o">=</span> <span class="n">length</span><span class="p">;</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">symbol</span><span class="o">-&gt;</span><span class="n">string</span><span class="p">,</span> <span class="n">string</span><span class="p">,</span> <span class="n">length</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">mps_commit</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">size</span><span class="p">));</span>
<span class="k">return</span> <span class="n">symbol</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="cautions">
<span id="topic-allocation-cautions"></span><span id="index-5"></span><h2>6.5. Cautions<a class="headerlink" href="#cautions" title="Permalink to this headline"></a></h2>
<p>While a block is reserved but not yet committed:</p>
<ol class="arabic simple">
<li>The client program must not create an <a class="reference internal" href="../glossary/e.html#term-exact-reference"><em class="xref std std-term">exact reference</em></a> to
the reserved block (for example, by referring to the reserved block
from a <a class="reference internal" href="../glossary/f.html#term-formatted-object"><em class="xref std std-term">formatted object</em></a>). All references to it must be
ambiguous (for example, local variables).</li>
<li>Similar restrictions apply to a reference that has been stored in
the reserved block. Such a reference might be invalid, and must
not be copied to an <a class="reference internal" href="../glossary/e.html#term-exact-reference"><em class="xref std std-term">exact reference</em></a> or dereferenced. It is
safe to copy such a reference if it remains ambiguous (for
example, copying to a local variable or to another part of the new
block).</li>
</ol>
<p>Before calling <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>:</p>
<ol class="arabic simple">
<li>The new block must be validly formatted. If it belongs to an
<a class="reference internal" href="../glossary/o.html#term-object-format"><em class="xref std std-term">object format</em></a>, then it must be correctly recognized by the
format methods (the <a class="reference internal" href="../glossary/s.html#term-skip-method"><em class="xref std std-term">skip method</em></a> must return the object&#8217;s
correct size; the <a class="reference internal" href="../glossary/s.html#term-scan-method"><em class="xref std std-term">scan method</em></a> must scan it; the
<a class="reference internal" href="../glossary/i.html#term-is-forwarded-method"><em class="xref std std-term">is-forwarded method</em></a> must report that it is not a
forwarding object, and so on).</li>
<li>All exact references in the new block (references that are
<a class="reference internal" href="../glossary/f.html#term-fix"><em class="xref std std-term">fixed</em></a> by scanning functions) must contain valid
references or null pointers.</li>
<li>The new object must be ambiguously <a class="reference internal" href="../glossary/r.html#term-reachable"><em class="xref std std-term">reachable</em></a>.</li>
</ol>
<p>You do not have to initialize the whole block so long as you satisfy
these conditions. For example, it is permissible to defer
initialization completely (for example, by writing
<tt class="docutils literal"><span class="pre">TYPE_UNINITIALIZED</span></tt> into a tag field), so long as you handle this
correctly in the format methods.</p>
<p>However, if you do not initialize the whole block then you should
beware: the uninitialized contents of the block is likely to consist
of dead objects. If, due to a bug, you created an exact reference into
the middle of the uninitialized block, this might by bad luck point to
a dead object, which would be resurrected (and it might well contain
further exact references to other dead objects). To ensure detection
of such a bug promptly you should consider filling the uninitialized
object with dummy values that cannot be mistaken for part of a valid
formatted object (at least in the debugging version of your program).</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">Some <a class="reference internal" href="../glossary/p.html#term-pool-class"><em class="xref std std-term">pool classes</em></a> have debugging counterparts that
automatically overwrite free space with a pattern of bytes of your
choosing. See <a class="reference internal" href="debugging.html#topic-debugging"><em>Debugging pools</em></a>.</p>
</div>
</div>
<div class="section" id="example-inserting-into-a-doubly-linked-list">
<span id="index-6"></span><h2>6.6. Example: inserting into a doubly linked list<a class="headerlink" href="#example-inserting-into-a-doubly-linked-list" title="Permalink to this headline"></a></h2>
<p>This example contains several mistakes. See the highlighted lines:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">typedef</span> <span class="k">struct</span> <span class="n">link_s</span> <span class="p">{</span>
<span class="n">type_t</span> <span class="n">type</span><span class="p">;</span> <span class="cm">/* TYPE_LINK */</span>
<span class="cm">/* all three of these pointers are fixed: */</span>
<span class="k">struct</span> <span class="n">link_s</span> <span class="o">*</span><span class="n">prev</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">link_s</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span>
<span class="n">obj_t</span> <span class="n">obj</span><span class="p">;</span>
<span class="p">}</span> <span class="n">link_s</span><span class="p">,</span> <span class="o">*</span><span class="n">link_t</span><span class="p">;</span>
<span class="cm">/* insert &#39;obj&#39; into the doubly-linked list after &#39;head&#39; */</span>
<span class="n">link_t</span> <span class="nf">insert_link</span><span class="p">(</span><span class="n">link_t</span> <span class="n">head</span><span class="p">,</span> <span class="n">obj_t</span> <span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">mps_addr_t</span> <span class="n">p</span><span class="p">;</span>
<span class="n">link_t</span> <span class="n">link</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">link_s</span><span class="p">));</span>
<span class="k">do</span> <span class="p">{</span>
<span class="n">mps_res_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">mps_reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span> <span class="n">ap</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;out of memory&quot;</span><span class="p">);</span>
<span class="n">link</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
<span class="n">link</span><span class="o">-&gt;</span><span class="n">type</span> <span class="o">=</span> <span class="n">TYPE_LINK</span><span class="p">;</span>
<span class="n">link</span><span class="o">-&gt;</span><span class="n">prev</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="hll"> <span class="n">link</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">link</span><span class="o">-&gt;</span><span class="n">prev</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span> <span class="cm">/* (1) */</span>
</span><span class="hll"> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">link</span><span class="p">;</span> <span class="cm">/* (2) */</span>
</span><span class="hll"> <span class="n">link</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">prev</span> <span class="o">=</span> <span class="n">link</span><span class="p">;</span> <span class="cm">/* (3) */</span>
</span> <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">mps_commit</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">size</span><span class="p">));</span>
<span class="hll"> <span class="n">link</span><span class="o">-&gt;</span><span class="n">obj</span> <span class="o">=</span> <span class="n">obj</span><span class="p">;</span> <span class="cm">/* (4) */</span>
</span> <span class="k">return</span> <span class="n">link</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The mistakes are:</p>
<ol class="arabic simple">
<li>Dereferencing a reference (here, <tt class="docutils literal"><span class="pre">link-&gt;prev</span></tt>) that was stored in
the reserved block.</li>
<li>Making an exact reference to the reserved block (here,
<tt class="docutils literal"><span class="pre">head-&gt;next</span></tt> becomes an exact reference to <tt class="docutils literal"><span class="pre">link</span></tt>). This must
be deferred until after a successful commit.</li>
<li>This line makes both mistakes made by lines (1) and (2).</li>
<li>The <tt class="docutils literal"><span class="pre">obj</span></tt> slot contains an exact reference that gets fixed by the
scan method, so it must be initialized before the call to commit.</li>
</ol>
<p>A correct version of <tt class="docutils literal"><span class="pre">insert_link</span></tt> looks like this:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">link_t</span> <span class="nf">insert_link</span><span class="p">(</span><span class="n">link_t</span> <span class="n">head</span><span class="p">,</span> <span class="n">obj_t</span> <span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">mps_addr_t</span> <span class="n">p</span><span class="p">;</span>
<span class="n">link_t</span> <span class="n">link</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">link_s</span><span class="p">));</span>
<span class="k">do</span> <span class="p">{</span>
<span class="n">mps_res_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">mps_reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span> <span class="n">ap</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;out of memory&quot;</span><span class="p">);</span>
<span class="n">link</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
<span class="n">link</span><span class="o">-&gt;</span><span class="n">type</span> <span class="o">=</span> <span class="n">TYPE_LINK</span><span class="p">;</span>
<span class="n">link</span><span class="o">-&gt;</span><span class="n">prev</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="n">link</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span>
<span class="n">link</span><span class="o">-&gt;</span><span class="n">obj</span> <span class="o">=</span> <span class="n">obj</span><span class="p">;</span>
<span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">mps_commit</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">size</span><span class="p">));</span>
<span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span><span class="o">-&gt;</span><span class="n">prev</span> <span class="o">=</span> <span class="n">link</span><span class="p">;</span>
<span class="n">head</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">link</span><span class="p">;</span>
<span class="k">return</span> <span class="n">link</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="allocation-point-implementation">
<span id="topic-allocation-point-implementation"></span><span id="index-7"></span><h2>6.7. Allocation point implementation<a class="headerlink" href="#allocation-point-implementation" title="Permalink to this headline"></a></h2>
<p>An allocation point consists of a structure of type <a class="reference internal" href="#mps_ap_s" title="mps_ap_s"><tt class="xref c c-type docutils literal"><span class="pre">mps_ap_s</span></tt></a>
and an associated <a class="reference internal" href="../glossary/b.html#term-buffer"><em class="xref std std-term">buffer</em></a>.</p>
<div class="figure align-center">
<img alt="Diagram: Allocation point and its associated buffer." src="../_images/ap-buffer.svg" /><p class="caption">Allocation point and its associated buffer.</p>
</div>
<p>The buffer is structured as shown in the figure, with free space at
the end of the buffer, <em>committed</em> blocks at the beginning, and
(possibly) one <em>reserved</em> block in the middle. The <a class="reference internal" href="#mps_ap_s" title="mps_ap_s"><tt class="xref c c-type docutils literal"><span class="pre">mps_ap_s</span></tt></a>
structure contains three addresses into the associated buffer:
<tt class="docutils literal"><span class="pre">limit</span></tt> points to the end of the buffer, <tt class="docutils literal"><span class="pre">alloc</span></tt> points to the
beginning of the free space, and <tt class="docutils literal"><span class="pre">init</span></tt> points to the end of the
initialized blocks.</p>
<p>Allocation points are fast and nearly lock-free because in order to
reserve space for a new block, the client program first checks that
<tt class="docutils literal"><span class="pre">ap-&gt;alloc</span> <span class="pre">+</span> <span class="pre">size</span> <span class="pre">&lt;=</span> <span class="pre">ap-&gt;limit</span></tt> and in the common case that it is,
it takes a copy of <tt class="docutils literal"><span class="pre">ap-&gt;init</span></tt> (which now points to the reserved
block) and sets <tt class="docutils literal"><span class="pre">ap-&gt;alloc</span> <span class="pre">+=</span> <span class="pre">size</span></tt>.</p>
<p>What happens when <tt class="docutils literal"><span class="pre">ap-&gt;alloc</span> <span class="pre">+</span> <span class="pre">size</span> <span class="pre">&gt;</span> <span class="pre">ap-&gt;limit</span></tt>, that is, when the
new block won&#8217;t fit in the buffer? Then the buffer needs to be
<em>refilled</em> by calling <a class="reference internal" href="#mps_ap_fill" title="mps_ap_fill"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_fill()</span></tt></a>, with typical results
shown in the diagram below.</p>
<div class="figure align-center">
<img alt="Diagram: Allocation point after refilling." src="../_images/ap-fill.svg" /><p class="caption">Allocation point after refilling.</p>
</div>
<p>Refilling is why allocation points are only <em>nearly</em> lock-free:
<a class="reference internal" href="#mps_ap_fill" title="mps_ap_fill"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_fill()</span></tt></a> has to take locks on internal MPS data
structures.</p>
<p>Note that <a class="reference internal" href="#mps_ap_fill" title="mps_ap_fill"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_fill()</span></tt></a> reserves the requested block as well
as refilling the buffer.</p>
<p>The <em>reserve</em> operation thus looks like this:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ap</span><span class="o">-&gt;</span><span class="n">alloc</span> <span class="o">+</span> <span class="n">size</span> <span class="o">&lt;=</span> <span class="n">ap</span><span class="o">-&gt;</span><span class="n">limit</span><span class="p">)</span> <span class="p">{</span>
<span class="n">ap</span><span class="o">-&gt;</span><span class="n">alloc</span> <span class="o">+=</span> <span class="n">size</span><span class="p">;</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">ap</span><span class="o">-&gt;</span><span class="n">init</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">mps_ap_fill</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="p">,</span> <span class="n">ap</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="p">{</span>
<span class="cm">/* handle error */</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The critical path consists of an add, a store, and a branch (and
branch prediction should work well since the test usually succeeds).</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">Normally the client program would use the macro
<a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> to perform this operation, as described
above, rather than directly accessing the fields of the allocation
point structure. But there are use cases where direct access is
needed to generate the fastest code (for example, in the case of a
compiler generating machine code that needs to interface with the
MPS), and it is for these use cases that the details of
<a class="reference internal" href="#mps_ap_s" title="mps_ap_s"><tt class="xref c c-type docutils literal"><span class="pre">mps_ap_s</span></tt></a> are made public and supported.</p>
</div>
<p>When the new block has been initialized it must be <a class="reference internal" href="../glossary/c.html#term-committed-2"><em class="xref std std-term">committed<sup>(2)</sup></em></a>. To do this, set <tt class="docutils literal"><span class="pre">ap-&gt;init</span> <span class="pre">=</span> <span class="pre">ap-&gt;alloc</span></tt> and then check to see
if the allocation point has been <em>trapped</em>: that is, if the garbage
collector might have moved some objects since the new block was
reserved. The garbage collector traps an allocation point by setting
<tt class="docutils literal"><span class="pre">ap-&gt;limit</span> <span class="pre">=</span> <span class="pre">0</span></tt>, so if this case is found, then the reserved block
may have been invalidated, and must be discarded and re-reserved, and
the buffer must be refilled. The function <a class="reference internal" href="#mps_ap_trip" title="mps_ap_trip"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_trip()</span></tt></a>
determines whether or not this case applies, returning true if the
block is valid, false if not.</p>
<p>The <em>commit</em> operation thus looks like this:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">ap</span><span class="o">-&gt;</span><span class="n">init</span> <span class="o">=</span> <span class="n">ap</span><span class="o">-&gt;</span><span class="n">alloc</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ap</span><span class="o">-&gt;</span><span class="n">limit</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">mps_ap_trip</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">size</span><span class="p">))</span> <span class="p">{</span>
<span class="cm">/* p is invalid */</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="cm">/* p is valid */</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The critical path here consists of a store and a branch (and again,
branch prediction should work well since the test almost never fails).</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">Normally the client program would use <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a> to
perform this operation, as described above, rather than directly
accessing the fields of the allocation point structure. But direct
access is supported by the MPS.</p>
</div>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">The commit operation relies on atomic ordered access to words in
memory to detect a <a class="reference internal" href="../glossary/f.html#term-flip"><em class="xref std std-term">flip</em></a> that occurs between the assignment
<tt class="docutils literal"><span class="pre">ap-&gt;init</span> <span class="pre">=</span> <span class="pre">ap-&gt;alloc</span></tt> and the test <tt class="docutils literal"><span class="pre">ap-&gt;limit</span> <span class="pre">==</span> <span class="pre">0</span></tt>. A
compiler or processor that reordered these two instructions would
break the protocol. On some processor architectures and some
compilers, it may be necessary to insert a memory barrier
instruction at this point.</p>
</div>
<dl class="type">
<dt id="mps_ap_s">
<tt class="descname">mps_ap_s</tt><a class="headerlink" href="#mps_ap_s" title="Permalink to this definition"></a></dt>
<dd><p>The type of the structure used to represent <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation
points</em></a>:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">typedef</span> <span class="k">struct</span> <span class="n">mps_ap_s</span> <span class="p">{</span>
<span class="n">mps_addr_t</span> <span class="n">init</span><span class="p">;</span>
<span class="n">mps_addr_t</span> <span class="n">alloc</span><span class="p">;</span>
<span class="n">mps_addr_t</span> <span class="n">limit</span><span class="p">;</span>
<span class="cm">/* ... private fields ... */</span>
<span class="p">}</span> <span class="n">mps_ap_s</span><span class="p">;</span>
</pre></div>
</div>
<p><tt class="docutils literal"><span class="pre">init</span></tt> is the limit of initialized memory.</p>
<p><tt class="docutils literal"><span class="pre">alloc</span></tt> is the limit of allocated memory.</p>
<p><tt class="docutils literal"><span class="pre">limit</span></tt> is the limit of available memory.</p>
<p>An allocation point is an interface to a <a class="reference internal" href="../glossary/p.html#term-pool"><em class="xref std std-term">pool</em></a> which
provides very fast allocation, and defers the need for
synchronization in a multi-threaded environment.</p>
<p>Create an allocation point for a pool by calling
<a class="reference internal" href="#mps_ap_create_k" title="mps_ap_create_k"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_create_k()</span></tt></a>, and allocate memory via one by calling
<a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a> and <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>.</p>
</dd></dl>
<dl class="function">
<dt id="mps_ap_fill">
<a class="reference internal" href="error.html#mps_res_t" title="mps_res_t">mps_res_t</a> <tt class="descname">mps_ap_fill</tt><big>(</big><a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;*p_o</em>, <a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;ap</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#mps_ap_fill" title="Permalink to this definition"></a></dt>
<dd><p>Reserve a <a class="reference internal" href="../glossary/b.html#term-block"><em class="xref std std-term">block</em></a> of memory on an <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation point</em></a>
when the allocation point has insufficient space.</p>
<p><a class="reference internal" href="#mps_ap_fill" title="mps_ap_fill"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_fill()</span></tt></a> has same interface as <a class="reference internal" href="#mps_reserve" title="mps_reserve"><tt class="xref c c-func docutils literal"><span class="pre">mps_reserve()</span></tt></a>.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last"><a class="reference internal" href="#mps_ap_fill" title="mps_ap_fill"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_fill()</span></tt></a> must only be called according to the
<a class="reference internal" href="#topic-allocation-point-protocol"><em>Allocation point protocol</em></a>.</p>
</div>
</dd></dl>
<dl class="function">
<dt id="mps_ap_trip">
<a class="reference internal" href="interface.html#mps_bool_t" title="mps_bool_t">mps_bool_t</a> <tt class="descname">mps_ap_trip</tt><big>(</big><a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em>&nbsp;ap</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em>&nbsp;p</em>, size_t<em>&nbsp;size</em><big>)</big><a class="headerlink" href="#mps_ap_trip" title="Permalink to this definition"></a></dt>
<dd><p>Test whether a reserved block was successfully <a class="reference internal" href="../glossary/c.html#term-committed-2"><em class="xref std std-term">committed<sup>(2)</sup></em></a> when an <a class="reference internal" href="../glossary/a.html#term-allocation-point"><em class="xref std std-term">allocation point</em></a> was trapped.</p>
<p><a class="reference internal" href="#mps_ap_trip" title="mps_ap_trip"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_trip()</span></tt></a> has the same interface as <a class="reference internal" href="#mps_commit" title="mps_commit"><tt class="xref c c-func docutils literal"><span class="pre">mps_commit()</span></tt></a>.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last"><a class="reference internal" href="#mps_ap_trip" title="mps_ap_trip"><tt class="xref c c-func docutils literal"><span class="pre">mps_ap_trip()</span></tt></a> must only be called according to the
<a class="reference internal" href="#topic-allocation-point-protocol"><em>Allocation point protocol</em></a>.</p>
</div>
</dd></dl>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/logo.png" alt="Logo"/>
</a></p>
<h3><a href="../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">6. Allocation</a><ul>
<li><a class="reference internal" href="#manual-allocation">6.1. Manual allocation</a></li>
<li><a class="reference internal" href="#allocation-points">6.2. Allocation points</a></li>
<li><a class="reference internal" href="#allocation-point-protocol">6.3. Allocation point protocol</a></li>
<li><a class="reference internal" href="#example-allocating-a-symbol">6.4. Example: allocating a symbol</a></li>
<li><a class="reference internal" href="#cautions">6.5. Cautions</a></li>
<li><a class="reference internal" href="#example-inserting-into-a-doubly-linked-list">6.6. Example: inserting into a doubly linked list</a></li>
<li><a class="reference internal" href="#allocation-point-implementation">6.7. Allocation point implementation</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="pool.html"
title="previous chapter">5. Pools</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="format.html"
title="next chapter">7. Object formats</a></p><h4>Downloads</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/release/1.111.0/">MPS Kit release 1.111.0</a><br>
<a href="http://www.ravenbrook.com/project/mps/release/">All MPS Kit releases</a>
</p>
<h4>Issues</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/issue/?action=list&amp;view=status%3dopen&amp;display=Job:Priority:Title&amp;sort=Priority">Known issues</a><br>
<a href="http://www.ravenbrook.com/project/mps/issue/?action=fixed&release_fixed=1.111.0">Issues fixed in release 1.111.0</a>
</p><h4>Contact us</h4>
<p class="topless"><a href="mailto:mps-questions@ravenbrook.com">mps-questions@ravenbrook.com</a></p>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="format.html" title="7. Object formats"
>next</a> |</li>
<li class="right" >
<a href="pool.html" title="5. Pools"
>previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" >Reference</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2013, Ravenbrook Limited.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>