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