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