xref: /dflybsd-src/share/man/man9/token.9 (revision 573f7837675f100b586a645dc770548577358fa1)
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.\"
34abdf9ff7SSascha 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
51*573f7837SSascha Wildner.Fn lwkt_token_init "struct lwkt_token *tok" "const 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
92abdf9ff7SSascha WildnerIt is not recommended to take pool tokens in shared mode.
93abdf9ff7SSascha 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.
13618d6b65aSSascha Wildner.Sh FILES
13718d6b65aSSascha WildnerThe LWKT Token implementation is in
13818d6b65aSSascha Wildner.Pa /sys/kern/lwkt_token.c .
1393afb2937SSascha Wildner.Sh EXAMPLES
1403afb2937SSascha WildnerA simple example of using a token to protect access to a data structure:
1413afb2937SSascha Wildner.Bd -literal
1423afb2937SSascha Wildner/* Data structure to be protected */
1433afb2937SSascha Wildnerstruct protected_data {
1443afb2937SSascha Wildner	struct lwkt_token tok;
1453afb2937SSascha Wildner	int data;
1463afb2937SSascha Wildner};
1473afb2937SSascha Wildner
1483afb2937SSascha Wildnerstruct protected_data pdata;
1493afb2937SSascha Wildner
1503afb2937SSascha Wildner/* Called early in boot */
1513afb2937SSascha Wildnervoid
1523afb2937SSascha Wildnerinit(void)
1533afb2937SSascha Wildner{
154fffd28f3SVenkatesh Srinivas	lwkt_token_init(&pdata.tok, "example");
1553afb2937SSascha Wildner	pdata.data = 0;
1563afb2937SSascha Wildner}
1573afb2937SSascha Wildner
1583afb2937SSascha Wildner/*
1593afb2937SSascha Wildner * A silly kthread; it uses a token to protect pdata.data.
1603afb2937SSascha Wildner */
1613afb2937SSascha Wildnervoid
1623afb2937SSascha Wildnerkthread1(void)
1633afb2937SSascha Wildner{
1643afb2937SSascha Wildner	int local;
1653afb2937SSascha Wildner
1663afb2937SSascha Wildner	/*
167a4212b42SNicolas Thery	 * Get the soft token.
1683afb2937SSascha Wildner	 */
169a4212b42SNicolas Thery	lwkt_gettoken(&pdata.tok);
1703afb2937SSascha Wildner	for (;;) {
1713afb2937SSascha Wildner		local = pdata.data++;
1723afb2937SSascha Wildner		tsleep(pdata, 0, "sleep", 0);
1733afb2937SSascha Wildner		/*
1743afb2937SSascha Wildner		 * While we are asleep, we do not hold the token. When we
1753afb2937SSascha Wildner		 * awake here, we will hold the token again, but we may not
1763afb2937SSascha Wildner		 * depend on local reflecting pdata.data.
1773afb2937SSascha Wildner		 */
1783afb2937SSascha Wildner
1793afb2937SSascha Wildner		local = pdata.data;
1803afb2937SSascha Wildner		if (local == 4)
1813afb2937SSascha Wildner			break;
1823afb2937SSascha Wildner	}
1833afb2937SSascha Wildner	/*
184a4212b42SNicolas Thery	 * Release the token.
1853afb2937SSascha Wildner	 */
186a4212b42SNicolas Thery	lwkt_reltoken(&pdata.tok);
1873afb2937SSascha Wildner}
1883afb2937SSascha Wildner.Ed
1893afb2937SSascha Wildner.Pp
1903afb2937SSascha WildnerAn example using pool tokens:
1913afb2937SSascha Wildner.Bd -literal
1923afb2937SSascha Wildnerstruct dynamic_data {
1933afb2937SSascha Wildner	int ref;
1943afb2937SSascha Wildner};
1953afb2937SSascha Wildner
1963afb2937SSascha Wildner/*
1973afb2937SSascha Wildner * Use a token to protect a reference count in a dynamic structure.
1983afb2937SSascha Wildner * Embedding a token in the structure would be inappropriate, since
1993afb2937SSascha Wildner * another thread may attempt to take the token after we have freed
2003afb2937SSascha Wildner * the object but before we have removed all external references to it.
2013afb2937SSascha Wildner */
2023afb2937SSascha Wildnervoid
2033afb2937SSascha Wildnerkfunction(struct dynamic_data *dynptr)
2043afb2937SSascha Wildner{
205a4212b42SNicolas Thery	struct lwkt_token *tok;
2063afb2937SSascha Wildner
2073afb2937SSascha Wildner	/*
2083afb2937SSascha Wildner	 * Get a token from the associated with the address of dynptr
2093afb2937SSascha Wildner	 */
210a4212b42SNicolas Thery	tok = lwkt_getpooltoken(dynptr);
2113afb2937SSascha Wildner	dynptr->ref--;
2123afb2937SSascha Wildner	if (dynptr->ref == 0)
2133afb2937SSascha Wildner		free(dynptr);
2143afb2937SSascha Wildner
2153afb2937SSascha Wildner	/*
2163afb2937SSascha Wildner	 * Release the token via its reference, as above
2173afb2937SSascha Wildner	 */
218a4212b42SNicolas Thery	lwkt_reltoken(tok);
2193afb2937SSascha Wildner}
2203afb2937SSascha Wildner.Ed
2213afb2937SSascha Wildner.Sh NOTES
2223afb2937SSascha WildnerSoft tokens are not released when a thread is preempted; they are only released
2233afb2937SSascha Wildnerwhen a thread explicitly blocks, such as via
2243afb2937SSascha Wildner.Fn tsleep
2253afb2937SSascha Wildneror
2263afb2937SSascha Wildner.Fn lwkt_switch .
2273afb2937SSascha Wildner.Pp
2283afb2937SSascha WildnerIf
2293afb2937SSascha Wildner.Fn lwkt_gettoken
2303afb2937SSascha Wildnerblocks while attempting to acquire a token, all currently-held tokens will
2313afb2937SSascha Wildnerbe released till a thread can acquire all of them again.
2323afb2937SSascha Wildner.Pp
2333afb2937SSascha WildnerWhen tokens are held and
2343afb2937SSascha Wildner.Fn tsleep_interlock
2353afb2937SSascha Wildneris used, tokens are not released until blocking happens - that is until the
2363afb2937SSascha Wildner.Fn tsleep
2373afb2937SSascha Wildnerpaired with the
2383afb2937SSascha Wildner.Fn tsleep_interlock
2393afb2937SSascha Wildneris called.
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