xref: /dflybsd-src/share/man/man9/token.9 (revision abdf9ff7ecf1197b8e86f424661a8cf30d024863)
13afb2937SSascha Wildner.\"
23afb2937SSascha Wildner.\" Copyright (c) 2010 The DragonFly Project.  All rights reserved.
33afb2937SSascha Wildner.\"
43afb2937SSascha Wildner.\" This code is derived from software contributed to The DragonFly Project
53afb2937SSascha Wildner.\" by Venkatesh Srinivas <me@endeavour.zapto.org>.
63afb2937SSascha Wildner.\"
73afb2937SSascha Wildner.\" Redistribution and use in source and binary forms, with or without
83afb2937SSascha Wildner.\" modification, are permitted provided that the following conditions
93afb2937SSascha Wildner.\" are met:
103afb2937SSascha Wildner.\"
113afb2937SSascha Wildner.\" 1. Redistributions of source code must retain the above copyright
123afb2937SSascha Wildner.\"    notice, this list of conditions and the following disclaimer.
133afb2937SSascha Wildner.\" 2. Redistributions in binary form must reproduce the above copyright
143afb2937SSascha Wildner.\"    notice, this list of conditions and the following disclaimer in
153afb2937SSascha Wildner.\"    the documentation and/or other materials provided with the
163afb2937SSascha Wildner.\"    distribution.
173afb2937SSascha Wildner.\" 3. Neither the name of The DragonFly Project nor the names of its
183afb2937SSascha Wildner.\"    contributors may be used to endorse or promote products derived
193afb2937SSascha Wildner.\"    from this software without specific, prior written permission.
203afb2937SSascha Wildner.\"
213afb2937SSascha Wildner.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
223afb2937SSascha Wildner.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
233afb2937SSascha Wildner.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
243afb2937SSascha Wildner.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
253afb2937SSascha Wildner.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
263afb2937SSascha Wildner.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
273afb2937SSascha Wildner.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
283afb2937SSascha Wildner.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
293afb2937SSascha Wildner.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
303afb2937SSascha Wildner.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
313afb2937SSascha Wildner.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
323afb2937SSascha Wildner.\" SUCH DAMAGE.
333afb2937SSascha Wildner.\"
34*abdf9ff7SSascha Wildner.Dd January 30, 2012
353afb2937SSascha Wildner.Dt TOKEN 9
36fb5b3747SSascha Wildner.Os
373afb2937SSascha Wildner.Sh NAME
383afb2937SSascha Wildner.Nm lwkt_token_init ,
393afb2937SSascha Wildner.Nm lwkt_token_uninit ,
403afb2937SSascha Wildner.Nm lwkt_gettoken ,
413afb2937SSascha Wildner.Nm lwkt_trytoken ,
423afb2937SSascha Wildner.Nm lwkt_reltoken ,
433afb2937SSascha Wildner.Nm lwkt_token_pool_lookup ,
44ccfda945SVenkatesh Srinivas.Nm lwkt_getpooltoken ,
459254ffb1SSascha Wildner.\".Nm lwkt_relpooltoken ,
468e9c3bf6SSascha Wildner.Nm lwkt_token_swap
473afb2937SSascha Wildner.Nd soft token locks
483afb2937SSascha Wildner.Sh SYNOPSIS
493afb2937SSascha Wildner.In sys/thread.h
503afb2937SSascha Wildner.Ft void
51fffd28f3SVenkatesh Srinivas.Fn lwkt_token_init "struct lwkt_token *tok" "char *desc"
523afb2937SSascha Wildner.Ft void
533afb2937SSascha Wildner.Fn lwkt_token_uninit "struct lwkt_token *tok"
543afb2937SSascha Wildner.Ft void
55a4212b42SNicolas Thery.Fn lwkt_gettoken "struct lwkt_token *tok"
563afb2937SSascha Wildner.Ft int
57a4212b42SNicolas Thery.Fn lwkt_trytoken "struct lwkt_token *tok"
583afb2937SSascha Wildner.Ft void
59a4212b42SNicolas Thery.Fn lwkt_reltoken "struct lwkt_token *tok"
603afb2937SSascha Wildner.Ft struct lwkt_token *
613afb2937SSascha Wildner.Fn lwkt_token_pool_lookup "void *ptr"
62a4212b42SNicolas Thery.Ft struct lwkt_token *
63a4212b42SNicolas Thery.Fn lwkt_getpooltoken "void *ptr"
64ccfda945SVenkatesh Srinivas.Ft void
6580921833SVenkatesh Srinivas.Fn lwkt_gettoken_shared "struct lwkt_token *tok"
6680921833SVenkatesh Srinivas.Ft void
678e9c3bf6SSascha Wildner.Fn lwkt_token_swap "void"
683afb2937SSascha Wildner.Sh DESCRIPTION
693afb2937SSascha WildnerA soft token is a lock which is only held while a thread is running.
703afb2937SSascha WildnerIf a thread explicitly blocks, all its tokens are released, and reacquired
713afb2937SSascha Wildnerwhen the thread resumes.
723afb2937SSascha WildnerWhile a thread blocks, the conditions protected by a soft token
733afb2937SSascha Wildnermay change and may need to be reevaluated on wakeup.
743afb2937SSascha Wildner.Pp
753afb2937SSascha WildnerTokens may be taken recursively.
763afb2937SSascha WildnerHowever, tokens must be released in the reverse order they were acquired.
773afb2937SSascha Wildner.Pp
7880921833SVenkatesh SrinivasTokens may be acquired in shared mode, allowing multiple concurrent holders,
7980921833SVenkatesh Srinivasvia
8080921833SVenkatesh Srinivas.Fn lwkt_gettoken_shared ,
8180921833SVenkatesh Srinivasor in exclusive mode, allowing only one holder, via
8280921833SVenkatesh Srinivas.Fn lwkt_gettoken .
8380921833SVenkatesh SrinivasIt is safe to acquire a token shared while holding it exclusively.
8480921833SVenkatesh SrinivasA thread attempting to acquire a token exclusively after holding it shared
8580921833SVenkatesh Srinivaswill deadlock.
8680921833SVenkatesh Srinivas.Pp
873afb2937SSascha WildnerThe pool token interface exists to allow using tokens with data structures
883afb2937SSascha Wildnerwhich may be deallocated.
893afb2937SSascha WildnerIt allows getting a token reference from an address, which
903afb2937SSascha Wildneris implemented by a set of statically allocated tokens and a hash function.
913afb2937SSascha Wildner.Pp
92*abdf9ff7SSascha WildnerIt is not recommended to take pool tokens in shared mode.
93*abdf9ff7SSascha WildnerA hash collision
9480921833SVenkatesh Srinivasfrom a subsequent exclusive pool token request will hit the
9580921833SVenkatesh Srinivasexclusive-after-shared deadlock.
9680921833SVenkatesh Srinivas.Pp
973afb2937SSascha WildnerThe
983afb2937SSascha Wildner.Fn lwkt_token_init
998e9c3bf6SSascha Wildnerfunction is called to initialize a token.
1008e9c3bf6SSascha WildnerThe
101fffd28f3SVenkatesh Srinivas.Fa desc
102fffd28f3SVenkatesh Srinivasargument specifies the wait string displayed when waiting for the token.
1033afb2937SSascha WildnerThe
1043afb2937SSascha Wildner.Fn lwkt_token_uninit
1053afb2937SSascha Wildnerfunction is called to de-initialize one.
1063afb2937SSascha WildnerBefore using a token, it must be initialized.
1073afb2937SSascha Wildner.Pp
1083afb2937SSascha WildnerThe
1093afb2937SSascha Wildner.Fn lwkt_gettoken
110a4212b42SNicolas Theryfunction attempts to acquire a token.
1113afb2937SSascha WildnerIf it is unsuccessful, the calling thread blocks.
1123afb2937SSascha WildnerThe
1133afb2937SSascha Wildner.Fn lwkt_trytoken
114a4212b42SNicolas Therydoes the same thing; however, if it cannot acquire the token, it returns 0
115a4212b42SNicolas Theryinstead of blocking.
1163afb2937SSascha WildnerThe
1173afb2937SSascha Wildner.Fn lwkt_reltoken
118a4212b42SNicolas Theryfunction releases a previously acquired soft token.
1193afb2937SSascha Wildner.Pp
1203afb2937SSascha WildnerThe
1213afb2937SSascha Wildner.Fn lwkt_token_pool_lookup
1223afb2937SSascha Wildnerfunction takes an address and maps it to one of a number of statically
1233afb2937SSascha Wildnerallocated tokens.
1243afb2937SSascha WildnerThe
1253afb2937SSascha Wildner.Fn lwkt_getpooltoken
1263afb2937SSascha Wildnerfunction acquires a token associated with an address.
1273afb2937SSascha WildnerUse these two functions when tokens must protect a data structure,
1283afb2937SSascha Wildnerbut the structure can be deallocated.
1293afb2937SSascha WildnerPool tokens do not need to be initialized.
130ccfda945SVenkatesh Srinivas.Pp
131ccfda945SVenkatesh SrinivasThe
132ccfda945SVenkatesh Srinivas.Fn lwkt_token_swap
133ccfda945SVenkatesh Srinivasfunction swaps the two most recently acquired tokens; this allows release of
1348e9c3bf6SSascha Wildnertokens out-of-order.
1358e9c3bf6SSascha WildnerThis function should not be called when less than two tokens are held.
1363afb2937SSascha Wildner.Sh EXAMPLES
1373afb2937SSascha WildnerA simple example of using a token to protect access to a data structure:
1383afb2937SSascha Wildner.Bd -literal
1393afb2937SSascha Wildner/* Data structure to be protected */
1403afb2937SSascha Wildnerstruct protected_data {
1413afb2937SSascha Wildner	struct lwkt_token tok;
1423afb2937SSascha Wildner	int data;
1433afb2937SSascha Wildner};
1443afb2937SSascha Wildner
1453afb2937SSascha Wildnerstruct protected_data pdata;
1463afb2937SSascha Wildner
1473afb2937SSascha Wildner/* Called early in boot */
1483afb2937SSascha Wildnervoid
1493afb2937SSascha Wildnerinit(void)
1503afb2937SSascha Wildner{
151fffd28f3SVenkatesh Srinivas	lwkt_token_init(&pdata.tok, "example");
1523afb2937SSascha Wildner	pdata.data = 0;
1533afb2937SSascha Wildner}
1543afb2937SSascha Wildner
1553afb2937SSascha Wildner/*
1563afb2937SSascha Wildner * A silly kthread; it uses a token to protect pdata.data.
1573afb2937SSascha Wildner */
1583afb2937SSascha Wildnervoid
1593afb2937SSascha Wildnerkthread1(void)
1603afb2937SSascha Wildner{
1613afb2937SSascha Wildner	int local;
1623afb2937SSascha Wildner
1633afb2937SSascha Wildner	/*
164a4212b42SNicolas Thery	 * Get the soft token.
1653afb2937SSascha Wildner	 */
166a4212b42SNicolas Thery	lwkt_gettoken(&pdata.tok);
1673afb2937SSascha Wildner	for (;;) {
1683afb2937SSascha Wildner		local = pdata.data++;
1693afb2937SSascha Wildner		tsleep(pdata, 0, "sleep", 0);
1703afb2937SSascha Wildner		/*
1713afb2937SSascha Wildner		 * While we are asleep, we do not hold the token. When we
1723afb2937SSascha Wildner		 * awake here, we will hold the token again, but we may not
1733afb2937SSascha Wildner		 * depend on local reflecting pdata.data.
1743afb2937SSascha Wildner		 */
1753afb2937SSascha Wildner
1763afb2937SSascha Wildner		local = pdata.data;
1773afb2937SSascha Wildner		if (local == 4)
1783afb2937SSascha Wildner			break;
1793afb2937SSascha Wildner	}
1803afb2937SSascha Wildner	/*
181a4212b42SNicolas Thery	 * Release the token.
1823afb2937SSascha Wildner	 */
183a4212b42SNicolas Thery	lwkt_reltoken(&pdata.tok);
1843afb2937SSascha Wildner}
1853afb2937SSascha Wildner.Ed
1863afb2937SSascha Wildner.Pp
1873afb2937SSascha WildnerAn example using pool tokens:
1883afb2937SSascha Wildner.Bd -literal
1893afb2937SSascha Wildnerstruct dynamic_data {
1903afb2937SSascha Wildner	int ref;
1913afb2937SSascha Wildner};
1923afb2937SSascha Wildner
1933afb2937SSascha Wildner/*
1943afb2937SSascha Wildner * Use a token to protect a reference count in a dynamic structure.
1953afb2937SSascha Wildner * Embedding a token in the structure would be inappropriate, since
1963afb2937SSascha Wildner * another thread may attempt to take the token after we have freed
1973afb2937SSascha Wildner * the object but before we have removed all external references to it.
1983afb2937SSascha Wildner */
1993afb2937SSascha Wildnervoid
2003afb2937SSascha Wildnerkfunction(struct dynamic_data *dynptr)
2013afb2937SSascha Wildner{
202a4212b42SNicolas Thery	struct lwkt_token *tok;
2033afb2937SSascha Wildner
2043afb2937SSascha Wildner	/*
2053afb2937SSascha Wildner	 * Get a token from the associated with the address of dynptr
2063afb2937SSascha Wildner	 */
207a4212b42SNicolas Thery	tok = lwkt_getpooltoken(dynptr);
2083afb2937SSascha Wildner	dynptr->ref--;
2093afb2937SSascha Wildner	if (dynptr->ref == 0)
2103afb2937SSascha Wildner		free(dynptr);
2113afb2937SSascha Wildner
2123afb2937SSascha Wildner	/*
2133afb2937SSascha Wildner	 * Release the token via its reference, as above
2143afb2937SSascha Wildner	 */
215a4212b42SNicolas Thery	lwkt_reltoken(tok);
2163afb2937SSascha Wildner}
2173afb2937SSascha Wildner.Ed
2183afb2937SSascha Wildner.Sh NOTES
2193afb2937SSascha WildnerSoft tokens are not released when a thread is preempted; they are only released
2203afb2937SSascha Wildnerwhen a thread explicitly blocks, such as via
2213afb2937SSascha Wildner.Fn tsleep
2223afb2937SSascha Wildneror
2233afb2937SSascha Wildner.Fn lwkt_switch .
2243afb2937SSascha Wildner.Pp
2253afb2937SSascha WildnerIf
2263afb2937SSascha Wildner.Fn lwkt_gettoken
2273afb2937SSascha Wildnerblocks while attempting to acquire a token, all currently-held tokens will
2283afb2937SSascha Wildnerbe released till a thread can acquire all of them again.
2293afb2937SSascha Wildner.Pp
2303afb2937SSascha WildnerWhen tokens are held and
2313afb2937SSascha Wildner.Fn tsleep_interlock
2323afb2937SSascha Wildneris used, tokens are not released until blocking happens - that is until the
2333afb2937SSascha Wildner.Fn tsleep
2343afb2937SSascha Wildnerpaired with the
2353afb2937SSascha Wildner.Fn tsleep_interlock
2363afb2937SSascha Wildneris called.
2373afb2937SSascha Wildner.Sh FILES
2383afb2937SSascha WildnerThe LWKT Token implementation is in
2393afb2937SSascha Wildner.Pa /sys/kern/lwkt_token.c .
2403afb2937SSascha Wildner.Sh SEE ALSO
2413afb2937SSascha Wildner.Xr crit_enter 9 ,
2423afb2937SSascha Wildner.Xr lockmgr 9 ,
2433afb2937SSascha Wildner.Xr serializer 9 ,
2443afb2937SSascha Wildner.Xr sleep 9 ,
2453afb2937SSascha Wildner.Xr spinlock 9
2463afb2937SSascha Wildner.Sh HISTORY
2473afb2937SSascha WildnerLWKT tokens first appeared in
2483afb2937SSascha Wildner.Dx 1.0 .
24980921833SVenkatesh SrinivasShared tokens first appeared in
25080921833SVenkatesh Srinivas.Dx 2.11 .
2513afb2937SSascha Wildner.Sh AUTHORS
2523afb2937SSascha WildnerThe
2533afb2937SSascha Wildner.Nm token
2543afb2937SSascha Wildnerimplementation was written by
2553afb2937SSascha Wildner.An Matthew Dillon .
256