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>
— <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
<<a class="In">sys/param.h</a>></code>
<br/>
<code class="In">#include <<a class="In">sys/proc.h</a>></code>
<br/>
<code class="In">#include <<a class="In">sys/epoch.h</a>></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, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
if (prison_check_ip4(cred, &sin->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(&ifa->ifa_refcnt))
epoch_call(net_epoch, ifa_destroy, &ifa->ifa_epoch_ctx);
}
void
if_purgeaddrs(struct ifnet *ifp)
{
/* .... *
IF_ADDR_WLOCK(ifp);
CK_STAILQ_REMOVE(&ifp->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>
|