tlock.3 - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
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 
    14 #include 
    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 
    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.