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