There are two new system calls today, documented
in the man page below.  As the man page says,
they are intended as building blocks, not to be used by
regular programs.  The functionality they provide is not
far from possible to implement with rendezvous(2), but
the crucial difference is that semrelease has no qlocks
and thus is guaranteed not to block the calling process*,
making it suitable to use in real-time processes to wake
up non-real-time processes.  Sape is using this to good
effect in an internal app.

These semaphores are actually a more convenient building
block than rendezvous for implementing things like qlock,
channels, and rsleep/rwakeup.  For compatibility with
older kernels, we're leaving those alone.  Maybe in a year
or two.

See /sys/src/9/port/sysproc.c for more information.

Russ


* Of course, semrelease will block if *addr is swapped
out, but if you're using real-time processes, you're 
not swapping anyway.



     SEMACQUIRE(2)                                       SEMACQUIRE(2)

     NAME
          semacquire, semrelease - user level semaphores

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

          int semacquire(long *addr, int block);

          long semrelease(long *addr, long count);

     DESCRIPTION
          Semacquire and semrelease facilitate scheduling between pro-
          cesses 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.  It returns 1 if
          the semaphore was acquired and -1 on error (e.g., if it was
          interrupted).  If block is zero and the semaphore is not
          immediately available, semacquire returns 0 instead of wait-
          ing.  Semrelease adds count to the semaphore's value and
          returns the new value.

          Semacquire 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)
               {
                    return *addr += count;
               }

          Like rendezvous(2), semacquire and semrelease are not typi-
          cally used directly.  Instead, they are intended to be used
          to coordinate scheduling in higher-level abstractions such
          as locks, rendezvous points, and channels (see lock(2) and
          thread(2)). Also like rendezvous , semacquire 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.

Reply via email to