plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

lock.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.