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