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.5 2005/08/01 01:49:16 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 DragonFly 78implementation optimized the count = 1 case but otherwise just wakes up 79all processes sleeping on the address. 80.Pp 81Kernel support for userland mutexes is based on the physical memory backing 82the user address. Two userland programs may use this facility through 83.Fn mmap , 84.Fn sysv , 85and 86.Fn rfork 87based shared memory. It is important to note that the kernel does not 88take responsibility for adjusting the contents of the mutex or for the 89userland implementation of the mutex. 90.Sh RETURN VALUES 91.Fn umtx_sleep 92will return 0 if it successfully slept and was then woken up. Otherwise 93it will return -1 and set 94.Li errno 95as shown below. 96.Pp 97.Fn umtx_wakeup 98will generally return 0 unless the address is bad. 99.Sh ERRORS 100.Bl -tag -width Er 101.It Bq Er EBUSY 102The contents of 103.Fa *ptr 104did not match 105.Fa value 106.It Bq Er ETIMEDOUT 107The specified timeout occured. 108.It Bq Er EINTR 109The 110.Fn umtx_sleep 111call was interrupted by a signal. 112.It Bq Er EINVAL 113An invalid parameter (typically an invalid timeout) was specified. 114.El 115.Sh EXAMPLE 116.Bd -literal -compact 117 118void 119userland_get_mutex(struct umtx *mtx) 120{ 121 int v; 122 123 for (;;) { 124 v = mtx->lock; 125 if ((v & MTX_LOCKED) == 0) { 126 /* 127 * not locked, attempt to lock. 128 */ 129 if (cmp_and_exg(&mtx->lock, v, v | MTX_LOCKED) == 0) 130 return; 131 } else { 132 /* 133 * Locked, bump the contested count and obtain the contested 134 * mutex. 135 */ 136 if (cmp_and_exg(&mtx->lock, v, v + 1) == 0) { 137 userland_get_mutex_contested(mtx); 138 return; 139 } 140 } 141 } 142} 143 144static void 145userland_get_mutex_contested(struct umtx *mtx) 146{ 147 int v; 148 149 for (;;) { 150 v = mtx->lock; 151 assert(v & ~MTX_LOCKED); /* our contesting count still there */ 152 if ((v & MTX_LOCKED) == 0) { 153 /* 154 * not locked, attempt to remove our contested count and 155 * lock at the same time. 156 */ 157 if (cmp_and_exg(&mtx->lock, v, (v - 1) | MTX_LOCKED) == 0) 158 return; 159 } else { 160 /* 161 * Still locked, sleep and try again. 162 */ 163 umtx_sleep(&mtx->lock, v, 0); 164 /* 165 * XXX note: if we are woken up here but do not proceed to 166 * attempt to obtain the mutex, we should chain the 167 * umtx_wakeup() along. 168 */ 169 } 170 } 171} 172 173void 174userland_rel_mutex(struct umtx *mtx) 175{ 176 int v; 177 178 for (;;) { 179 v = mtx->lock; 180 assert(v & MTX_LOCKED); /* we still have it locked */ 181 if (v == MTX_LOCKED) { 182 /* 183 * We hold an uncontested lock, try to set to an unlocked 184 * state. 185 */ 186 if (cmp_and_exg(&mtx->lock, MTX_LOCKED, 0) == 0) 187 return; 188 } else { 189 /* 190 * We hold a contested lock, unlock and wakeup exactly 191 * one sleeper. It is possible for this to race a new 192 * thread obtaining a lock, in which case any contested 193 * sleeper we wake up will simply go back to sleep. 194 */ 195 if (cmp_and_exg(&mtx->lock, v, v & ~MTX_LOCKED) == 0) { 196 umtx_wakeup(&mtx->lock, 1); 197 return; 198 } 199 } 200 } 201} 202.Ed 203.Sh SEE ALSO 204.Xr tls 2 205.Sh HISTORY 206The 207.Fn umtx_sleep , 208and 209.Fn umtx_wakeup 210function calls first appeared in DragonFly 1.1 . 211