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.12 2008/04/14 20:17:41 dillon 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 simultaneously with another releasing the mutex, this condition 62is caught when the second userland thread calls 63.Fn umtx_wakeup 64after releasing the contended mutex. 65.Pp 66The 67.Fa timeout 68is not specific limitation other then what fits in the signed integer. 69A negative timeout will return 70.Er EINVAL . 71.Pp 72The 73.Fn umtx_wakeup 74system call will wakeup the specified number of processes sleeping 75in 76.Fn umtx_sleep 77on the specified user address. A count of 0 will wake up all sleeping 78processes. This function may wake up more processes then the specified 79count but will never wake up fewer processes (unless there are simply not 80that many currently sleeping on the address). The current 81.Dx 82implementation optimized the count = 1 case but otherwise just wakes up 83all processes sleeping on the address. 84.Pp 85Kernel support for userland mutexes is based on the physical memory backing 86the user address. Two userland programs may use this facility through 87.Fn mmap , 88.Fn sysv , 89.Fn rfork , 90or light weight process-based shared memory. 91It is important to note that the kernel does not 92take responsibility for adjusting the contents of the mutex or for the 93userland implementation of the mutex. 94.Pp 95.Fn umtx_sleep 96does not restart in case of a signal, even if the signal specifies 97that system calls should restart. 98.Pp 99Various operating system events can cause 100.Fn umtx_sleep 101to return prematurely, with the contents of the mutex unchanged relative 102to the compare value. Callers must be able to deal with such returns. 103.Sh RETURN VALUES 104.Fn umtx_sleep 105will return 0 if it successfully slept and was then woken up. Otherwise 106it will return -1 and set 107.Va errno 108as shown below. 109.Pp 110.Fn umtx_wakeup 111will generally return 0 unless the address is bad. 112.Sh EXAMPLE 113.Bd -literal -compact 114 115void 116userland_get_mutex(struct umtx *mtx) 117{ 118 int v; 119 120 for (;;) { 121 v = mtx->lock; 122 if ((v & MTX_LOCKED) == 0) { 123 /* 124 * not locked, attempt to lock. 125 */ 126 if (cmp_and_exg(&mtx->lock, v, v | MTX_LOCKED) == 0) 127 return; 128 } else { 129 /* 130 * Locked, bump the contested count and obtain the contested 131 * mutex. 132 */ 133 if (cmp_and_exg(&mtx->lock, v, v + 1) == 0) { 134 userland_get_mutex_contested(mtx); 135 return; 136 } 137 } 138 } 139} 140 141static void 142userland_get_mutex_contested(struct umtx *mtx) 143{ 144 int v; 145 146 for (;;) { 147 v = mtx->lock; 148 assert(v & ~MTX_LOCKED); /* our contesting count still there */ 149 if ((v & MTX_LOCKED) == 0) { 150 /* 151 * not locked, attempt to remove our contested count and 152 * lock at the same time. 153 */ 154 if (cmp_and_exg(&mtx->lock, v, (v - 1) | MTX_LOCKED) == 0) 155 return; 156 } else { 157 /* 158 * Still locked, sleep and try again. 159 */ 160 umtx_sleep(&mtx->lock, v, 0); 161 /* 162 * XXX note: if we are woken up here but do not proceed to 163 * attempt to obtain the mutex, we should chain the 164 * umtx_wakeup() along. 165 */ 166 } 167 } 168} 169 170void 171userland_rel_mutex(struct umtx *mtx) 172{ 173 int v; 174 175 for (;;) { 176 v = mtx->lock; 177 assert(v & MTX_LOCKED); /* we still have it locked */ 178 if (v == MTX_LOCKED) { 179 /* 180 * We hold an uncontested lock, try to set to an unlocked 181 * state. 182 */ 183 if (cmp_and_exg(&mtx->lock, MTX_LOCKED, 0) == 0) 184 return; 185 } else { 186 /* 187 * We hold a contested lock, unlock and wakeup exactly 188 * one sleeper. It is possible for this to race a new 189 * thread obtaining a lock, in which case any contested 190 * sleeper we wake up will simply go back to sleep. 191 */ 192 if (cmp_and_exg(&mtx->lock, v, v & ~MTX_LOCKED) == 0) { 193 umtx_wakeup(&mtx->lock, 1); 194 return; 195 } 196 } 197 } 198} 199.Ed 200.Sh ERRORS 201.Bl -tag -width Er 202.It Bq Er EBUSY 203The contents of 204.Fa *ptr 205did not match 206.Fa value 207.It Bq Er EWOULDBLOCK 208The specified timeout occurred. 209.It Bq Er EINTR 210The 211.Fn umtx_sleep 212call was interrupted by a signal. 213.It Bq Er EINVAL 214An invalid parameter (typically an invalid timeout) was specified. 215.El 216.Sh SEE ALSO 217.Xr tls 2 218.Sh HISTORY 219The 220.Fn umtx_sleep , 221and 222.Fn umtx_wakeup 223function calls first appeared in 224.Dx 1.1 . 225