THREAD(3)                                               THREAD(3)

     NAME
          alt, chancreate, chanfree, chanprint, chansetname,
          mainstacksize, proccreate, procdata, recv, recvp, recvul,
          send, sendp, sendul, nbrecv, nbrecvp, nbrecvul, nbsend,
          nbsendp, nbsendul, threadcreate, threaddata, threadexec,
          threadexecl, threadexits, threadexitsall, threadgetgrp,
          threadgetname, threadint, threadintgrp, threadkill,
          threadkillgrp, threadmain, threadnotify, threadid,
          threadpid, threadpin, threadunpin, threadsetgrp,
          threadsetname, threadsetstate, threadspawn, threadspawnd,
          threadspawnl, threadwaitchan, yield - thread and proc
          management

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

          #define CHANEND     0
          #define CHANSND     1
          #define CHANRCV     2
          #define CHANNOP     3
          #define CHANNOBLK   4

          typedef struct Alt Alt;
          struct Alt {
              Channel *c;
              void    *v;
              int     op;
              Channel **tag;
              int     entryno;
              char    *name;
          };

          void     threadmain(int argc, char *argv[])
          int      mainstacksize
          int      proccreate(void (*fn)(void*), void *arg, uint stacksize)
          int      threadcreate(void (*fn)(void*), void *arg, uint stacksize)
          void     threadexits(char *status)
          void     threadexitsall(char *status)
          void     yield(void)
          int      threadpin(void)
          int      threadunpin(void)

          int      threadid(void)
          int      threadgrp(void)
          int      threadsetgrp(int group)
          int      threadpid(int id)

          int      threadint(int id)

     Page 1                       Plan 9             (printed 3/28/24)

     THREAD(3)                                               THREAD(3)

          int      threadintgrp(int group)
          int      threadkill(int id)
          int      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      threadspawnl(int fd[3], char *file, ...)
          int      threadspawn(int fd[3], char *file, char *args[])
          int      threadspawnd(int fd[3], char *file, char *args[], char *dir)
          int      threadexecl(Channel *cpid, int fd[3], char *file, ...)
          int      threadexec(Channel *cpid, int fd[3], 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 cooper-
          atively scheduled threads. Programs using threads must
          replace main by threadmain. The thread library provides a
          main function that sets up a proc with a single thread exe-
          cuting threadmain on a stack of size mainstacksize (default
          eight kilobytes).  To set mainstacksize, declare a global
          variable initialized to the desired value (e.g., int
          mainstacksize = 1024).

     Page 2                       Plan 9             (printed 3/28/24)

     THREAD(3)                                               THREAD(3)

          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.
          Proccreate creates a new proc, and inside that proc creates
          a single thread as threadcreate would, returning the id of
          the created thread.  Be aware that the calling thread may
          continue execution before the newly created proc and thread
          are scheduled.  Because of this, arg should not point to
          data on the stack of a function 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.

          When the last thread in threadmain's proc exits, the program
          will appear to its parent to have exited.  The remaining
          procs will still run together, but as a background program.

          The threads in a proc are coroutines, scheduled nonpreemp-
          tively 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, threadexec, threadexecl, threadexits,
          threadspawn, threadspawnd, threadspawnl, alt, send, and recv
          (and the calls related to send and recv-see their descrip-
          tions further on).  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(3)) or channel communication.
          System calls such as read(3) block the entire proc; all
          threads in a proc block until the system call finishes.

          Threadpin disables scheduling inside a proc, `pinning' the
          current thread as the only runnable one in the current proc.
          Threadunpin reenables scheduling, allowing other procs to
          run once the current thread relinquishes the processor.
          Threadpin and threadunpin can lead to deadlock.  Used care-
          fully, they can make library routines that use qlocks appear
          atomic relative to the current proc, like a system call.

          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 cur-
          rent 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

     Page 3                       Plan 9             (printed 3/28/24)

     THREAD(3)                                               THREAD(3)

          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 relinquishes the processor.

          Primarily for debugging, threads can have string names asso-
          ciated 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.

          Also for debugging, threads have a string state associated
          with them.  Threadsetstate sets the state string.  There is
          no threadgetstate; since the thread scheduler resets the
          state to Running every time it runs the thread, it is only
          useful for debuggers to inspect the state.

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

          Threadexecl and threadexec are threaded analogues of exec
          and execl (see exec(3)); on success, they replace the call-
          ing thread and invoke the external program, never returning.
          (Unlike on Plan 9, the calling thread need not be the only
          thread in its proc-the other threads will continue execut-
          ing.)  On error, they return -1.  If cpid is not null, the
          pid of the invoked program will be sent along cpid (using
          sendul) once the program has been started, or -1 will be
          sent if an error occurs.  Threadexec and threadexecl will
          not access their arguments after sending a result along
          cpid. Thus, programs that malloc the argv passed to
          threadexec can safely free it once they have received the
          cpid response.

          Threadexecl and threadexec will duplicate (see dup(3)) the
          three file descriptors in fd onto standard input, output,
          and error for the external program and then close them in
          the calling thread.  Beware of code that sets

               fd[0] = 0;
               fd[1] = 1;
               fd[2] = 2;

     Page 4                       Plan 9             (printed 3/28/24)

     THREAD(3)                                               THREAD(3)

          to use the current standard files.  The correct code is

               fd[0] = dup(0, -1);
               fd[1] = dup(1, -1);
               fd[2] = dup(2, -1);

          Threadspawnl and threadspawn are like threadexecl and
          threadexec but do not replace the current thread.  They
          return the pid of the invoked program on success, or -1 on
          error.  Threadspawnd is like threadspawn but takes as its
          final argument the directory in which to run the invoked
          program.  The child will attempt to change into that direc-
          tory before running the program, but it is only best effort:
          failure to change into the directory does not stop the run-
          ning of the program.

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

          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 until 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).

          The name element in the Channel structure is a description
          intended for use in debugging.  Chansetname sets the name.

          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 dis-
          carded.  Send and recv return 1 on success, -1 if inter-
          rupted.  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 elsize. Recvp, nbrecvp, recvul, and nbrecvul
          receive a pointer or an unsigned long; they return zero when
          a zero is received, when interrupted, or (for nbrecvp and
          nbrecvul) when the operation would have blocked.  To

     Page 5                       Plan 9             (printed 3/28/24)

     THREAD(3)                                               THREAD(3)

          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 potential send or receive operation.  In
          an Alt structure, c is the channel; v the value pointer
          (which may be null); and op the operation: CHANSND for a
          send operation, CHANRECV for a recv operation; CHANNOP for
          no operation (useful when alt is called with a varying set
          of operations).  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 struc-
          ture.  If no operations can proceed and the list is termi-
          nated with CHANNOBLK, alt returns the index of the terminat-
          ing 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(3)
          and sends the result to the channel c. The string delivered
          by chanprint is allocated with malloc(3) and should be freed
          upon receipt.

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

          Threaded programs should use threadnotify in place of
          atnotify (see notify(3)).

          It is safe to use sysfatal(3) in threaded programs.
          Sysfatal will print the error string and call
          threadexitsall.

          It is not safe to call rfork in a threaded program, except
          to call rfork(RFNOTEG) from the main proc before any other
          procs have been created.  To create new processes, use
          proccreate.

     FILES
          /usr/local/plan9/acid/thread contains useful acid(1) func-
          tions for debugging threaded programs.

          /usr/local/plan9/src/libthread/test contains some example
          programs.

     SOURCE
          /usr/local/plan9/src/libthread

     Page 6                       Plan 9             (printed 3/28/24)

     THREAD(3)                                               THREAD(3)

     SEE ALSO
          intro(3), ioproc(3)

     BUGS
          To avoid name conflicts, alt, nbrecv, nbrecvp, nbrecvul,
          nbsend, nbsendp, nbsendul, recv, recvp, recvul, send, sendp,
          and sendul are defined as macros that expand to chanalt,
          channbrecv, and so on.  Yield is defined as a macro that
          expands to threadyield. See intro(3).

          Threadint, threadintgrp, threadkill, threadkillgrp and
          threadpid are unimplemented.

          The implementation of threadnotify may not be correct.

          There appears to be a race in the Linux NPTL implementation
          of pthread_exit . Call threadexitsall rather than coordinat-
          ing a simultaneous threadexits among many threads.

     Page 7                       Plan 9             (printed 3/28/24)