xref: /dragonfly/share/man/man9/token.9 (revision e96fb831)
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
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.
84The
85.Fa desc
86argument specifies the wait string displayed when waiting for the token.
87The
88.Fn lwkt_token_uninit
89function is called to de-initialize one.
90Before using a token, it must be initialized.
91.Pp
92The
93.Fn lwkt_gettoken
94function attempts to acquire a token.
95If it is unsuccessful, the calling thread blocks.
96The
97.Fn lwkt_trytoken
98does the same thing; however, if it cannot acquire the token, it returns 0
99instead of blocking.
100The
101.Fn lwkt_reltoken
102function releases a previously acquired soft token.
103.Pp
104The
105.Fn lwkt_token_pool_lookup
106function takes an address and maps it to one of a number of statically
107allocated tokens.
108The
109.Fn lwkt_getpooltoken
110function acquires a token associated with an address.
111Use these two functions when tokens must protect a data structure,
112but the structure can be deallocated.
113Pool tokens do not need to be initialized.
114.Pp
115The
116.Fn lwkt_token_swap
117function swaps the two most recently acquired tokens; this allows release of
118tokens out-of-order.
119This function should not be called when less than two tokens are held.
120.Sh EXAMPLES
121A simple example of using a token to protect access to a data structure:
122.Bd -literal
123/* Data structure to be protected */
124struct protected_data {
125	struct lwkt_token tok;
126	int data;
127};
128
129struct protected_data pdata;
130
131/* Called early in boot */
132void
133init(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 */
142void
143kthread1(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
171An example using pool tokens:
172.Bd -literal
173struct 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 */
183void
184kfunction(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
203Soft tokens are not released when a thread is preempted; they are only released
204when a thread explicitly blocks, such as via
205.Fn tsleep
206or
207.Fn lwkt_switch .
208.Pp
209If
210.Fn lwkt_gettoken
211blocks while attempting to acquire a token, all currently-held tokens will
212be released till a thread can acquire all of them again.
213.Pp
214When tokens are held and
215.Fn tsleep_interlock
216is used, tokens are not released until blocking happens - that is until the
217.Fn tsleep
218paired with the
219.Fn tsleep_interlock
220is called.
221.Sh FILES
222The 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
231LWKT tokens first appeared in
232.Dx 1.0 .
233.Sh AUTHORS
234The
235.Nm token
236implementation was written by
237.An Matthew Dillon .
238