summaryrefslogtreecommitdiff
path: root/static/freebsd/man9/epoch.9 4.html
blob: eb84213baac0e5da15a4f2e0c62b6e2fc003a700 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
<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>