Blob


1 .TH LOCK 3
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 (3)).
84 The thread library replaces the
85 .IR rendezvous (3)
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 .PP
189 .B Ref
190 contains a
191 .B long
192 that can be incremented and decremented atomically:
193 .I Incref
194 increments the
195 .I Ref
196 in one atomic operation.
197 .I Decref
198 atomically decrements the
199 .B Ref
200 and returns zero if the resulting value is zero, non-zero otherwise.
201 .SH SOURCE
202 .B /usr/local/plan9/src/libc/port/lock.c
203 .br
204 .B /usr/local/plan9/src/libc/9sys/qlock.c
205 .br
206 .B /usr/local/plan9/src/libthread/ref.c
207 .SH SEE ALSO
208 .I rfork
209 in
210 .IR fork (3)
211 .SH BUGS
212 .B Locks
213 are not strictly spin locks.
214 After each unsuccessful attempt,
215 .I lock
216 calls
217 .B sleep(0)
218 to yield the CPU; this handles the common case
219 where some other process holds the lock.
220 After a thousand unsuccessful attempts,
221 .I lock
222 sleeps for 100ms between attempts.
223 Another another thousand unsuccessful attempts,
224 .I lock
225 sleeps for a full second between attempts.
226 .B Locks
227 are not intended to be held for long periods of time.
228 The 100ms and full second sleeps are only heuristics to
229 avoid tying up the CPU when a process deadlocks.
230 As discussed above,
231 if a lock is to be held for much more than a few instructions,
232 the queueing lock types should be almost always be used.