QLOCK(9)                                                 QLOCK(9)

          qlock, qunlock, canqlock, rlock, runlock, wlock, wunlock -
          serial synchronisation

          typedef struct
               Lock use;           /* to access Qlock structure */
               Proc *head;         /* next process waiting for object */
               Proc *tail;         /* last process waiting for object */
               int  locked;        /* flag */
          } QLock;

          typedef struct
               Lock      use;
               Proc      *head;    /* list of waiting processes */
               Proc      *tail;
               uintptr   wpc;      /* pc of writer */
               Proc      *wproc;   /* writing proc */
               int       readers;  /* number of readers */
               int       writer;   /* number of writers */
          } RWlock;

          void eqlock(QLock *l)

          void qlock(QLock *l)

          void qunlock(QLock *l)

          int  canqlock(QLock *l)

          void rlock(RWlock *l)

          void runlock(RWlock *l)

          int  canrlock(RWlock *l)

          void wlock(RWlock *l)

          void wunlock(RWlock *l)

          The primitive locking functions described in lock(9) guaran-
          tee mutual exclusion, but they implement spin locks, and
          should not be used if the process might sleep(9) within a
          critical section.  The following functions serialise access
          to a resource by forming an orderly queue of processes.

          Each resource to be controlled is given an associated QLock

     Page 1                       Plan 9             (printed 4/23/24)

     QLOCK(9)                                                 QLOCK(9)

          structure; it is usually most straightforward to put the
          QLock in the structure that represents the resource.  It
          must be initialised to zero before use (as guaranteed for
          global variables and for structures allocated by malloc).

          On return from qlock, the process has acquired the lock l,
          and can assume exclusive access to the associated resource.
          If the lock is not immediately available, the requesting
          process is placed on a FIFO queue of processes that have
          requested the lock.  Processes on this list are blocked in
          the `Queueing' state.

          Eqlock is an interruptible form of qlock.

          Qunlock unlocks l and schedules the first process queued for
          it (if any).

          Canqlock is a non-blocking form of qlock. It tries to obtain
          the lock l and returns true if successful, and 0 otherwise;
          it always returns immediately.

          RWlock is a form of lock for resources that have distinct
          readers and writers.  It allows concurrent readers but gives
          each writer exclusive access.  A caller announces its read
          or write intentions by choice of lock (and unlock) function;
          the system assumes the caller will not modify a structure
          accessed under read lock.

          Rlock acquires l for reading.  The holder can read but
          agrees not to modify the resource.  There may be several
          concurrent readers.  Canrlock is non-blocking: it returns
          non-zero if it successfully acquired the lock immediately,
          and 0 if the resource was unavailable.

          Runlock returns a read lock; the last reader out enables the
          first writer waiting (if any).

          Wlock acquires a write lock.  The holder of such a lock may
          assume exclusive access to the resource, and is allowed to
          modify it.

          Wunlock returns a write lock.  The next pending process,
          whether reader or writer, is scheduled.


          lock(9), malloc(9), splhi(9)

     Page 2                       Plan 9             (printed 4/23/24)