Implement TLS support, tls manual pages, and link the umtx and tls manual
[dragonfly.git] / lib / libc / sys / umtx.2
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.2 2005/02/21 21:41:01 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
50 The
51 .Fn umtx_sleep
52 system call will put the calling process to sleep for
53 .Fa timeout
54 microseconds if the contents of the specified point matches 
55 the specified value.
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
59 .Fn umtx_wakeup .
60 In particular, while it is possible for two userland threads to race, one
61 going to sleep simultaniously with another releasing the mutex, this condition
62 is caught when the second userland thread calls
63 .Fn umtx_wakeup
64 after releasing the contended mutex.
65 The
66 .Fa timeout
67 is limited to the range 0-1000000 microseconds.
68 .Pp
69 The
70 .Fn umtx_wakeup
71 system call will wakeup the specified number of processes sleeping
72 in
73 .Fn umtx_sleep
74 on the specified user address.  A count of 0 will wake up all sleeping
75 processes.  This function may wake up more processes then the specified
76 count but will never wake up fewer processes (unless there are simply not
77 that many currently sleeping on the address).  The current DragonFly
78 implementation optimized the count = 1 case but otherwise just wakes up
79 all processes sleeping on the address.
80 .Pp
81 Kernel support for userland mutexes is based on the physical memory backing
82 the user address.  Two userland programs may use this facility through
83 .Fn mmap ,
84 .Fn sysv ,
85 and
86 .Fn rfork
87 based shared memory.  It is important to note that the kernel does not
88 take responsibility for adjusting the contents of the mutex or for the
89 userland implementation of the mutex.
90 .Sh RETURN VALUES
91 .Fn umtx_sleep
92 will return 0 if it successfully slept and was then woken up.  Otherwise
93 it will return -1 and set
94 .Li errno
95 as shown below.
96 .Pp
97 .Fn umtx_wakeup
98 will generally return 0 unless the address is bad. 
99 .Sh ERRORS
100 .Bl -tag -width Er
101 .It Bq Er EBUSY
102 The contents of
103 .Fa *ptr
104 did not match
105 .Fa value
106 .It Bq Er ETIMEDOUT
107 The specified timeout occured.
108 .It Bq Er EINTR
109 The
110 .Fn umtx_sleep
111 call was interrupted by a signal.
112 .It Bq Er EINVAL
113 An invalid parameter (typically an invalid timeout) was specified.
114 .Sh EXAMPLE
115 .Bd -literal -compact
116
117 void
118 userland_get_mutex(struct umtx *mtx)
119 {
120     int v;
121
122     for (;;) {
123         v = mtx->lock;
124         if ((v & MTX_LOCKED) == 0) {
125             /*
126              * not locked, attempt to lock.
127              */
128             if (cmp_and_exg(&mtx->lock, v, v | MTX_LOCKED) == 0)
129                 return;
130         } else {
131             /*
132              * Locked, bump the contested count and obtain the contested
133              * mutex.
134              */
135             if (cmp_and_exg(&mtx->lock, v, v + 1) == 0) {
136                 userland_get_mutex_contested(mtx);
137                 return;
138             }
139         }
140     }
141 }
142
143 static void
144 userland_get_mutex_contested(struct umtx *mtx)
145 {
146     int v;
147
148     for (;;) {
149         v = mtx->lock;
150         assert(v & ~MTX_LOCKED);        /* our contesting count still there */
151         if ((v & MTX_LOCKED) == 0) {
152             /*
153              * not locked, attempt to remove our contested count and
154              * lock at the same time.
155              */
156             if (cmp_and_exg(&mtx->lock, v, (v - 1) | MTX_LOCKED) == 0)
157                 return;
158         } else {
159             /*
160              * Still locked, sleep and try again.
161              */
162             umtx_sleep(&mtx->lock, v, 0);
163             /*
164              * XXX note: if we are woken up here but do not proceed to
165              * attempt to obtain the mutex, we should chain the 
166              * umtx_wakeup() along.
167              */
168         }
169     }
170 }
171
172 void
173 userland_rel_mutex(struct umtx *mtx)
174 {
175     int v;
176
177     for (;;) {
178         v = mtx->lock;
179         assert(v & MTX_LOCKED); /* we still have it locked */
180         if (v == MTX_LOCKED) {
181             /*
182              * We hold an uncontested lock, try to set to an unlocked
183              * state.
184              */
185             if (cmp_and_exg(&mtx->lock, MTX_LOCKED, 0) == 0)
186                 return;
187         } else {
188             /*
189              * We hold a contested lock, unlock and wakeup exactly
190              * one sleeper.  It is possible for this to race a new
191              * thread obtaining a lock, in which case any contested
192              * sleeper we wake up will simply go back to sleep.
193              */
194             if (cmp_and_exg(&mtx->lock, v, v & ~MTX_LOCKED) == 0) {
195                 umtx_wakeup(&mtx->lock, 1);
196                 return;
197             }
198         }
199     }
200 }
201 .Ed
202
203 .Sh SEE ALSO
204 .Xr tls 2  
205
206 .Sh HISTORY
207 The
208 .Fn umtx_sleep ,
209 and
210 .Fn umtx_wakeup
211 function calls first appeared in DragonFly 1.1 .