tlock.3 - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tlock.3 (4972B)
       ---
            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 locks,
           76 and
           77 .B Rendezes
           78 are rendezvous points.
           79 .PP
           80 Locks and rendezvous points have trivial implementations in programs
           81 not using the thread library
           82 (see
           83 .MR thread (3) ),
           84 since such programs have no concurrency.
           85 .PP
           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.
           89 .PP
           90 .I Lock
           91 blocks until the lock has been obtained.
           92 .I Canlock
           93 is non-blocking.
           94 It tries to obtain a lock and returns a non-zero value if it
           95 was successful, 0 otherwise.
           96 .I Unlock
           97 releases a lock.
           98 .PP
           99 .B QLocks
          100 have the same interface but are not spin locks; instead if the lock is taken
          101 .I qlock
          102 will suspend execution of the calling thread until it is released.
          103 .PP
          104 Although
          105 .B Locks
          106 are the more primitive lock, they have limitations; for example,
          107 they cannot synchronize between tasks in the same
          108 .IR proc .
          109 Use
          110 .B QLocks
          111 instead.
          112 .PP
          113 .B RWLocks
          114 manage access to a data structure that has distinct readers and writers.
          115 .I Rlock
          116 grants read access;
          117 .I runlock
          118 releases it.
          119 .I Wlock
          120 grants write access;
          121 .I wunlock
          122 releases it.
          123 .I Canrlock
          124 and
          125 .I canwlock
          126 are the non-blocking versions.
          127 There may be any number of simultaneous readers,
          128 but only one writer.
          129 Moreover,
          130 if write access is granted no one may have
          131 read access until write access is released.
          132 .PP
          133 All types of lock should be initialized to all zeros before use; this
          134 puts them in the unlocked state.
          135 .PP
          136 .B Rendezes
          137 are rendezvous points.  Each
          138 .B Rendez
          139 .I r
          140 is protected by a
          141 .B QLock
          142 .IB r -> l \fR,
          143 which must be held by the callers of
          144 .IR rsleep ,
          145 .IR rwakeup ,
          146 and
          147 .IR rwakeupall .
          148 .I Rsleep
          149 atomically releases
          150 .IB r -> l
          151 and suspends execution of the calling task.
          152 After resuming execution,
          153 .I rsleep
          154 will reacquire
          155 .IB r -> l
          156 before returning.
          157 If any processes are sleeping on
          158 .IR r ,
          159 .I rwakeup
          160 wakes one of them.
          161 It returns 1 if a process was awakened, 0 if not.
          162 .I Rwakeupall
          163 wakes all processes sleeping on
          164 .IR r ,
          165 returning the number of processes awakened.
          166 .I Rwakeup
          167 and
          168 .I rwakeupall
          169 do not release
          170 .IB r -> l
          171 and do not suspend execution of the current task.
          172 .PP
          173 Before use,
          174 .B Rendezes
          175 should be initialized to all zeros except for
          176 .IB r -> l
          177 pointer, which should point at the
          178 .B QLock
          179 that will guard
          180 .IR r .
          181 .PP
          182 A
          183 .B Ref
          184 contains a
          185 .B long
          186 that can be incremented and decremented atomically:
          187 .I Incref
          188 increments the
          189 .I Ref
          190 in one atomic operation.
          191 .I Decref
          192 atomically decrements the
          193 .B Ref
          194 and returns zero if the resulting value is zero, non-zero otherwise.
          195 .SH SOURCE
          196 .B \*9/src/lib9/qlock.c
          197 .br
          198 .B \*9/src/libthread
          199 .SH BUGS
          200 .B Locks
          201 are not always spin locks.
          202 Instead they are usually implemented using the 
          203 .I pthreads
          204 library's
          205 .BR pthread_mutex_t ,
          206 whose implementation method is not defined.
          207 .PP
          208 On
          209 .IR pthreads -based
          210 systems, the implementation of
          211 .B Lock
          212 never calls
          213 .I pthread_mutex_destroy
          214 to free the
          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
          219 is a no-op).
          220 .BR 
          221 .PP
          222 On systems that do not have a usable
          223 .I pthreads
          224 implementation, the
          225 .B Lock
          226 implementation provided by
          227 .I libthread
          228 is still not exactly a spin lock.
          229 After each unsuccessful attempt,
          230 .I lock
          231 calls
          232 .B sleep(0)
          233 to yield the CPU; this handles the common case
          234 where some other process holds the lock.
          235 After a thousand unsuccessful attempts,
          236 .I lock
          237 sleeps for 100ms between attempts.
          238 Another another thousand unsuccessful attempts,
          239 .I lock
          240 sleeps for a full second between attempts.
          241 .B Locks
          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.
          245 As discussed above,
          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.