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