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