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
187 It is important that this
189 is the same one that protects the rendezvous condition; see the example.
195 that can be incremented and decremented atomically:
199 in one atomic operation.
201 atomically decrements the
203 and returns zero if the resulting value is zero, non-zero otherwise.
205 Implement a buffered single-element channel using
227 c = mallocz(sizeof *c, 1);
237 send(Chan *c, int val)
244 rwakeup(&c->empty); /* no longer empty */
261 rwakeup(&c->full); /* no longer full */
275 this ensures that wakeups are not missed.
277 .B /sys/src/libc/port/lock.c
279 .B /sys/src/libc/9sys/qlock.c
281 .B /sys/src/libthread/ref.c
288 are not strictly spin locks.
289 After each unsuccessful attempt,
293 to yield the CPU; this handles the common case
294 where some other process holds the lock.
295 After a thousand unsuccessful attempts,
297 sleeps for 100ms between attempts.
298 After another thousand unsuccessful attempts,
300 sleeps for a full second between attempts.
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.
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.
309 It is an error for a program to
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.