glenda.party
term% ls -F
term% cat index.txt
THREAD(2)                     System Calls Manual                    THREAD(2)

NAME
       alt,  chanclose,  chancreate,  chanfree,  chanclosing, chanprint, main‐
       stacksize, proccreate, procdata, procexec, procexecl, procrfork,  recv,
       recvp,  recvul, send, sendp, sendul, nbrecv, nbrecvp, nbrecvul, nbsend,
       nbsendp, nbsendul, threadcreate, threaddata,  threadexits,  threadexit‐
       sall, threadgetgrp, threadgetname, threadint, threadintgrp, threadkill,
       threadkillgrp,  threadmain,  threadnotify, threadid, threadpid, thread‐
       setgrp, threadsetname, threadwaitchan, yield - thread and proc  manage‐
       ment

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

       typedef enum {
           CHANEND,
           CHANSND,
           CHANRCV,
           CHANNOP,
           CHANNOBLK,
       } ChanOp;

       typedef struct Alt Alt;
       struct Alt {
           Channel *c;   /* channel */
           void    *v;   /* pointer to value */
           ChanOp  op;   /* operation */
           char    *err; /* did the op fail? */
           /*
            * the next variables are used internally to alt
            * they need not be initialized
            */
           Channel **tag;   /* pointer to rendez-vous tag */
           int     entryno; /* entry number */
       };

       void     threadmain(int argc, char *argv[])
       int      mainstacksize
       int      proccreate(void (*fn)(void*), void *arg, uint stacksize)
       int      procrfork(void (*fn)(void*), void *arg, uint stacksize,
                    int rforkflag)
       int      threadcreate(void (*fn)(void*), void *arg, uint stacksize)
       void     threadexits(char *status)
       void     threadexitsall(char *status)
       void     yield(void)
       int      threadid(void)
       int      threadgrp(void)
       int      threadsetgrp(int group)
       int      threadpid(int id)
       void     threadint(int id)
       void     threadintgrp(int group)
       void     threadkill(int id)
       void     threadkillgrp(int group)
       void     threadsetname(char *name, ...)
       char*    threadgetname(void)
       void**   threaddata(void)
       void**   procdata(void)
       Channel* chancreate(int elsize, int nel)
       void     chanfree(Channel *c)
       int      alt(Alt *alts)
       int      recv(Channel *c, void *v)
       void*    recvp(Channel *c)
       ulong    recvul(Channel *c)
       int      nbrecv(Channel *c, void *v)
       void*    nbrecvp(Channel *c)
       ulong    nbrecvul(Channel *c)
       int      send(Channel *c, void *v)
       int      sendp(Channel *c, void *v)
       int      sendul(Channel *c, ulong v)
       int      nbsend(Channel *c, void *v)
       int      nbsendp(Channel *c, void *v)
       int      nbsendul(Channel *c, ulong v)
       int      chanprint(Channel *c, char *fmt, ...)
       int      chanclose(Channel *c);
       int      chanclosing(Channel *c);
       void     procexecl(Channel *cpid, char *file, ...)
       void     procexec(Channel *cpid, char *file, char *args[])
       Channel* threadwaitchan(void)
       int      threadnotify(int (*f)(void*, char*), int in)

DESCRIPTION
       The  thread  library  provides  parallel programming support similar to
       that of the languages Alef and Newsqueak.  Threads and procs  occupy  a
       shared  address space, communicating and synchronizing through channels
       and shared variables.

       A proc is a Plan 9 process that contains  one  or  more  cooperatively-
       scheduled threads.  Programs using threads must replace main by thread‐
       main.   The thread library provides a main function that sets up a proc
       with a single thread executing threadmain on a stack of size mainstack‐
       size (default eight kilobytes).  To set mainstacksize, declare a global
       variable initialized to the desired value (e.g.,  int  mainstacksize  =
       1024).

   Creation
       Threadcreate  creates  a  new  thread  in the calling proc, returning a
       unique integer identifying the thread; the thread executes fn(arg) on a
       stack of size stacksize.  Thread stacks are allocated in shared memory,
       making it valid to pass pointers to stack variables between threads and
       procs.  Procrfork creates a new proc, and inside that  proc  creates  a
       single  thread  as  threadcreate would, returning the id of the created
       thread.  Procrfork creates the new proc by calling rfork (see  fork(2))
       with  flags  RFPROC|RFMEM|RFNOWAIT|rforkflag.   (The thread library de‐
       pends on all its procs running in the same rendezvous  group.   Do  not
       include  RFREND  in  rforkflag.)   Proccreate is identical to procrfork
       with rforkflag set to zero.  Be aware that the calling thread may  con‐
       tinue execution before the newly created proc and thread are scheduled.
       Because  of  this, arg should not point to data on the stack of a func‐
       tion that could return before the new process is scheduled.

       Threadexits terminates the calling thread.  If the thread is  the  last
       in  its proc, threadexits also terminates the proc, using status as the
       exit status.  Threadexitsall terminates all procs in the program, using
       status as the exit status.

   Scheduling
       The threads in a proc are coroutines, scheduled non-preemptively  in  a
       round-robin  fashion.   A  thread must explicitly relinquish control of
       the processor before another thread in the same  proc  is  run.   Calls
       that  do  this are yield, proccreate, procexec, procexecl, threadexits,
       alt, send, and recv (and the calls related to send and  recv—see  their
       descriptions further on), plus these from lock(2): qlock, rlock, wlock,
       rsleep.   Procs  are  scheduled  by  the  operating system.  Therefore,
       threads in different procs can preempt one another  in  arbitrary  ways
       and  should  synchronize  their  actions  using qlocks (see lock(2)) or
       channel communication.  System calls such as read(2) block  the  entire
       proc; all threads in a proc block until the system call finishes.

       As mentioned above, each thread has a unique integer thread id.  Thread
       ids  are  not  reused;  they are unique across the life of the program.
       Threadid returns the id for the current thread.  Each thread also has a
       thread group id.  The initial thread has a group id of zero.  Each  new
       thread  inherits the group id of the thread that created it.  Threadgrp
       returns the group id for the  current  thread;  threadsetgrp  sets  it.
       Threadpid  returns  the pid of the Plan 9 process containing the thread
       identified by id, or -1 if no such thread is found.

       Threadint interrupts a thread that is blocked in a channel operation or
       system call.  Threadintgrp interrupts all threads with the given  group
       id.   Threadkill  marks  a  thread to die when it next relinquishes the
       processor (via one of the  calls  listed  above).   If  the  thread  is
       blocked  in a channel operation or system call, it is also interrupted.
       Threadkillgrp kills all threads with the given  group  id.   Note  that
       threadkill and threadkillgrp will not terminate a thread that never re‐
       linquishes the processor.

   Names and per-thread data
       Primarily  for debugging, threads can have string names associated with
       them.  Threadgetname returns the current thread's  name;  threadsetname
       sets it.  The pointer returned by threadgetname is only valid until the
       next call to threadsetname.

       Threaddata  returns a pointer to a per-thread pointer that may be modi‐
       fied by threaded programs for per-thread storage.  Similarly,  procdata
       returns a pointer to a per-proc pointer.

   Executing new programs
       Procexecl  and  procexec  are threaded analogues of exec and execl (see
       exec(2)); on success, they replace the calling thread  (which  must  be
       the only thread in its proc) and invoke the external program, never re‐
       turning.   On  error,  they return -1.  If cpid is not null, the pid of
       the invoked program will be sent along cpid once the program  has  been
       started, or -1 will be sent if an error occurs.  Procexec and procexecl
       will  not  access  their  arguments  after sending a result along cpid.
       Thus, programs that malloc the argv passed to procexec can safely  free
       it once they have received the cpid response.

       Threadwaitchan returns a channel of pointers to Waitmsg structures (see
       wait(2)).   When  an  exec'ed  process exits, a pointer to a Waitmsg is
       sent to this channel.  These Waitmsg  structures  have  been  allocated
       with malloc(2) and should be freed after use.

   Channels
       A  Channel  is  a buffered or unbuffered queue for fixed-size messages.
       Procs and threads send messages into the channel and recv messages from
       the channel.  If the channel is unbuffered, a send operation blocks un‐
       til the corresponding recv operation occurs and vice versa.  Chancreate
       allocates a new channel for messages of size elsize and with  a  buffer
       holding  nel  messages.   If  nel  is  zero, the channel is unbuffered.
       Chanfree frees a channel that is  no  longer  used.   Chanfree  can  be
       called  by  either sender or receiver after the last item has been sent
       or received.  Freeing the channel will be delayed if there is a  thread
       blocked  on it until that thread unblocks (but chanfree returns immedi‐
       ately).

       Send sends the element pointed at by v to the channel c.  If v is null,
       zeros are sent.  Recv receives an element from c and stores  it  in  v.
       If  v is null, the received value is discarded.  Send and recv return 1
       on success, -1 if interrupted.  Nbsend and nbrecv behave similarly, but
       return 0 rather than blocking.

       Sendp, nbsendp, sendul, and nbsendul send  a  pointer  or  an  unsigned
       long;  the  channel must have been initialized with the appropriate el‐
       size.  Recvp, nbrecvp, recvul, and nbrecvul receive a pointer or an un‐
       signed long; they return zero when a  zero  is  received,  when  inter‐
       rupted,  or  (for  nbrecvp  and nbrecvul) when the operation would have
       blocked.  To distinguish between these three cases, use recv or nbrecv.

       Alt can be used to recv from or send to one of a number of channels, as
       directed by an array of Alt structures, each of which describes  a  po‐
       tential send or receive operation.  In an Alt structure, c is the chan‐
       nel;  v  the  value  pointer (which may be null); and op the operation:
       CHANSND for a send operation, CHANRCV for a recv operation; CHANNOP for
       no operation (useful when alt is called with a varying  set  of  opera‐
       tions).   The array of Alt structures is terminated by an entry with op
       CHANEND or CHANNOBLK.  If at least one Alt structure can  proceed,  one
       of  them  is chosen at random to be executed.  Alt returns the index of
       the chosen structure.  If no operations can proceed  and  the  list  is
       terminated  with  CHANNOBLK,  alt  returns the index of the terminating
       CHANNOBLK structure.  Otherwise, alt blocks until one of the operations
       can proceed, eventually returning the index of the structure  executes.
       Alt returns -1 when interrupted.  The tag and entryno fields in the Alt
       structure are used internally by alt and need not be initialized.  They
       are not used between alt calls.

       Chanprint formats its arguments in the manner of print(2) and sends the
       result  to  the  channel c.  The string delivered by chanprint is allo‐
       cated with malloc(2) and should be freed upon receipt.

       Chanclose prevents further elements being sent to the channel c.  After
       closing a channel, send and recv never block.  Send always returns  -1.
       Recv  returns  -1 if the channel is empty.  Alt may choose a CHANSND or
       CHANRCV that failed because the channel was closed.  In this case,  the
       err  field  of the Alt entry points to an error string stating that the
       channel was closed and the operation was completed  with  failure.   If
       all entries have been selected and failed because they were closed, alt
       returns -1.

   Errors, notes and resources
       Thread library functions do not return on failure; if errors occur, the
       entire program is aborted.

       Chanclosing returns -1 if no one called closed on the channel, and oth‐
       erwise the number of elements still in the channel.

       Threaded programs should use threadnotify in place of atnotify (see no‐
       tify(2)).

       It  is safe to use sysfatal (see perror(2)) in threaded programs.  Sys‐
       fatal will print the error string and call threadexitsall.

       It is safe to use rfork (see fork(2)) to manage the namespace, file de‐
       scriptors, note group, and environment of a single process.   That  is,
       it  is  safe  to  call  rfork  with  the  flags RFNAMEG, RFFDG, RFCFDG,
       RFNOTEG, RFENVG, and RFCENVG.  (To create new processes, use proccreate
       and procrfork.)  As mentioned above, the thread library depends on  all
       procs  being in the same rendezvous group; do not change the rendezvous
       group with rfork.

FILES
       /sys/lib/acid/thread
              useful acid(1) functions for debugging threaded programs.

       /sys/src/libthread/example.c
              a full example program.

SOURCE
       /sys/src/libthread

SEE ALSO
       intro(2), ioproc(2), lock(2)

                                                                     THREAD(2)