Merge branch 'vendor/BZIP'
[dragonfly.git] / share / man / man9 / token.9
1 .\"
2 .\" Copyright (c) 2010 The DragonFly Project.  All rights reserved.
3 .\"
4 .\" This code is derived from software contributed to The DragonFly Project
5 .\" by Venkatesh Srinivas <me@endeavour.zapto.org>.
6 .\"
7 .\" Redistribution and use in source and binary forms, with or without
8 .\" modification, are permitted provided that the following conditions
9 .\" are met:
10 .\"
11 .\" 1. Redistributions of source code must retain the above copyright
12 .\"    notice, this list of conditions and the following disclaimer.
13 .\" 2. Redistributions in binary form must reproduce the above copyright
14 .\"    notice, this list of conditions and the following disclaimer in
15 .\"    the documentation and/or other materials provided with the
16 .\"    distribution.
17 .\" 3. Neither the name of The DragonFly Project nor the names of its
18 .\"    contributors may be used to endorse or promote products derived
19 .\"    from this software without specific, prior written permission.
20 .\"
21 .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 .\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25 .\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 .\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 .\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 .\" SUCH DAMAGE.
33 .\"
34 .Dd May 31, 2010
35 .Os
36 .Dt TOKEN 9
37 .Sh NAME
38 .Nm lwkt_token_init ,
39 .Nm lwkt_token_uninit ,
40 .Nm lwkt_gettoken ,
41 .Nm lwkt_trytoken ,
42 .Nm lwkt_reltoken ,
43 .Nm lwkt_token_pool_lookup ,
44 .Nm lwkt_getpooltoken
45 .Nd soft token locks
46 .Sh SYNOPSIS
47 .In sys/thread.h
48 .Ft void
49 .Fn lwkt_token_init "struct lwkt_token *tok" "int mpsafe"
50 .Ft void
51 .Fn lwkt_token_uninit "struct lwkt_token *tok"
52 .Ft void
53 .Fn lwkt_gettoken "struct lwkt_token *tok"
54 .Ft int
55 .Fn lwkt_trytoken "struct lwkt_token *tok"
56 .Ft void
57 .Fn lwkt_reltoken "struct lwkt_token *tok"
58 .Ft struct lwkt_token *
59 .Fn lwkt_token_pool_lookup "void *ptr"
60 .Ft struct lwkt_token *
61 .Fn lwkt_getpooltoken "void *ptr"
62 .Sh DESCRIPTION
63 .Pp
64 A soft token is a lock which is only held while a thread is running.
65 If a thread explicitly blocks, all its tokens are released, and reacquired
66 when the thread resumes.
67 While a thread blocks, the conditions protected by a soft token
68 may change and may need to be reevaluated on wakeup.
69 .Pp
70 Tokens may be taken recursively.
71 However, tokens must be released in the reverse order they were acquired.
72 .Pp
73 The pool token interface exists to allow using tokens with data structures
74 which may be deallocated.
75 It allows getting a token reference from an address, which
76 is implemented by a set of statically allocated tokens and a hash function.
77 .Pp
78 The
79 .Fn lwkt_token_init
80 function is called to initialize a token.
81 If
82 .Fa mpsafe
83 is 0 the MP lock is taken before acquiring the token and released after
84 releasing the token.
85 The
86 .Fn lwkt_token_uninit
87 function is called to de-initialize one.
88 Before using a token, it must be initialized.
89 .Pp
90 The
91 .Fn lwkt_gettoken
92 function attempts to acquire a token.
93 If it is unsuccessful, the calling thread blocks.
94 The
95 .Fn lwkt_trytoken
96 does the same thing; however, if it cannot acquire the token, it returns 0
97 instead of blocking.
98 The
99 .Fn lwkt_reltoken
100 function releases a previously acquired soft token.
101 .Pp
102 The
103 .Fn lwkt_token_pool_lookup
104 function takes an address and maps it to one of a number of statically
105 allocated tokens.
106 The
107 .Fn lwkt_getpooltoken
108 function acquires a token associated with an address.
109 Use these two functions when tokens must protect a data structure,
110 but the structure can be deallocated.
111 Pool tokens do not need to be initialized.
112 .Sh EXAMPLES
113 A simple example of using a token to protect access to a data structure:
114 .Bd -literal
115 /* Data structure to be protected */
116 struct protected_data {
117         struct lwkt_token tok;
118         int data;
119 };
120
121 struct protected_data pdata;
122
123 /* Called early in boot */
124 void
125 init(void)
126 {
127         lwkt_token_init(&pdata.tok ,1);
128         pdata.data = 0;
129 }
130
131 /*
132  * A silly kthread; it uses a token to protect pdata.data.
133  */
134 void
135 kthread1(void)
136 {
137         int local;
138
139         /*
140          * Get the soft token.
141          */
142         lwkt_gettoken(&pdata.tok);
143         for (;;) {
144                 local = pdata.data++;
145                 tsleep(pdata, 0, "sleep", 0);
146                 /*
147                  * While we are asleep, we do not hold the token. When we
148                  * awake here, we will hold the token again, but we may not
149                  * depend on local reflecting pdata.data.
150                  */
151
152                 local = pdata.data;
153                 if (local == 4)
154                         break;
155         }
156         /*
157          * Release the token.
158          */
159         lwkt_reltoken(&pdata.tok);
160 }
161 .Ed
162 .Pp
163 An example using pool tokens:
164 .Bd -literal
165 struct dynamic_data {
166         int ref;
167 };
168
169 /*
170  * Use a token to protect a reference count in a dynamic structure.
171  * Embedding a token in the structure would be inappropriate, since
172  * another thread may attempt to take the token after we have freed
173  * the object but before we have removed all external references to it.
174  */
175 void
176 kfunction(struct dynamic_data *dynptr)
177 {
178         struct lwkt_token *tok;
179
180         /*
181          * Get a token from the associated with the address of dynptr
182          */
183         tok = lwkt_getpooltoken(dynptr);
184         dynptr->ref--;
185         if (dynptr->ref == 0)
186                 free(dynptr);
187
188         /*
189          * Release the token via its reference, as above
190          */
191         lwkt_reltoken(tok);
192 }
193 .Ed
194 .Sh NOTES
195 Soft tokens are not released when a thread is preempted; they are only released
196 when a thread explicitly blocks, such as via
197 .Fn tsleep
198 or
199 .Fn lwkt_switch .
200 .Pp
201 If
202 .Fn lwkt_gettoken
203 blocks while attempting to acquire a token, all currently-held tokens will
204 be released till a thread can acquire all of them again.
205 .Pp
206 When tokens are held and
207 .Fn tsleep_interlock
208 is used, tokens are not released until blocking happens - that is until the
209 .Fn tsleep
210 paired with the
211 .Fn tsleep_interlock
212 is called.
213 .Sh FILES
214 The LWKT Token implementation is in
215 .Pa /sys/kern/lwkt_token.c .
216 .Sh SEE ALSO
217 .Xr crit_enter 9 ,
218 .Xr lockmgr 9 ,
219 .Xr serializer 9 ,
220 .Xr sleep 9 ,
221 .Xr spinlock 9
222 .Sh HISTORY
223 LWKT tokens first appeared in
224 .Dx 1.0 .
225 .Sh AUTHORS
226 The
227 .Nm token
228 implementation was written by
229 .An Matthew Dillon .