SEMACQUIRE(2)                                       SEMACQUIRE(2)

     NAME
          semacquire, tsemacquire, semrelease - user level semaphores

     SYNOPSIS
          #include <u.h>
          #include <libc.h>

          int semacquire(long *addr, int block);

          int tsemacquire(long *addr, ulong ms);

          long semrelease(long *addr, long count);

     DESCRIPTION
          Semacquire, tsemacquire, and semrelease facilitate schedul-
          ing between processes sharing memory.  Processes arrange to
          share memory by using rfork with the RFMEM flag (see
          fork(2)), segattach(2), or thread(2).

          The semaphore's value is the integer pointed at by addr.
          Semacquire atomically waits until the semaphore has a posi-
          tive value and then decrements that value.  If block is zero
          and the semaphore is not immediately available, semacquire
          returns 0 instead of waiting.  Tsemacquire only waits ms
          milliseconds for the semaphore to attain a positive value
          and, if available in that time, decrements that value.  It
          returns 0 otherwise.  Both functions return 1 if the sema-
          phore was acquired and -1 on error (e.g., if they were
          interrupted).  Semrelease adds count to the semaphore's
          value and returns the new value.

          Semacquire (and analogously for tsemacquire) and semrelease
          can be thought of as efficient, correct replacements for:

               int
               semacquire(long *addr, int block)
               {
                    while(*addr == 0){
                         if(!block)
                              return 0;
                         if(interrupted)
                              return -1;
                    }
                    --*addr;
                    return 1;
               }

               int
               semrelease(long *addr, int count)
               {

     SEMACQUIRE(2)                                       SEMACQUIRE(2)

                    return *addr += count;
               }

          Like rendezvous(2), semacquire, tsemacquire, and semrelease
          are not typically used directly.  Instead, they are intended
          to be used to coordinate scheduling in higher-level abstrac-
          tions such as locks, rendezvous points, and channels (see
          lock(2) and thread(2)). Also like rendezvous, semacquire,
          tsemacquire, and semrelease cannot be used to coordinate
          between threads in a single process.  Use locks, rendezvous
          points, or channels instead.

     SOURCE
          /sys/src/9/port/sysproc.c

     SEE ALSO
          fork(2), lock(2), rendezvous(2), segattach(2), thread(2)

     DIAGNOSTICS
          These functions set errstr.