1 .\" Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
3 .\" This code is derived from software contributed to The DragonFly Project
4 .\" by Matthew Dillon <dillon@backplane.com>
6 .\" Redistribution and use in source and binary forms, with or without
7 .\" modification, are permitted provided that the following conditions
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
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.
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
33 .\" $DragonFly: src/lib/libc/sys/umtx.2,v 1.12 2008/04/14 20:17:41 dillon Exp $
41 .Nd kernel support for userland mutexes
46 .Fn umtx_sleep "const int *ptr" "int value" "int timeout"
48 .Fn umtx_wakeup "const int *ptr" "int count"
52 system call will put the calling process to sleep for
54 microseconds if the contents of the specified point matches
56 Specifying a timeout of 0 indicates an indefinite timeout.
57 The comparison is not atomic with the sleep but is properly
58 interlocked against another process calling
60 In particular, while it is possible for two userland threads to race, one
61 going to sleep simultaneously with another releasing the mutex, this condition
62 is caught when the second userland thread calls
64 after releasing the contended mutex.
68 is not specific limitation other than what fits in the signed integer.
69 A negative timeout will return
74 system call will wakeup the specified number of processes sleeping
77 on the specified user address. A count of 0 will wake up all sleeping
78 processes. This function may wake up more processes then the specified
79 count but will never wake up fewer processes (unless there are simply not
80 that many currently sleeping on the address). The current
82 implementation optimized the count = 1 case but otherwise just wakes up
83 all processes sleeping on the address.
85 Kernel support for userland mutexes is based on the physical memory backing
86 the user address. Two userland programs may use this facility through
90 or light weight process-based shared memory.
91 It is important to note that the kernel does not
92 take responsibility for adjusting the contents of the mutex or for the
93 userland implementation of the mutex.
96 does not restart in case of a signal, even if the signal specifies
97 that system calls should restart.
99 Various operating system events can cause
101 to return prematurely, with the contents of the mutex unchanged relative
102 to the compare value. Callers must be able to deal with such returns.
105 will return 0 if it successfully slept and was then woken up. Otherwise
106 it will return -1 and set
111 will generally return 0 unless the address is bad.
113 .Bd -literal -compact
116 userland_get_mutex(struct umtx *mtx)
122 if ((v & MTX_LOCKED) == 0) {
124 * not locked, attempt to lock.
126 if (cmp_and_exg(&mtx->lock, v, v | MTX_LOCKED) == 0)
130 * Locked, bump the contested count and obtain the contested
133 if (cmp_and_exg(&mtx->lock, v, v + 1) == 0) {
134 userland_get_mutex_contested(mtx);
142 userland_get_mutex_contested(struct umtx *mtx)
148 assert(v & ~MTX_LOCKED); /* our contesting count still there */
149 if ((v & MTX_LOCKED) == 0) {
151 * not locked, attempt to remove our contested count and
152 * lock at the same time.
154 if (cmp_and_exg(&mtx->lock, v, (v - 1) | MTX_LOCKED) == 0)
158 * Still locked, sleep and try again.
160 umtx_sleep(&mtx->lock, v, 0);
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.
171 userland_rel_mutex(struct umtx *mtx)
177 assert(v & MTX_LOCKED); /* we still have it locked */
178 if (v == MTX_LOCKED) {
180 * We hold an uncontested lock, try to set to an unlocked
183 if (cmp_and_exg(&mtx->lock, MTX_LOCKED, 0) == 0)
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.
192 if (cmp_and_exg(&mtx->lock, v, v & ~MTX_LOCKED) == 0) {
193 umtx_wakeup(&mtx->lock, 1);
207 .It Bq Er EWOULDBLOCK
208 The specified timeout occurred.
212 call was interrupted by a signal.
214 An invalid parameter (typically an invalid timeout) was specified.
223 function calls first appeared in