Merge branch 'vendor/OPENSSL'
[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 June 10, 2010
35 .Dt TOKEN 9
36 .Os
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 .\".Nm lwkt_relpooltoken ,
46 .Nm lwkt_token_swap
47 .Nd soft token locks
48 .Sh SYNOPSIS
49 .In sys/thread.h
50 .Ft void
51 .Fn lwkt_token_init "struct lwkt_token *tok" "char *desc"
52 .Ft void
53 .Fn lwkt_token_uninit "struct lwkt_token *tok"
54 .Ft void
55 .Fn lwkt_gettoken "struct lwkt_token *tok"
56 .Ft int
57 .Fn lwkt_trytoken "struct lwkt_token *tok"
58 .Ft void
59 .Fn lwkt_reltoken "struct lwkt_token *tok"
60 .Ft struct lwkt_token *
61 .Fn lwkt_token_pool_lookup "void *ptr"
62 .Ft struct lwkt_token *
63 .Fn lwkt_getpooltoken "void *ptr"
64 .Ft void
65 .Fn lwkt_token_swap "void"
66 .Sh DESCRIPTION
67 A soft token is a lock which is only held while a thread is running.
68 If a thread explicitly blocks, all its tokens are released, and reacquired
69 when the thread resumes.
70 While a thread blocks, the conditions protected by a soft token
71 may change and may need to be reevaluated on wakeup.
72 .Pp
73 Tokens may be taken recursively.
74 However, tokens must be released in the reverse order they were acquired.
75 .Pp
76 The pool token interface exists to allow using tokens with data structures
77 which may be deallocated.
78 It allows getting a token reference from an address, which
79 is implemented by a set of statically allocated tokens and a hash function.
80 .Pp
81 The
82 .Fn lwkt_token_init
83 function is called to initialize a token.
84 The
85 .Fa desc
86 argument specifies the wait string displayed when waiting for the token.
87 The
88 .Fn lwkt_token_uninit
89 function is called to de-initialize one.
90 Before using a token, it must be initialized.
91 .Pp
92 The
93 .Fn lwkt_gettoken
94 function attempts to acquire a token.
95 If it is unsuccessful, the calling thread blocks.
96 The
97 .Fn lwkt_trytoken
98 does the same thing; however, if it cannot acquire the token, it returns 0
99 instead of blocking.
100 The
101 .Fn lwkt_reltoken
102 function releases a previously acquired soft token.
103 .Pp
104 The
105 .Fn lwkt_token_pool_lookup
106 function takes an address and maps it to one of a number of statically
107 allocated tokens.
108 The
109 .Fn lwkt_getpooltoken
110 function acquires a token associated with an address.
111 Use these two functions when tokens must protect a data structure,
112 but the structure can be deallocated.
113 Pool tokens do not need to be initialized.
114 .Pp
115 The
116 .Fn lwkt_token_swap
117 function swaps the two most recently acquired tokens; this allows release of
118 tokens out-of-order.
119 This function should not be called when less than two tokens are held.
120 .Sh EXAMPLES
121 A simple example of using a token to protect access to a data structure:
122 .Bd -literal
123 /* Data structure to be protected */
124 struct protected_data {
125         struct lwkt_token tok;
126         int data;
127 };
128
129 struct protected_data pdata;
130
131 /* Called early in boot */
132 void
133 init(void)
134 {
135         lwkt_token_init(&pdata.tok, "example");
136         pdata.data = 0;
137 }
138
139 /*
140  * A silly kthread; it uses a token to protect pdata.data.
141  */
142 void
143 kthread1(void)
144 {
145         int local;
146
147         /*
148          * Get the soft token.
149          */
150         lwkt_gettoken(&pdata.tok);
151         for (;;) {
152                 local = pdata.data++;
153                 tsleep(pdata, 0, "sleep", 0);
154                 /*
155                  * While we are asleep, we do not hold the token. When we
156                  * awake here, we will hold the token again, but we may not
157                  * depend on local reflecting pdata.data.
158                  */
159
160                 local = pdata.data;
161                 if (local == 4)
162                         break;
163         }
164         /*
165          * Release the token.
166          */
167         lwkt_reltoken(&pdata.tok);
168 }
169 .Ed
170 .Pp
171 An example using pool tokens:
172 .Bd -literal
173 struct dynamic_data {
174         int ref;
175 };
176
177 /*
178  * Use a token to protect a reference count in a dynamic structure.
179  * Embedding a token in the structure would be inappropriate, since
180  * another thread may attempt to take the token after we have freed
181  * the object but before we have removed all external references to it.
182  */
183 void
184 kfunction(struct dynamic_data *dynptr)
185 {
186         struct lwkt_token *tok;
187
188         /*
189          * Get a token from the associated with the address of dynptr
190          */
191         tok = lwkt_getpooltoken(dynptr);
192         dynptr->ref--;
193         if (dynptr->ref == 0)
194                 free(dynptr);
195
196         /*
197          * Release the token via its reference, as above
198          */
199         lwkt_reltoken(tok);
200 }
201 .Ed
202 .Sh NOTES
203 Soft tokens are not released when a thread is preempted; they are only released
204 when a thread explicitly blocks, such as via
205 .Fn tsleep
206 or
207 .Fn lwkt_switch .
208 .Pp
209 If
210 .Fn lwkt_gettoken
211 blocks while attempting to acquire a token, all currently-held tokens will
212 be released till a thread can acquire all of them again.
213 .Pp
214 When tokens are held and
215 .Fn tsleep_interlock
216 is used, tokens are not released until blocking happens - that is until the
217 .Fn tsleep
218 paired with the
219 .Fn tsleep_interlock
220 is called.
221 .Sh FILES
222 The LWKT Token implementation is in
223 .Pa /sys/kern/lwkt_token.c .
224 .Sh SEE ALSO
225 .Xr crit_enter 9 ,
226 .Xr lockmgr 9 ,
227 .Xr serializer 9 ,
228 .Xr sleep 9 ,
229 .Xr spinlock 9
230 .Sh HISTORY
231 LWKT tokens first appeared in
232 .Dx 1.0 .
233 .Sh AUTHORS
234 The
235 .Nm token
236 implementation was written by
237 .An Matthew Dillon .