.TH UPSEM 2
.SH NAME
upsem, downsem, altsems, initsem, semstats \- optimistic user level semaphores
.SH SYNOPSIS
.B #include <u.h>
.br
.B #include <libc.h>
.PP
.B
void upsem(Sem *s);
.PP
.B
int downsem(Sem *s, int block);
.PP
.B
int altsems(Sem *ss[], int n);
.PP
.B
void initsem(Sem *s, int tickets);
.PP
.B
void semstats(void)
.PP
.B extern int semtrytimes;
.SH DESCRIPTION
.IR Upsem ,
.IR downsem ,
and 
.I altsems
provide an interface for optimistic semaphores that work without entering the
kernel when they can proceed, and call the kernel only when it is really necessary
(e.g., to block or to unblock another process).
.PP
A semaphore is a struct shared among synchronizing processes.
Initialization is done by the user program by calling
.I initsem.
The parameter
.I tickets
must be a natural number. It
sets the initial state of the semaphore.
After the initialization, only the
following functions should be used to operate on the semaphore.
.PP
.I Downsem
tries to acquire one unit from the semaphore. If it can proceed, the call works without
calling the kernel. When it cannot proceed, the global
.I semtrytimes
controls for how long (how many times) the function will try to acquire without entering the
kernel, doing a busy wait.
If this fails and block is set, the kernel is
entered to block the process until a ticket can be acquired.
If block is not set, the process does not enter the kernel and the function returns 0.
When a ticket is acquired, the function returns 1.
If the system call fails, it returns a
negative value.
.PP
.I Upsem
releases one ticket. 
The call does not enter the kernel unless a process must be awaken.
.PP
.I Altsems
tries to perform a
.I downsem
in any one of the semaphores pointed to by pointers in
.I ss
(there are
.I n
entries in that array). After a busy wait determined by
.IR semtrytimes ,
if no semaphore can be acquired,
the kernel is entered and the process blocks 
until it can proceed. Otherwise, the
operation is performed without calling the kernel.
The function returns the semaphore that has been acquired.
If the operation fails, it returns a negative value.
.PP
.I Semstats
prints several statistics for debugging, and may be useful to learn if the
processes using the semaphores (any semaphore) did enter the kernel or not and
how many times they did.
.SH SOURCE
.B /sys/src/libc/9sys/upsem.c
and
.B /sys/src/9/port/syssem.c
.SH SEE ALSO
.IR fork (2),
.IR lock (2),
.IR rendezvous (2),
.IR segattach (2),
.IR thread (2),
and
.IR semacquire (2).
.SH DIAGNOSTICS
These functions set
.IR errstr .
If the semaphore's internal lock is corrupted (note that this
is indistinguishable from being extremely busy) the process
can get a suicide note.
.SH BUGS
.I Semalt
only can be used with semaphores located in the same shared segment.
