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 locks,
78 are rendezvous points.
80 Locks and rendezvous points have trivial implementations in programs
81 not using the thread library
84 since such programs have no concurrency.
86 Used carelessly, spin locks can be expensive and can easily generate deadlocks.
87 Their use is discouraged, especially in programs that use the
88 thread library because they prevent context switches between threads.
91 blocks until the lock has been obtained.
94 It tries to obtain a lock and returns a non-zero value if it
95 was successful, 0 otherwise.
100 have the same interface but are not spin locks; instead if the lock is taken
102 will suspend execution of the calling thread until it is released.
106 are the more primitive lock, they have limitations; for example,
107 they cannot synchronize between tasks in the same
114 manage access to a data structure that has distinct readers and writers.
126 are the non-blocking versions.
127 There may be any number of simultaneous readers,
130 if write access is granted no one may have
131 read access until write access is released.
133 All types of lock should be initialized to all zeros before use; this
134 puts them in the unlocked state.
137 are rendezvous points. Each
143 which must be held by the callers of
151 and suspends execution of the calling task.
152 After resuming execution,
157 If any processes are sleeping on
161 it returns 1 if a process was awakened, 0 if not.
163 wakes all processes sleeping on
165 returning the number of processes awakened.
171 and do not suspend execution of the current task.
175 should be initialized to all zeros except for
177 pointer, which should point at the
186 that can be incremented and decremented atomically:
190 in one atomic operation.
192 atomically decrements the
194 and returns zero if the resulting value is zero, non-zero otherwise.
196 .B \*9/src/lib9/qlock.c
201 are not always spin locks.
202 Instead they are usually implemented using the
205 .BR pthread_mutex_t ,
206 whose implementation method is not defined.
210 systems, the implementation of
213 .I pthread_mutex_destroy
215 .BR pthread_mutex_t 's.
216 This leads to resource leaks on FreeBSD 5
217 (though not on Linux 2.6, where
218 .I pthread_mutex_destroy
222 On systems that do not have a usable
226 implementation provided by
228 is still not exactly a spin lock.
229 After each unsuccessful attempt,
233 to yield the CPU; this handles the common case
234 where some other process holds the lock.
235 After a thousand unsuccessful attempts,
237 sleeps for 100ms between attempts.
238 Another another thousand unsuccessful attempts,
240 sleeps for a full second between attempts.
242 are not intended to be held for long periods of time.
243 The 100ms and full second sleeps are only heuristics to
244 avoid tying up the CPU when a process deadlocks.
246 if a lock is to be held for much more than a few instructions,
247 the queueing lock types should be almost always be used.