]> git.lizzy.rs Git - plan9front.git/blob - sys/man/2/lock
provide procsetname(2) manpage
[plan9front.git] / sys / man / 2 / lock
1 .TH LOCK 2
2 .SH NAME
3 lock, canlock, unlock,
4 qlock, canqlock, qunlock,
5 rlock, canrlock, runlock,
6 wlock, canwlock, wunlock,
7 rsleep, rwakeup, rwakeupall,
8 incref, decref
9 \- spin locks, queueing rendezvous locks, reader-writer locks, rendezvous points, and reference counts
10 .SH SYNOPSIS
11 .ft L
12 .nf
13 #include <u.h>
14 #include <libc.h>
15 .PP
16 .ft L
17 .nf
18 void    lock(Lock *l)
19 int     canlock(Lock *l)
20 void    unlock(Lock *l)
21 .PP
22 .ft L
23 .nf
24 void    qlock(QLock *l)
25 int     canqlock(QLock *l)
26 void    qunlock(QLock *l)
27 .PP
28 .ft L
29 .nf
30 void    rlock(RWLock *l)
31 int     canrlock(RWLock *l)
32 void    runlock(RWLock *l)
33 .PP
34 .ft L
35 .nf
36 void    wlock(RWLock *l)
37 int     canwlock(RWLock *l)
38 void    wunlock(RWLock *l)
39 .PP
40 .ft L
41 .nf
42 typedef struct Rendez {
43         QLock *l;
44         \fI...\fP
45 } Rendez;
46 .PP
47 .ft L
48 .nf
49 void    rsleep(Rendez *r)
50 int     rwakeup(Rendez *r)
51 int     rwakeupall(Rendez *r)
52 .PP
53 .ft L
54 #include <thread.h>
55 .PP
56 .ft L
57 .nf
58 typedef struct Ref {
59         long ref;
60 } Ref;
61 .PP
62 .ft L
63 .nf
64 void incref(Ref*)
65 long decref(Ref*)
66 .fi
67 .SH DESCRIPTION
68 These routines are used  to synchronize processes sharing memory.
69 .PP
70 .B Locks
71 are spin locks,
72 .B QLocks
73 and
74 .B RWLocks
75 are different types of queueing rendezvous locks,
76 and
77 .B Rendezes
78 are rendezvous points.
79 .PP
80 Locks and rendezvous points work in regular programs as
81 well as programs that use the thread library
82 (see
83 .IR thread (2)).
84 The thread library replaces the
85 .IR rendezvous (2)
86 system call
87 with its own implementation,
88 .IR threadrendezvous ,
89 so that threads as well as processes may be synchronized by locking calls
90 in threaded programs.
91 .PP
92 Used carelessly, spin locks can be expensive and can easily generate deadlocks.
93 Their use is discouraged, especially in programs that use the
94 thread library because they prevent context switches between threads.
95 .PP
96 .I Lock
97 blocks until the lock has been obtained.
98 .I Canlock
99 is non-blocking.
100 It tries to obtain a lock and returns a non-zero value if it
101 was successful, 0 otherwise.
102 .I Unlock
103 releases a lock.
104 .PP
105 .B QLocks
106 have the same interface but are not spin locks; instead if the lock is taken
107 .I qlock
108 will suspend execution of the calling task until it is released.
109 .PP
110 Although
111 .B Locks
112 are the more primitive lock, they have limitations; for example,
113 they cannot synchronize between tasks in the same
114 .IR proc .
115 Use
116 .B QLocks
117 instead.
118 .PP
119 .B RWLocks
120 manage access to a data structure that has distinct readers and writers.
121 .I Rlock
122 grants read access;
123 .I runlock
124 releases it.
125 .I Wlock
126 grants write access;
127 .I wunlock
128 releases it.
129 .I Canrlock
130 and
131 .I canwlock
132 are the non-blocking versions.
133 There may be any number of simultaneous readers,
134 but only one writer.
135 Moreover,
136 if write access is granted no one may have
137 read access until write access is released.
138 .PP
139 All types of lock should be initialized to all zeros before use; this
140 puts them in the unlocked state.
141 .PP
142 .B Rendezes
143 are rendezvous points.  Each
144 .B Rendez
145 .I r
146 is protected by a
147 .B QLock
148 .IB r -> l \fR,
149 which must be held by the callers of
150 .IR rsleep ,
151 .IR rwakeup ,
152 and
153 .IR rwakeupall .
154 .I Rsleep
155 atomically releases
156 .IB r -> l
157 and suspends execution of the calling task.
158 After resuming execution,
159 .I rsleep
160 will reacquire
161 .IB r -> l
162 before returning.
163 If any processes are sleeping on
164 .IR r ,
165 .I rwakeup
166 wakes one of them.
167 it returns 1 if a process was awakened, 0 if not.
168 .I Rwakeupall
169 wakes all processes sleeping on
170 .IR r ,
171 returning the number of processes awakened.
172 .I Rwakeup
173 and
174 .I rwakeupall
175 do not release
176 .IB r -> l
177 and do not suspend execution of the current task.
178 .PP
179 Before use,
180 .B Rendezes
181 should be initialized to all zeros except for
182 .IB r -> l
183 pointer, which should point at the
184 .B QLock
185 that will guard
186 .IR r .
187 It is important that this
188 .B QLock
189 is the same one that protects the rendezvous condition; see the example.
190 .PP
191 A
192 .B Ref
193 contains a
194 .B long
195 that can be incremented and decremented atomically:
196 .I Incref
197 increments the
198 .I Ref
199 in one atomic operation.
200 .I Decref
201 atomically decrements the
202 .B Ref
203 and returns zero if the resulting value is zero, non-zero otherwise.
204 .SH EXAMPLE
205 Implement a buffered single-element channel using 
206 .I rsleep
207 and
208 .IR rwakeup :
209 .IP
210 .EX
211 .ta +4n +4n +4n
212 typedef struct Chan
213 {
214         QLock l;
215         Rendez full, empty;
216         int val, haveval;
217 } Chan;
218 .EE
219 .IP
220 .EX
221 .ta +4n +4n +4n
222 Chan*
223 mkchan(void)
224 {
225         Chan *c;
226
227         c = mallocz(sizeof *c, 1);
228         c->full.l = &c->l;
229         c->empty.l = &c->l;
230         return c;
231 }
232 .EE
233 .IP
234 .EX
235 .ta +4n +4n +4n
236 void
237 send(Chan *c, int val)
238 {
239         qlock(&c->l);
240         while(c->haveval)
241                 rsleep(&c->full);
242         c->haveval = 1;
243         c->val = val;
244         rwakeup(&c->empty);  /* no longer empty */
245         qunlock(&c->l);
246 }
247 .EE
248 .IP
249 .EX
250 .ta +4n +4n +4n
251 int
252 recv(Chan *c)
253 {
254         int v;
255
256         qlock(&c->l);
257         while(!c->haveval)
258                 rsleep(&c->empty);
259         c->haveval = 0;
260         v = c->val;
261         rwakeup(&c->full);  /* no longer full */
262         qunlock(&c->l);
263         return v;
264 }
265 .EE
266 .LP
267 Note that the 
268 .B QLock
269 protecting the
270 .B Chan
271 is the same
272 .B QLock
273 used for the 
274 .BR Rendez ;
275 this ensures that wakeups are not missed.
276 .SH SOURCE
277 .B /sys/src/libc/port/lock.c
278 .br
279 .B /sys/src/libc/9sys/qlock.c
280 .br
281 .B /sys/src/libthread/ref.c
282 .SH SEE ALSO
283 .I rfork
284 in
285 .IR fork (2)
286 .SH BUGS
287 .B Locks
288 are not strictly spin locks.
289 After each unsuccessful attempt,
290 .I lock
291 calls
292 .B sleep(0)
293 to yield the CPU; this handles the common case
294 where some other process holds the lock.
295 After a thousand unsuccessful attempts,
296 .I lock
297 sleeps for 100ms between attempts.
298 After another thousand unsuccessful attempts,
299 .I lock
300 sleeps for a full second between attempts.
301 .B Locks
302 are not intended to be held for long periods of time.
303 The 100ms and full second sleeps are only heuristics to
304 avoid tying up the CPU when a process deadlocks.
305 As discussed above,
306 if a lock is to be held for much more than a few instructions,
307 the queueing lock types should almost always be used.
308 .PP
309 It is an error for a program to
310 .I fork
311 when it holds a lock in shared memory, since this will result
312 in two processes holding the same lock at the same time,
313 which should not happen.