1.\" Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. 2.\" 3.\" This code is derived from software contributed to The DragonFly Project 4.\" by Matthew Dillon <dillon@backplane.com> 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 10.\" 1. Redistributions of source code must retain the above copyright 11.\" notice, this list of conditions and the following disclaimer. 12.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" notice, this list of conditions and the following disclaimer in 14.\" the documentation and/or other materials provided with the 15.\" distribution. 16.\" 3. Neither the name of The DragonFly Project nor the names of its 17.\" contributors may be used to endorse or promote products derived 18.\" from this software without specific, prior written permission. 19.\" 20.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" SUCH DAMAGE. 32.\" 33.\" $DragonFly: src/lib/libc/sys/umtx.2,v 1.6 2005/12/10 00:22:28 swildner Exp $ 34.\" 35.Dd February 21, 2005 36.Dt UMTX 2 37.Os 38.Sh NAME 39.Nm umtx_sleep , 40.Nm umtx_wakeup 41.Nd kernel support for userland mutexes 42.Sh LIBRARY 43.Lb libc 44.Sh SYNOPSIS 45.Ft int 46.Fn umtx_sleep "const int *ptr" "int value" "int timeout" 47.Ft int 48.Fn umtx_wakeup "const int *ptr" "int count" 49.Sh DESCRIPTION 50The 51.Fn umtx_sleep 52system call will put the calling process to sleep for 53.Fa timeout 54microseconds if the contents of the specified point matches 55the specified value. 56Specifying a timeout of 0 indicates an indefinite timeout. 57The comparison is not atomic with the sleep but is properly 58interlocked against another process calling 59.Fn umtx_wakeup . 60In particular, while it is possible for two userland threads to race, one 61going to sleep simultaniously with another releasing the mutex, this condition 62is caught when the second userland thread calls 63.Fn umtx_wakeup 64after releasing the contended mutex. 65The 66.Fa timeout 67is limited to the range 0-1000000 microseconds. 68.Pp 69The 70.Fn umtx_wakeup 71system call will wakeup the specified number of processes sleeping 72in 73.Fn umtx_sleep 74on the specified user address. A count of 0 will wake up all sleeping 75processes. This function may wake up more processes then the specified 76count but will never wake up fewer processes (unless there are simply not 77that many currently sleeping on the address). The current 78.Dx 79implementation optimized the count = 1 case but otherwise just wakes up 80all processes sleeping on the address. 81.Pp 82Kernel support for userland mutexes is based on the physical memory backing 83the user address. Two userland programs may use this facility through 84.Fn mmap , 85.Fn sysv , 86and 87.Fn rfork 88based shared memory. It is important to note that the kernel does not 89take responsibility for adjusting the contents of the mutex or for the 90userland implementation of the mutex. 91.Sh RETURN VALUES 92.Fn umtx_sleep 93will return 0 if it successfully slept and was then woken up. Otherwise 94it will return -1 and set 95.Li errno 96as shown below. 97.Pp 98.Fn umtx_wakeup 99will generally return 0 unless the address is bad. 100.Sh ERRORS 101.Bl -tag -width Er 102.It Bq Er EBUSY 103The contents of 104.Fa *ptr 105did not match 106.Fa value 107.It Bq Er ETIMEDOUT 108The specified timeout occured. 109.It Bq Er EINTR 110The 111.Fn umtx_sleep 112call was interrupted by a signal. 113.It Bq Er EINVAL 114An invalid parameter (typically an invalid timeout) was specified. 115.El 116.Sh EXAMPLE 117.Bd -literal -compact 118 119void 120userland_get_mutex(struct umtx *mtx) 121{ 122 int v; 123 124 for (;;) { 125 v = mtx->lock; 126 if ((v & MTX_LOCKED) == 0) { 127 /* 128 * not locked, attempt to lock. 129 */ 130 if (cmp_and_exg(&mtx->lock, v, v | MTX_LOCKED) == 0) 131 return; 132 } else { 133 /* 134 * Locked, bump the contested count and obtain the contested 135 * mutex. 136 */ 137 if (cmp_and_exg(&mtx->lock, v, v + 1) == 0) { 138 userland_get_mutex_contested(mtx); 139 return; 140 } 141 } 142 } 143} 144 145static void 146userland_get_mutex_contested(struct umtx *mtx) 147{ 148 int v; 149 150 for (;;) { 151 v = mtx->lock; 152 assert(v & ~MTX_LOCKED); /* our contesting count still there */ 153 if ((v & MTX_LOCKED) == 0) { 154 /* 155 * not locked, attempt to remove our contested count and 156 * lock at the same time. 157 */ 158 if (cmp_and_exg(&mtx->lock, v, (v - 1) | MTX_LOCKED) == 0) 159 return; 160 } else { 161 /* 162 * Still locked, sleep and try again. 163 */ 164 umtx_sleep(&mtx->lock, v, 0); 165 /* 166 * XXX note: if we are woken up here but do not proceed to 167 * attempt to obtain the mutex, we should chain the 168 * umtx_wakeup() along. 169 */ 170 } 171 } 172} 173 174void 175userland_rel_mutex(struct umtx *mtx) 176{ 177 int v; 178 179 for (;;) { 180 v = mtx->lock; 181 assert(v & MTX_LOCKED); /* we still have it locked */ 182 if (v == MTX_LOCKED) { 183 /* 184 * We hold an uncontested lock, try to set to an unlocked 185 * state. 186 */ 187 if (cmp_and_exg(&mtx->lock, MTX_LOCKED, 0) == 0) 188 return; 189 } else { 190 /* 191 * We hold a contested lock, unlock and wakeup exactly 192 * one sleeper. It is possible for this to race a new 193 * thread obtaining a lock, in which case any contested 194 * sleeper we wake up will simply go back to sleep. 195 */ 196 if (cmp_and_exg(&mtx->lock, v, v & ~MTX_LOCKED) == 0) { 197 umtx_wakeup(&mtx->lock, 1); 198 return; 199 } 200 } 201 } 202} 203.Ed 204.Sh SEE ALSO 205.Xr tls 2 206.Sh HISTORY 207The 208.Fn umtx_sleep , 209and 210.Fn umtx_wakeup 211function calls first appeared in 212.Dx 1.1 . 213