mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-26 07:11:34 -08:00
715 lines
No EOL
68 KiB
HTML
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 — 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> »</li>
|
|
<li><a href="index.html" accesskey="U">Reference</a> »</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> *p_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em> pool</em>, size_t<em> 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’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> pool</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em> addr</em>, size_t<em> 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’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’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> *ap_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em> pool</em>, <a class="reference internal" href="keyword.html#mps_arg_s" title="mps_arg_s">mps_arg_s</a><em> 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’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’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> *ap_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em> 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> *ap_o</em>, <a class="reference internal" href="pool.html#mps_pool_t" title="mps_pool_t">mps_pool_t</a><em> pool</em>, va_list<em> 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> 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’ <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 “in a race” 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 “lost the race”: 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’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">&</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> *p_o</em>, <a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em> ap</em>, size_t<em> 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’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> res_v</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em> *p_v</em>, <a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em> ap</em>, size_t<em> 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> ap</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em> p</em>, size_t<em> 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’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">&</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">"out of memory in make_symbol"</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">-></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">-></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">-></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’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 'obj' into the doubly-linked list after 'head' */</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">&</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">"out of memory"</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">-></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">-></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">-></span><span class="n">next</span> <span class="o">=</span> <span class="n">link</span><span class="o">-></span><span class="n">prev</span><span class="o">-></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">-></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">-></span><span class="n">next</span><span class="o">-></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">-></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->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->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">&</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">"out of memory"</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">-></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">-></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">-></span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
|
|
<span class="n">link</span><span class="o">-></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">-></span><span class="n">next</span><span class="o">-></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">-></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->alloc</span> <span class="pre">+</span> <span class="pre">size</span> <span class="pre"><=</span> <span class="pre">ap->limit</span></tt> and in the common case that it is,
|
|
it takes a copy of <tt class="docutils literal"><span class="pre">ap->init</span></tt> (which now points to the reserved
|
|
block) and sets <tt class="docutils literal"><span class="pre">ap->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->alloc</span> <span class="pre">+</span> <span class="pre">size</span> <span class="pre">></span> <span class="pre">ap->limit</span></tt>, that is, when the
|
|
new block won’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">-></span><span class="n">alloc</span> <span class="o">+</span> <span class="n">size</span> <span class="o"><=</span> <span class="n">ap</span><span class="o">-></span><span class="n">limit</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">ap</span><span class="o">-></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">-></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">&</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->init</span> <span class="pre">=</span> <span class="pre">ap->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->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">-></span><span class="n">init</span> <span class="o">=</span> <span class="n">ap</span><span class="o">-></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">-></span><span class="n">limit</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&&</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->init</span> <span class="pre">=</span> <span class="pre">ap->alloc</span></tt> and the test <tt class="docutils literal"><span class="pre">ap->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> *p_o</em>, <a class="reference internal" href="#mps_ap_t" title="mps_ap_t">mps_ap_t</a><em> ap</em>, size_t<em> 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> ap</em>, <a class="reference internal" href="interface.html#mps_addr_t" title="mps_addr_t">mps_addr_t</a><em> p</em>, size_t<em> 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&view=status%3dopen&display=Job:Priority:Title&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> »</li>
|
|
<li><a href="index.html" >Reference</a> »</li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer">
|
|
© <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> |