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
|
<table class="head">
<tr>
<td class="head-ltitle">MTX_POOL(9)</td>
<td class="head-vol">Kernel Developer's Manual</td>
<td class="head-rtitle">MTX_POOL(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">mtx_pool</code>,
<code class="Nm">mtx_pool_alloc</code>,
<code class="Nm">mtx_pool_find</code>,
<code class="Nm">mtx_pool_lock</code>,
<code class="Nm">mtx_pool_lock_spin</code>,
<code class="Nm">mtx_pool_unlock</code>,
<code class="Nm">mtx_pool_unlock_spin</code>,
<code class="Nm">mtx_pool_create</code>,
<code class="Nm">mtx_pool_destroy</code> — <span class="Nd">mutex
pool routines</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/lock.h</a>></code>
<br/>
<code class="In">#include <<a class="In">sys/mutex.h</a>></code></p>
<p class="Pp"><var class="Ft">struct mtx *</var>
<br/>
<code class="Fn">mtx_pool_alloc</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool *pool</var>);</p>
<p class="Pp"><var class="Ft">struct mtx *</var>
<br/>
<code class="Fn">mtx_pool_find</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool *pool</var>, <var class="Fa" style="white-space: nowrap;">void
*ptr</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">mtx_pool_lock</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool *pool</var>, <var class="Fa" style="white-space: nowrap;">void
*ptr</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">mtx_pool_lock_spin</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool *pool</var>, <var class="Fa" style="white-space: nowrap;">void
*ptr</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">mtx_pool_unlock</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool *pool</var>, <var class="Fa" style="white-space: nowrap;">void
*ptr</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">mtx_pool_unlock_spin</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool *pool</var>, <var class="Fa" style="white-space: nowrap;">void
*ptr</var>);</p>
<p class="Pp"><var class="Ft">struct mtx_pool *</var>
<br/>
<code class="Fn">mtx_pool_create</code>(<var class="Fa" style="white-space: nowrap;">const
char *mtx_name</var>, <var class="Fa" style="white-space: nowrap;">int
pool_size</var>, <var class="Fa" style="white-space: nowrap;">int
opts</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">mtx_pool_destroy</code>(<var class="Fa" style="white-space: nowrap;">struct
mtx_pool **poolp</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">Mutex pools are designed to be used as short term leaf mutexes;
i.e., the last mutex one might acquire before calling
<a class="Xr">mtx_sleep(9)</a>. They operate using a shared pool of mutexes.
A mutex may be chosen from the pool based on a supplied pointer, which may
or may not point to anything valid, or the caller may allocate an arbitrary
shared mutex from the pool and save the returned mutex pointer for later
use.</p>
<p class="Pp">The shared mutexes in the <var class="Va">mtxpool_sleep</var>
mutex pool, which is created by default, are standard, non-recursive,
blockable mutexes, and should only be used in appropriate situations. The
mutexes in the <var class="Va">mtxpool_lockbuilder</var> mutex pool are
similar, except that they are initialized with the MTX_NOWITNESS flag so
that they may be used to build higher-level locks. Other mutex pools may be
created that contain mutexes with different properties, such as spin
mutexes.</p>
<p class="Pp">The caller can lock and unlock mutexes returned by the pool
routines, but since the mutexes are shared, the caller should not attempt to
destroy them or modify their characteristics. While pool mutexes are
normally leaf mutexes (meaning that one cannot depend on any ordering
guarantees after obtaining one), one can still obtain other mutexes under
carefully controlled circumstances. Specifically, if one has a private mutex
(one that was allocated and initialized by the caller), one can obtain it
after obtaining a pool mutex if ordering issues are carefully accounted for.
In these cases the private mutex winds up being the true leaf mutex.</p>
<p class="Pp">Pool mutexes have the following advantages:</p>
<p class="Pp"></p>
<ol class="Bl-enum Bd-indent Bl-compact">
<li>No structural overhead; i.e., they can be associated with a structure
without adding bloat to it.</li>
<li>Mutexes can be obtained for invalid pointers, which is useful when one
uses mutexes to interlock destructor operations.</li>
<li>No initialization or destruction overhead.</li>
<li>Can be used with <a class="Xr">mtx_sleep(9)</a>.</li>
</ol>
<p class="Pp">And the following disadvantages:</p>
<p class="Pp"></p>
<ol class="Bl-enum Bd-indent Bl-compact">
<li>Should generally only be used as leaf mutexes.</li>
<li>Pool/pool dependency ordering cannot be guaranteed.</li>
<li>Possible L1 cache mastership contention between CPUs.</li>
</ol>
<p class="Pp" id="mtx_pool_alloc"><a class="permalink" href="#mtx_pool_alloc"><code class="Fn">mtx_pool_alloc</code></a>()
obtains a shared mutex from the specified pool. This routine uses a simple
rover to choose one of the shared mutexes managed by the
<code class="Nm">mtx_pool</code> subsystem.</p>
<p class="Pp" id="mtx_pool_find"><a class="permalink" href="#mtx_pool_find"><code class="Fn">mtx_pool_find</code></a>()
returns the shared mutex associated with the specified address. This routine
will create a hash out of the pointer passed into it and will choose a
shared mutex from the specified pool based on that hash. The pointer does
not need to point to anything real.</p>
<p class="Pp" id="mtx_pool_lock"><a class="permalink" href="#mtx_pool_lock"><code class="Fn">mtx_pool_lock</code></a>(),
<a class="permalink" href="#mtx_pool_lock_spin"><code class="Fn" id="mtx_pool_lock_spin">mtx_pool_lock_spin</code></a>(),
<a class="permalink" href="#mtx_pool_unlock"><code class="Fn" id="mtx_pool_unlock">mtx_pool_unlock</code></a>(),
and
<a class="permalink" href="#mtx_pool_unlock_spin"><code class="Fn" id="mtx_pool_unlock_spin">mtx_pool_unlock_spin</code></a>()
lock and unlock the shared mutex from the specified pool associated with the
specified address; they are a combination of
<code class="Fn">mtx_pool_find</code>() and <a class="Xr">mtx_lock(9)</a>,
<a class="Xr">mtx_lock_spin(9)</a>, <a class="Xr">mtx_unlock(9)</a>, and
<a class="Xr">mtx_unlock_spin(9)</a>, respectively. Since these routines
must first find the mutex to operate on, they are not as fast as directly
using the mutex pointer returned by a previous invocation of
<code class="Fn">mtx_pool_find</code>() or
<code class="Fn">mtx_pool_alloc</code>().</p>
<p class="Pp" id="mtx_pool_create"><a class="permalink" href="#mtx_pool_create"><code class="Fn">mtx_pool_create</code></a>()
allocates and initializes a new mutex pool of the specified size. The pool
size must be a power of two. The <var class="Fa">opts</var> argument is
passed to <a class="Xr">mtx_init(9)</a> to set the options for each mutex in
the pool.</p>
<p class="Pp" id="mtx_pool_destroy"><a class="permalink" href="#mtx_pool_destroy"><code class="Fn">mtx_pool_destroy</code></a>()
calls <a class="Xr">mtx_destroy(9)</a> on each mutex in the specified pool,
deallocates the memory associated with the pool, and assigns NULL to the
pool pointer.</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">locking(9)</a>, <a class="Xr">mutex(9)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<p class="Pp">These routines first appeared in <span class="Ux">FreeBSD
5.0</span>.</p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">February 6, 2010</td>
<td class="foot-os">FreeBSD 15.0</td>
</tr>
</table>
|