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