|  | 
 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)
 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 cooperatively
    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 executing 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). 
    
    
    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 nonpreemptively
    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 descriptions 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 carefully, 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 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 relinquishes the processor.
    
    
    
    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. 
    
    
    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 calling 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 executing.) 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 
 to use the current standard files. The correct code is|  |  |  | fd[0] = 0; fd[1] = 1;
 fd[2] = 2;
 
 | 
 
 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 directory before
    running the program, but it is only best effort: failure to change
    into the directory does not stop the running 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 immediately). 
    
    
    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 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
    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
    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 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(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.|  |  |  | fd[0] = dup(0, −1); fd[1] = dup(1, −1);
 fd[2] = dup(2, −1);
 
 | 
 
 | 
 FILES     
 SOURCE     
 SEE ALSO    
 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 coordinating a
    simultaneous threadexits among many threads. 
 | 
 |  |