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