2 .\" Copyright (c) 2010 The DragonFly Project. All rights reserved.
4 .\" This code is derived from software contributed to The DragonFly Project
5 .\" by Venkatesh Srinivas <me@endeavour.zapto.org>.
7 .\" Redistribution and use in source and binary forms, with or without
8 .\" modification, are permitted provided that the following conditions
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
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.
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
39 .Nm lwkt_token_uninit ,
43 .Nm lwkt_token_pool_lookup ,
44 .Nm lwkt_getpooltoken ,
45 .\".Nm lwkt_relpooltoken ,
51 .Fn lwkt_token_init "struct lwkt_token *tok" "const char *desc"
53 .Fn lwkt_token_uninit "struct lwkt_token *tok"
55 .Fn lwkt_gettoken "struct lwkt_token *tok"
57 .Fn lwkt_trytoken "struct lwkt_token *tok"
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"
65 .Fn lwkt_gettoken_shared "struct lwkt_token *tok"
67 .Fn lwkt_token_swap "void"
69 A soft token is a lock which is only held while a thread is running.
70 If a thread explicitly blocks, all its tokens are released, and reacquired
71 when the thread resumes.
72 While a thread blocks, the conditions protected by a soft token
73 may change and may need to be reevaluated on wakeup.
75 Tokens may be taken recursively.
76 However, tokens must be released in the reverse order they were acquired.
78 Tokens may be acquired in shared mode, allowing multiple concurrent holders,
80 .Fn lwkt_gettoken_shared ,
81 or in exclusive mode, allowing only one holder, via
83 It is safe to acquire a token shared while holding it exclusively.
84 A thread attempting to acquire a token exclusively after holding it shared
87 The pool token interface exists to allow using tokens with data structures
88 which may be deallocated.
89 It allows getting a token reference from an address, which
90 is implemented by a set of statically allocated tokens and a hash function.
92 It is not recommended to take pool tokens in shared mode.
94 from a subsequent exclusive pool token request will hit the
95 exclusive-after-shared deadlock.
99 function is called to initialize a token.
102 argument specifies the wait string displayed when waiting for the token.
104 .Fn lwkt_token_uninit
105 function is called to de-initialize one.
106 Before using a token, it must be initialized.
110 function attempts to acquire a token.
111 If it is unsuccessful, the calling thread blocks.
114 does the same thing; however, if it cannot acquire the token, it returns 0
118 function releases a previously acquired soft token.
121 .Fn lwkt_token_pool_lookup
122 function takes an address and maps it to one of a number of statically
125 .Fn lwkt_getpooltoken
126 function acquires a token associated with an address.
127 Use these two functions when tokens must protect a data structure,
128 but the structure can be deallocated.
129 Pool tokens do not need to be initialized.
133 function swaps the two most recently acquired tokens; this allows release of
135 This function should not be called when less than two tokens are held.
137 The LWKT Token implementation is in
138 .Pa /sys/kern/lwkt_token.c .
140 A simple example of using a token to protect access to a data structure:
142 /* Data structure to be protected */
143 struct protected_data {
144 struct lwkt_token tok;
148 struct protected_data pdata;
150 /* Called early in boot */
154 lwkt_token_init(&pdata.tok, "example");
159 * A silly kthread; it uses a token to protect pdata.data.
167 * Get the soft token.
169 lwkt_gettoken(&pdata.tok);
171 local = pdata.data++;
172 tsleep(pdata, 0, "sleep", 0);
174 * While we are asleep, we do not hold the token. When we
175 * awake here, we will hold the token again, but we may not
176 * depend on local reflecting pdata.data.
186 lwkt_reltoken(&pdata.tok);
190 An example using pool tokens:
192 struct dynamic_data {
197 * Use a token to protect a reference count in a dynamic structure.
198 * Embedding a token in the structure would be inappropriate, since
199 * another thread may attempt to take the token after we have freed
200 * the object but before we have removed all external references to it.
203 kfunction(struct dynamic_data *dynptr)
205 struct lwkt_token *tok;
208 * Get a token from the associated with the address of dynptr
210 tok = lwkt_getpooltoken(dynptr);
212 if (dynptr->ref == 0)
216 * Release the token via its reference, as above
222 Soft tokens are not released when a thread is preempted; they are only released
223 when a thread explicitly blocks, such as via
230 blocks while attempting to acquire a token, all currently-held tokens will
231 be released till a thread can acquire all of them again.
233 When tokens are held and
235 is used, tokens are not released until blocking happens - that is until the
247 LWKT tokens first appeared in
249 Shared tokens first appeared in
254 implementation was written by