summaryrefslogtreecommitdiff
path: root/static/freebsd/man9/epoch.9 4.html
diff options
context:
space:
mode:
Diffstat (limited to 'static/freebsd/man9/epoch.9 4.html')
-rw-r--r--static/freebsd/man9/epoch.9 4.html284
1 files changed, 0 insertions, 284 deletions
diff --git a/static/freebsd/man9/epoch.9 4.html b/static/freebsd/man9/epoch.9 4.html
deleted file mode 100644
index eb84213b..00000000
--- a/static/freebsd/man9/epoch.9 4.html
+++ /dev/null
@@ -1,284 +0,0 @@
-<table class="head">
- <tr>
- <td class="head-ltitle">EPOCH(9)</td>
- <td class="head-vol">Kernel Developer's Manual</td>
- <td class="head-rtitle">EPOCH(9)</td>
- </tr>
-</table>
-<div class="manual-text">
-<section class="Sh">
-<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
-<p class="Pp"><code class="Nm">epoch</code>,
- <code class="Nm">epoch_context</code>, <code class="Nm">epoch_alloc</code>,
- <code class="Nm">epoch_free</code>, <code class="Nm">epoch_enter</code>,
- <code class="Nm">epoch_exit</code>, <code class="Nm">epoch_wait</code>,
- <code class="Nm">epoch_enter_preempt</code>,
- <code class="Nm">epoch_exit_preempt</code>,
- <code class="Nm">epoch_wait_preempt</code>,
- <code class="Nm">epoch_call</code>,
- <code class="Nm">epoch_drain_callbacks</code>,
- <code class="Nm">in_epoch</code>, <code class="Nm">in_epoch_verbose</code>
- &#x2014; <span class="Nd">kernel epoch based reclamation</span></p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
-<p class="Pp"><code class="In">#include
- &lt;<a class="In">sys/param.h</a>&gt;</code>
- <br/>
- <code class="In">#include &lt;<a class="In">sys/proc.h</a>&gt;</code>
- <br/>
- <code class="In">#include &lt;<a class="In">sys/epoch.h</a>&gt;</code></p>
-<div class="Bd Pp Li">
-<pre>struct epoch; /* Opaque */</pre>
-</div>
-<br/>
-<var class="Vt">typedef struct epoch *epoch_t</var>;
-<div class="Bd Pp Li">
-<pre>struct epoch_context {
- void *data[2];
-};</pre>
-</div>
-<br/>
-<var class="Vt">typedef struct epoch_context *epoch_context_t</var>;
-<br/>
-<var class="Vt">typedef void epoch_callback_t(epoch_context_t)</var>;
-<div class="Bd Pp Li">
-<pre>struct epoch_tracker; /* Opaque */</pre>
-</div>
-<br/>
-<var class="Vt">typedef struct epoch_tracker *epoch_tracker_t</var>;
-<p class="Pp"><var class="Ft">epoch_t</var>
- <br/>
- <code class="Fn">epoch_alloc</code>(<var class="Fa" style="white-space: nowrap;">const
- char *name</var>, <var class="Fa" style="white-space: nowrap;">int
- flags</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_free</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_enter</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_exit</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_wait</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_enter_preempt</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>, <var class="Fa" style="white-space: nowrap;">epoch_tracker_t
- et</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_exit_preempt</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>, <var class="Fa" style="white-space: nowrap;">epoch_tracker_t
- et</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_wait_preempt</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_call</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>, <var class="Fa" style="white-space: nowrap;">epoch_callback_t
- callback</var>, <var class="Fa" style="white-space: nowrap;">epoch_context_t
- ctx</var>);</p>
-<p class="Pp"><var class="Ft">void</var>
- <br/>
- <code class="Fn">epoch_drain_callbacks</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">int</var>
- <br/>
- <code class="Fn">in_epoch</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>);</p>
-<p class="Pp"><var class="Ft">int</var>
- <br/>
- <code class="Fn">in_epoch_verbose</code>(<var class="Fa" style="white-space: nowrap;">epoch_t
- epoch</var>, <var class="Fa" style="white-space: nowrap;">int
- dump_onfail</var>);</p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
-<p class="Pp">Epochs are used to guarantee liveness and immutability of data by
- deferring reclamation and mutation until a grace period has elapsed. Epochs
- do not have any lock ordering issues. Entering and leaving an epoch section
- will never block.</p>
-<p class="Pp" id="epoch_alloc">Epochs are allocated with
- <a class="permalink" href="#epoch_alloc"><code class="Fn">epoch_alloc</code></a>().
- The <var class="Fa">name</var> argument is used for debugging convenience
- when the <code class="Cd">EPOCH_TRACE</code> kernel option is configured. By
- default, epochs do not allow preemption during sections. By default mutexes
- cannot be held across
- <a class="permalink" href="#epoch_wait_preempt"><code class="Fn" id="epoch_wait_preempt">epoch_wait_preempt</code></a>().
- The <var class="Fa">flags</var> specified are formed by
- <a class="permalink" href="#OR"><i class="Em" id="OR">OR</i></a>'ing the
- following values:</p>
-<div class="Bd-indent">
-<dl class="Bl-tag">
- <dt id="EPOCH_LOCKED"><a class="permalink" href="#EPOCH_LOCKED"><code class="Dv">EPOCH_LOCKED</code></a></dt>
- <dd>Permit holding mutexes across <code class="Fn">epoch_wait_preempt</code>()
- (requires <code class="Dv">EPOCH_PREEMPT</code>). When doing this one must
- be cautious of creating a situation where a deadlock is possible.</dd>
- <dt id="EPOCH_PREEMPT"><a class="permalink" href="#EPOCH_PREEMPT"><code class="Dv">EPOCH_PREEMPT</code></a></dt>
- <dd>The <var class="Vt">epoch</var> will allow preemption during sections.
- Only non-sleepable locks may be acquired during a preemptible epoch. The
- functions <code class="Fn">epoch_enter_preempt</code>(),
- <code class="Fn">epoch_exit_preempt</code>(), and
- <code class="Fn">epoch_wait_preempt</code>() must be used in place of
- <code class="Fn">epoch_enter</code>(),
- <code class="Fn">epoch_exit</code>(), and
- <code class="Fn">epoch_wait</code>(), respectively.</dd>
-</dl>
-</div>
-<p class="Pp" id="epoch_free"><var class="Vt">epoch</var>s are freed with
- <a class="permalink" href="#epoch_free"><code class="Fn">epoch_free</code></a>().</p>
-<p class="Pp" id="epoch_enter">Threads indicate the start of an epoch critical
- section by calling
- <a class="permalink" href="#epoch_enter"><code class="Fn">epoch_enter</code></a>()
- (or
- <a class="permalink" href="#epoch_enter_preempt"><code class="Fn" id="epoch_enter_preempt">epoch_enter_preempt</code></a>()
- for preemptible epochs). Threads call
- <a class="permalink" href="#epoch_exit"><code class="Fn" id="epoch_exit">epoch_exit</code></a>()
- (or
- <a class="permalink" href="#epoch_exit_preempt"><code class="Fn" id="epoch_exit_preempt">epoch_exit_preempt</code></a>()
- for preemptible epochs) to indicate the end of a critical section.
- <var class="Vt">struct epoch_tracker</var>s are stack objects whose pointers
- are passed to <code class="Fn">epoch_enter_preempt</code>() and
- <code class="Fn">epoch_exit_preempt</code>() (much like
- <var class="Vt">struct rm_priotracker</var>).</p>
-<p class="Pp" id="epoch_call">Threads can defer work until a grace period has
- expired since any thread has entered the epoch either synchronously or
- asynchronously.
- <a class="permalink" href="#epoch_call"><code class="Fn">epoch_call</code></a>()
- defers work asynchronously by invoking the provided
- <var class="Fa">callback</var> at a later time.
- <code class="Fn">epoch_wait</code>() (or
- <code class="Fn">epoch_wait_preempt</code>()) blocks the current thread
- until the grace period has expired and the work can be done safely.</p>
-<p class="Pp" id="epoch_wait">Default, non-preemptible epoch wait
- (<a class="permalink" href="#epoch_wait"><code class="Fn">epoch_wait</code></a>())
- is guaranteed to have much shorter completion times relative to preemptible
- epoch wait
- (<a class="permalink" href="#epoch_wait_preempt~2"><code class="Fn" id="epoch_wait_preempt~2">epoch_wait_preempt</code></a>()).
- (In the default type, none of the threads in an epoch section will be
- preempted before completing its section.)</p>
-<p class="Pp" id="in_epoch">INVARIANTS can assert that a thread is in an epoch
- by using
- <a class="permalink" href="#in_epoch"><code class="Fn">in_epoch</code></a>().
- <code class="Fn">in_epoch</code>(<var class="Fa">epoch</var>) is equivalent
- to invoking
- <a class="permalink" href="#in_epoch_verbose"><code class="Fn" id="in_epoch_verbose">in_epoch_verbose</code></a>(<var class="Fa">epoch</var>,
- <var class="Fa">0</var>). If <code class="Cd">EPOCH_TRACE</code> is enabled,
- <code class="Fn">in_epoch_verbose</code>(<var class="Fa">epoch</var>,
- <var class="Fa">1</var>) provides additional verbose debugging
- information.</p>
-<p class="Pp" id="epoch_wait~2">The epoch API currently does not support
- sleeping in epoch_preempt sections. A caller should never call
- <a class="permalink" href="#epoch_wait~2"><code class="Fn">epoch_wait</code></a>()
- in the middle of an epoch section for the same epoch as this will lead to a
- deadlock.</p>
-<p class="Pp" id="epoch_drain_callbacks">The
- <a class="permalink" href="#epoch_drain_callbacks"><code class="Fn">epoch_drain_callbacks</code></a>()
- function is used to drain all pending callbacks which have been invoked by
- prior <code class="Fn">epoch_call</code>() function calls on the same epoch.
- This function is useful when there are shared memory structure(s) referred
- to by the epoch callback(s) which are not refcounted and are rarely freed.
- The typical place for calling this function is right before freeing or
- invalidating the shared resource(s) used by the epoch callback(s). This
- function can sleep and is not optimized for performance.</p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN
- VALUES</a></h1>
-<p class="Pp"><code class="Fn">in_epoch</code>(<var class="Fa">curepoch</var>)
- will return 1 if curthread is in curepoch, 0 otherwise.</p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
-<p class="Pp">Async free example: Thread 1:</p>
-<div class="Bd Pp Li">
-<pre>int
-in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_laddr *laddr,
- struct ucred *cred)
-{
- /* ... */
- epoch_enter(net_epoch);
- CK_STAILQ_FOREACH(ifa, &amp;ifp-&gt;if_addrhead, ifa_link) {
- sa = ifa-&gt;ifa_addr;
- if (sa-&gt;sa_family != AF_INET)
- continue;
- sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &amp;sin-&gt;sin_addr) == 0) {
- ia = (struct in_ifaddr *)ifa;
- break;
- }
- }
- epoch_exit(net_epoch);
- /* ... */
-}</pre>
-</div>
-Thread 2:
-<div class="Bd Pp Li">
-<pre>void
-ifa_free(struct ifaddr *ifa)
-{
-
- if (refcount_release(&amp;ifa-&gt;ifa_refcnt))
- epoch_call(net_epoch, ifa_destroy, &amp;ifa-&gt;ifa_epoch_ctx);
-}
-
-void
-if_purgeaddrs(struct ifnet *ifp)
-{
-
- /* .... *
- IF_ADDR_WLOCK(ifp);
- CK_STAILQ_REMOVE(&amp;ifp-&gt;if_addrhead, ifa, ifaddr, ifa_link);
- IF_ADDR_WUNLOCK(ifp);
- ifa_free(ifa);
-}</pre>
-</div>
-<p class="Pp">Thread 1 traverses the ifaddr list in an epoch. Thread 2 unlinks
- with the corresponding epoch safe macro, marks as logically free, and then
- defers deletion. More general mutation or a synchronous free would have to
- follow a call to <code class="Fn">epoch_wait</code>().</p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
- ALSO</a></h1>
-<p class="Pp"><a class="Xr">callout(9)</a>, <a class="Xr">locking(9)</a>,
- <a class="Xr">mtx_pool(9)</a>, <a class="Xr">mutex(9)</a>,
- <a class="Xr">rwlock(9)</a>, <a class="Xr">sema(9)</a>,
- <a class="Xr">sleep(9)</a>, <a class="Xr">sx(9)</a></p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
-<p class="Pp">The <code class="Nm">epoch</code> framework first appeared in
- <span class="Ux">FreeBSD 11.0</span>.</p>
-</section>
-<section class="Sh">
-<h1 class="Sh" id="CAVEATS"><a class="permalink" href="#CAVEATS">CAVEATS</a></h1>
-<p class="Pp">One must be cautious when using
- <code class="Fn">epoch_wait_preempt</code>(). Threads are pinned during
- epoch sections, so if a thread in a section is then preempted by a higher
- priority compute bound thread on that CPU, it can be prevented from leaving
- the section indefinitely.</p>
-<p class="Pp">Epochs are not a straight replacement for read locks. Callers must
- use safe list and tailq traversal routines in an epoch (see ck_queue). When
- modifying a list referenced from an epoch section safe removal routines must
- be used and the caller can no longer modify a list entry in place. An item
- to be modified must be handled with copy on write and frees must be deferred
- until after a grace period has elapsed.</p>
-</section>
-</div>
-<table class="foot">
- <tr>
- <td class="foot-date">March 25, 2024</td>
- <td class="foot-os">FreeBSD 15.0</td>
- </tr>
-</table>