.\" Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. .\" .\" This code is derived from software contributed to The DragonFly Project .\" by Matthew Dillon .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in .\" the documentation and/or other materials provided with the .\" distribution. .\" 3. Neither the name of The DragonFly Project nor the names of its .\" contributors may be used to endorse or promote products derived .\" from this software without specific, prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS .\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE .\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED .\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .Dd January 15, 2015 .Dt UMTX 2 .Os .Sh NAME .Nm umtx_sleep , .Nm umtx_wakeup .Nd kernel support for userland mutexes .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In unistd.h .Ft int .Fn umtx_sleep "volatile const int *ptr" "int value" "int timeout" .Ft int .Fn umtx_wakeup "volatile const int *ptr" "int count" .Sh DESCRIPTION The .Fn umtx_sleep system call will put the calling process to sleep for .Fa timeout microseconds if the contents of the specified pointer matches the specified value. Specifying a timeout of 0 indicates an indefinite timeout. The comparison is not atomic with the sleep but is properly interlocked against another process calling .Fn umtx_wakeup . In particular, while it is possible for two userland threads to race, one going to sleep simultaneously with another releasing the mutex, this condition is caught when the second userland thread calls .Fn umtx_wakeup after releasing the contended mutex. .Pp The .Fa timeout has no specific limitation other than what fits in the signed integer. A negative timeout will return .Er EINVAL . .Pp WARNING! In order to properly interlock against .Fn fork , this function will do an atomic read-modify-write on the underlying memory by atomically adding the value 0 to it. .Pp The .Fn umtx_wakeup system call will wakeup the specified number of processes sleeping in .Fn umtx_sleep on the specified user address. A count of 0 will wake up all sleeping processes. This function may wake up more processes then the specified count but will never wake up fewer processes (unless there are simply not that many currently sleeping on the address). The current .Dx implementation optimized the count = 1 case but otherwise just wakes up all processes sleeping on the address. .Pp Kernel support for userland mutexes is based on the physical memory backing the user address. That is, the kernel will typically construct a sleep id based on the underlying physical memory address. Two userland programs may use this facility through .Fn mmap , .Fn sysv , .Fn rfork , or light weight process-based shared memory. It is important to note that the kernel does not take responsibility for adjusting the contents of the mutex or for the userland implementation of the mutex. .Pp .Fn umtx_sleep does not restart in case of a signal, even if the signal specifies that system calls should restart. .Pp Various operating system events can cause .Fn umtx_sleep to return prematurely, with the contents of the mutex unchanged relative to the compare value. Callers must be able to deal with such returns. .Sh RETURN VALUES .Fn umtx_sleep will return 0 if it successfully slept and was then woken up. Otherwise it will return -1 and set .Va errno as shown below. .Pp .Fn umtx_wakeup will generally return 0 unless the address is bad. .Sh EXAMPLES .Bd -literal -compact void userland_get_mutex(struct umtx *mtx) { int v; v = mtx->lock; for (;;) { if (v == 0) { if (atomic_fcmpset_int(&mtx->lock, &v, 1)) break; } else if (atomic_fcmpset_int(&mtx->lock, &v, 2)) { umtx_sleep(&mtx->lock, 2, 0); } } } void userland_rel_mutex(struct umtx *mtx) { int v; v = atomic_swap_int(&mtx->lock, 0); if (v == 2) umtx_wakeup(&mtx->lock, 1); } .Ed .Sh WARNINGS This function can return -1 with errno set to .Er EWOULDBLOCK early and even if no timeout is specified due to the kernel failsafe timeout activating. The caller is advised to track the timeout independently using .Fn clock_gettime . .Pp This function can return -1 with errno set to .Er EINTR and it is up to the caller to loop if the caller's own API disallows returning .Er EINTR . .Pp This function can also return -1 with errno set to .Er EBUSY due to internal kernel effects. .Pp This function can return without error when woken up via internal kernel effects and not necessarily just by a .Fn umtx_wakeup call. .Pp Because the kernel will always use the underlying physical address for its tsleep/wakeup id (e.g. which is required to properly supported memory-mapped locks shared between processes), certain actions taken by the program and/or by the kernel can disrupt synchronization between .Fn umtx_sleep and .Fn umtx_wakeup . The kernel is responsible for handling .Fn fork actions, and will typically wakeup all blocked .Fn umtx_sleep for all threads of a process upon any thread forking. However, other actions such as pagein and pageout can also desynchronize sleeps and wakeups. To deal with these actions, the kernel typically implements a failsafe timeout of around 2 seconds for .Fn umtx_sleep . To properly resynchronize the physical address, ALL threads blocking on the address should perform a modifying operation on the underlying memory before re-entering the wait state, or otherwise be willing to incur the failsafe timeout as their recovery mechanism. .Sh ERRORS .Bl -tag -width Er .It Bq Er EBUSY The contents of .Fa *ptr possibly did not match .Fa value .It Bq Er EWOULDBLOCK The specified timeout occurred, or a kernel-defined failsafe timeout occurred, or the kernel requires a retry due to a copy-on-write / fork operation. Callers should not assume that the precise requested timeout occurred when this error is returned, and this error can be returned even when no timeout is specified. .It Bq Er EINTR The .Fn umtx_sleep call was interrupted by a signal. .It Bq Er EINVAL An invalid parameter (typically an invalid timeout) was specified. .El .Sh SEE ALSO .Xr tls 2 .Sh HISTORY The .Fn umtx_sleep , and .Fn umtx_wakeup function calls first appeared in .Dx 1.1 .