4 qlock, canqlock, qunlock,
5 rlock, canrlock, runlock,
6 wlock, canwlock, wunlock,
7 rsleep, rwakeup, rwakeupall
9 \- spin locks, queueing rendezvous locks, reader-writer locks, rendezvous points, and reference counts
25 int canqlock(QLock *l)
26 void qunlock(QLock *l)
31 int canrlock(RWLock *l)
32 void runlock(RWLock *l)
37 int canwlock(RWLock *l)
38 void wunlock(RWLock *l)
42 typedef struct Rendez {
49 void rsleep(Rendez *r)
50 int rwakeup(Rendez *r)
51 int rwakeupall(Rendez *r)
68 These routines are used to synchronize processes sharing memory.
75 are different types of queueing rendezvous locks,
78 are rendezvous points.
80 Locks and rendezvous points work in regular programs as
81 well as programs that use the thread library
84 The thread library replaces the
87 with its own implementation,
88 .IR threadrendezvous ,
89 so that threads as well as processes may be synchronized by locking calls
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.
97 blocks until the lock has been obtained.
100 It tries to obtain a lock and returns a non-zero value if it
101 was successful, 0 otherwise.
106 have the same interface but are not spin locks; instead if the lock is taken
108 will suspend execution of the calling task until it is released.
112 are the more primitive lock, they have limitations; for example,
113 they cannot synchronize between tasks in the same
120 manage access to a data structure that has distinct readers and writers.
132 are the non-blocking versions.
133 There may be any number of simultaneous readers,
136 if write access is granted no one may have
137 read access until write access is released.
139 All types of lock should be initialized to all zeros before use; this
140 puts them in the unlocked state.
143 are rendezvous points. Each
149 which must be held by the callers of
157 and suspends execution of the calling task.
158 After resuming execution,
163 If any processes are sleeping on
167 it returns 1 if a process was awakened, 0 if not.
169 wakes all processes sleeping on
171 returning the number of processes awakened.
177 and do not suspend execution of the current task.
181 should be initialized to all zeros except for
183 pointer, which should point at the
192 that can be incremented and decremented atomically:
196 in one atomic operation.
198 atomically decrements the
200 and returns zero if the resulting value is zero, non-zero otherwise.
202 .B /usr/local/plan9/src/libc/port/lock.c
204 .B /usr/local/plan9/src/libc/9sys/qlock.c
206 .B /usr/local/plan9/src/libthread/ref.c
213 are not strictly spin locks.
214 After each unsuccessful attempt,
218 to yield the CPU; this handles the common case
219 where some other process holds the lock.
220 After a thousand unsuccessful attempts,
222 sleeps for 100ms between attempts.
223 Another another thousand unsuccessful attempts,
225 sleeps for a full second between attempts.
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.
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.