.TH THREAD 2.SH NAMEalt,chancreate,chanfree,chaninit,proccreate,procdata,procexec,procexecl,procrfork,recv,recvp,recvul,send,sendp,sendul,nbrecv,nbrecvp,nbrecvul,nbsend,nbsendp,nbsendul,threadchdir,threadcreate,threaddata,threadexits,threadexitsall,threadgetgrp,threadgetname,threadkill,threadkillgrp,threadmain,threadnonotes,threadpid,threadprint,threadsetgrp,threadsetname,threadwaitchan,yield \- thread and proc management.SH SYNOPSIS.PP.EX.ta 4n +4n +4n +4n +4n +4n +4n#include <u.h>#include <libc.h>#include <thread.h>.sp#define CHANEND 0#define CHANSND 1#define CHANRCV 2#define CHANNOP 3#define CHANNOBLK 4.ifn .sp.ift .sp 0.5typedef struct Alt { Channel *c; void *v; int op; Channel **tag; ulong q;} Alt;.ifn .sp.ift .sp 0.5void threadmain(int argc, char *argv[]).ift .sp 0.2int proccreate(void (*f)(void *arg), void *arg, uint stacksize).ift .sp 0.2int procrfork(void (*f)(void *arg), void *arg, uint stacksize, int rforkflag).ift .sp 0.2int threadcreate(void (*f)(void *arg), void *arg, uint stacksize).ift .sp 0.2void yield(void).ift .sp 0.2void threadexits(char *status).ift .sp 0.2void threadexitsall(char *status).ift .sp 0.2Channel *chancreate(int elemsize, int bufsize).ift .sp 0.2int chaninit(Channel *c, int elemsize, int elemcnt).ift .sp 0.2int alt(Alt alts[]).ift .sp 0.2int recv(Channel *c, void *v).ift .sp 0.2ulong recvul(Channel *c).ift .sp 0.2void *recvp(Channel *c).ift .sp 0.2int nbrecv(Channel *c, void *v).ift .sp 0.2ulong nbrecvul(Channel *c).ift .sp 0.2void *nbrecvp(Channel *c).ift .sp 0.2int send(Channel *c, void *v).ift .sp 0.2int sendul(Channel *c, ulong v).ift .sp 0.2int sendp(Channel *c, void *v).ift .sp 0.2int nbsend(Channel *c, void *v).ift .sp 0.2int nbsendul(Channel *c, ulong v).ift .sp 0.2int nbsendp(Channel *c, void *v).ift .sp 0.2void chanfree(Channel *c).ift .sp 0.2void threadsetname(char *name).ift .sp 0.2char *threadgetname(void).ift .sp 0.2ulong *procdata(void).ift .sp 0.2ulong *threaddata(void).ift .sp 0.2int threadgetgrp(void).ift .sp 0.2int threadsetgrp(int group).ift .sp 0.2void threadkill(int id).ift .sp 0.2void threadkillgrp(int group).ift .sp 0.2int threadpid(int id).ift .sp 0.2void procexecl(Channel *pidc, char *file, ...).ift .sp 0.2void procexec(Channel *pidc, char *file, char *args[]).ift .sp 0.2Channel *threadwaitchan(void).ift .sp 0.2int threadprint(int fd, char *format, ...).EE.SH DESCRIPTION.PPThe thread library provides parallel-programming support similar to thatof the languagesAlef and Newsqueak.Threadsandprocscan be created that occupy a shared address space in which they cancommunicate through shared variables and.IR channels .A.B Channelis a buffered or unbuffered FIFO for fixed-size messages. Procs andthreads can.I sendmessages into the fifo and.I recvmessages from the fifo. If the fifo is unbuffered, a.I sendoperation blocks until the corresponding.I recvoperation occurs and.IR "vice versa" ..PPA.I procis a Plan 9 process that contains one or more.IR threads .The threads in a proc are coroutines. Runnable threads are schedulednonpreemptively in a round-robin fashion. A thread must explicitlyrelinquish control of the processor before another thread in the sameproc is run. Calls that do this are.IR yield ,.IR send ,.I recv(and the calls related to.I sendand.I recv\- see their descriptions further on),.IR alt ,and.IR threadexits ..PPProcsare scheduled by the operating system. Threads in different procs,therefore, can preempt one another in arbitrary ways, unless theyexplicitly synchronize their actions using.B qlocks(see.IR lock (2))or channel communication..PPBlocking system calls such as.IR read (2)do not cause another thread in the same proc to be scheduled.All threads in a proc block until the system call finishes..PPThread stacks are in shared memory, making it valid to pass pointers to stack variables between threads and procs..PPThreads in different procs are scheduled independently and preemptively.Data structures shared between threads in different procs need to beprotected by a.IR lock (2)..PPPrograms using threads must replace.B mainby.IR threadmain .The thread library will set up a proc with a single thread and call.IR threadmain ..PPA new proc is created by a call to.IR proccreate .The arguments are a function.I fwith a single.B void*argument to be called in the new proc, the argument.I argto that function, and the size of the stack for the new proc..I Proccreate.\" returns the thread id of the (single) thread in the newly created proc.returns the pid of the newly created proc.Processes are created by calling.I rfork(see .IR fork (2))with flags.B RFPROCand.BR RFMEM ..I Procrforkis like.I proccreatebut uses.I rforkflagsor'ed with.B RFPROCand.BR RFMEM ..PP.I Argcan be used to pass arbitrary data to.IR f .Be aware, however, that.I fruns in a new process and that it can take some time before.I fis scheduled..I Argshould not point to data on the stack of a function that couldreturn before the new process is scheduled..PP.I Threadcreatecreates a new thread in the proc of the calling thread. The argumentsare the same as those of.IR proccreate ..I Threadcreatereturns a.IR "thread id" ..PP.I Yieldgives up the processor to another thread in the calling proc..PP.I Threadexitscauses the calling thread to be destroyed. If the thread is the onlyremaining thread in its proc, the proc exits too (using the exit statussupplied to.IR threadexits )..PP.I Threadexitsallkills all threads in the application (and thus all procs) andexits with the status supplied..PP.I Chancreatecreates a buffered or unbuffered.BR Channel .The arguments are thesize of the elements in the channel (must by greater than zero) and thenumber of elements in the fifo. If the number is zero, the channelis blocking (synchronous). If it is greater than zero, the channelis buffered and blocks only if the fifo is empty.RI ( recv )or full.RI ( send )..I Chancreatereturns a pointer to the channel created..PP.I Chaninitinitializes an already allocated channel;.BR elemsize ,and.B elemcntare as in.BR chancreate ..PP.I Recvreceives an element from the channel named by its first argument andstores it in the location pointed to by its second argument. It returns.B 1for success, and.B -1when it was interrupted.If the second argument is null,the received value is ignored..PP.I Recvuland.I recvpreceive an unsigned long or a pointer, respectively, from a channel whoseelement size must be.B sizeof(ulong)or.BR "sizeof(void *)" ..PP.IR Nbrecv ,.IR nbrecvul ,and.I nbrecvpare non-blocking versions of.IR recv ,.IR recvul ,and.IR recvp .Note that.I nbrecvuland.I nbrecvpcan alsoreturn.B 0when the channel is empty.Since.B 0is both a valid data value and an error return,use.I nbrecvinsteadif you wish to distinguish an empty channel from onethat contains a zero element..PP.I Sendsends the value pointed to by the second parameter to the channel pointedto by the first parameter. If the value pointer is 0,zeroes are sent..I Send.IR yield s,so, if the receiving thread is blocked and in the same proc, it willrun first..PP.IR Sendul ,.IR sendp ,.IR nbsend ,.IR nbsendul ,and.I nbsendpare the specialized and nonblocking versions, analogous to the.I recvfamily of calls..PP.I Altcan be used to recv from or send to one of a number of channels..I Alttakes as its parameter an array of.B Altstructures. Each of these structures describes a potential send or recvoperation:.B cand.B vare the channel and value pointer (which may be.BR nil )and.B opspecifies the operation:.B CHANSNDfor a send operation,.B CHANRECVfor a recv operation;.B CHANNOPfor no operation\(emthe entry should be skipped. This can be usefulwhen.I altcalls are used with a varying set of operations.The array of.B Altstructures is terminated by a null entry whose opcode is.B CHANENDor.BR CHANNOBLK ..B CHANNOBLKis a default entry that `fires' when none of the other operations can fire.It makes an.I altstatement non-blocking..PP.I Altlooks for channel operations in the array of.I Altstructures that can proceed. If there is one, the associated.I sendor.I recvoperation occurs. If there is more than one, oneof them is chosen at random and the associated communication eventoccurs. If there are none, and the list is terminated by a.B CHANENDentry,.I altblocks until one of the operations can proceed. If there are none and the list is terminated by a.B CHANNOBLKentry, that entry will fire..I Altreturns the index of the operation that succeeded. The fields.B tagand.B qin the.B Altstructure are used by the implementation of alt. They are not usedbetween.I altcalls..PP.I Chanfreefrees a channel that is no longer used..I Chanfreecan be called by either sender or receiver after the last item has beensent or received. Freeing the channel will be delayed if there is a threadblocked on it until that thread unblocks (but chanfree returns instantly)..PP.I Threadgetnameand.I threadsetnamecan be used to read or set the name of a thread. This can be usefulfor debugging..PP.I Threadkillkills the thread identified by its.I "thread ID(as returned by threadcreate) and cleans up its stack..PP.I Procdatareturns a pointer to a per-process location (big enough to hold a pointer)into which applications can store per-proc data..PPThreads have a group number that is inherited on proc and thread creation,much like a process group..I Threadsetgrpcan be used to set this group to an arbitrary integer..I Threadgetgrpreturns the group of the current thread..I Threadkillgrpcan be used to kill all threads in a group..PP.I Threadpidreturns the.I pidof the proc of the thread whose.I idis given. If.I idequals zero, the pid of the proc of the current thread is returned and if.I iddoes not correspond to an existing thread, \-1 is returned..PP.I Procexecland.I procexecmay only be called from a thread which is the sole thread ina proc. The thread is removed from the program and the processexecutes independently.The first argument, if not nil, is a channel on which the pidof the exec-ed process will be returned..PPIf the pid channel is set,.I procexecand.I procexeclwill return (i.e., fail) if and only if they also send \-1 on the pid channel..PPThe rest of the arguments are the same as those of.I execland.I exec(see.IR exec (2)).To simplify resource management, these routines first use.IR access (2)to check if the file exists and is executable before attempting to.IR exec (2)it..PP.I Threadwaitchanreturns a channel of.B Waitmsgstructures (seeLines 1–500 of 678. Load more
.TH THREAD 2 .SH NAME alt, chancreate, chanfree, chaninit, proccreate, procdata, procexec, procexecl, procrfork, recv, recvp, recvul, send, sendp, sendul, nbrecv, nbrecvp, nbrecvul, nbsend, nbsendp, nbsendul, threadchdir, threadcreate, threaddata, threadexits, threadexitsall, threadgetgrp, threadgetname, threadkill, threadkillgrp, threadmain, threadnonotes, threadpid, threadprint, threadsetgrp, threadsetname, threadwaitchan, yield \- thread and proc management .SH SYNOPSIS .PP .EX .ta 4n +4n +4n +4n +4n +4n +4n #include <u.h> #include <libc.h> #include <thread.h> .sp #define CHANEND 0 #define CHANSND 1 #define CHANRCV 2 #define CHANNOP 3 #define CHANNOBLK 4 .ifn .sp .ift .sp 0.5 typedef struct Alt { Channel *c; void *v; int op; Channel **tag; ulong q; } Alt; .ifn .sp .ift .sp 0.5 void threadmain(int argc, char *argv[]) .ift .sp 0.2 int proccreate(void (*f)(void *arg), void *arg, uint stacksize) .ift .sp 0.2 int procrfork(void (*f)(void *arg), void *arg, uint stacksize, int rforkflag) .ift .sp 0.2 int threadcreate(void (*f)(void *arg), void *arg, uint stacksize) .ift .sp 0.2 void yield(void) .ift .sp 0.2 void threadexits(char *status) .ift .sp 0.2 void threadexitsall(char *status) .ift .sp 0.2 Channel *chancreate(int elemsize, int bufsize) .ift .sp 0.2 int chaninit(Channel *c, int elemsize, int elemcnt) .ift .sp 0.2 int alt(Alt alts[]) .ift .sp 0.2 int recv(Channel *c, void *v) .ift .sp 0.2 ulong recvul(Channel *c) .ift .sp 0.2 void *recvp(Channel *c) .ift .sp 0.2 int nbrecv(Channel *c, void *v) .ift .sp 0.2 ulong nbrecvul(Channel *c) .ift .sp 0.2 void *nbrecvp(Channel *c) .ift .sp 0.2 int send(Channel *c, void *v) .ift .sp 0.2 int sendul(Channel *c, ulong v) .ift .sp 0.2 int sendp(Channel *c, void *v) .ift .sp 0.2 int nbsend(Channel *c, void *v) .ift .sp 0.2 int nbsendul(Channel *c, ulong v) .ift .sp 0.2 int nbsendp(Channel *c, void *v) .ift .sp 0.2 void chanfree(Channel *c) .ift .sp 0.2 void threadsetname(char *name) .ift .sp 0.2 char *threadgetname(void) .ift .sp 0.2 ulong *procdata(void) .ift .sp 0.2 ulong *threaddata(void) .ift .sp 0.2 int threadgetgrp(void) .ift .sp 0.2 int threadsetgrp(int group) .ift .sp 0.2 void threadkill(int id) .ift .sp 0.2 void threadkillgrp(int group) .ift .sp 0.2 int threadpid(int id) .ift .sp 0.2 void procexecl(Channel *pidc, char *file, ...) .ift .sp 0.2 void procexec(Channel *pidc, char *file, char *args[]) .ift .sp 0.2 Channel *threadwaitchan(void) .ift .sp 0.2 int threadprint(int fd, char *format, ...) .EE .SH DESCRIPTION .PP The thread library provides parallel-programming support similar to that of the languages Alef and Newsqueak. Threads and procs can be created that occupy a shared address space in which they can communicate through shared variables and .IR channels . A .B Channel is a buffered or unbuffered FIFO for fixed-size messages. Procs and threads can .I send messages into the fifo and .I recv messages from the fifo. If the fifo is unbuffered, a .I send operation blocks until the corresponding .I recv operation occurs and .IR "vice versa" . .PP A .I proc is a Plan 9 process that contains one or more .IR threads . The threads in a proc are coroutines. Runnable threads are 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 .IR yield , .IR send , .I recv (and the calls related to .I send and .I recv \- see their descriptions further on), .IR alt , and .IR threadexits . .PP Procs are scheduled by the operating system. Threads in different procs, therefore, can preempt one another in arbitrary ways, unless they explicitly synchronize their actions using .B qlocks (see .IR lock (2)) or channel communication. .PP Blocking system calls such as .IR read (2) do not cause another thread in the same proc to be scheduled. All threads in a proc block until the system call finishes. .PP Thread stacks are in shared memory, making it valid to pass pointers to stack variables between threads and procs. .PP Threads in different procs are scheduled independently and preemptively. Data structures shared between threads in different procs need to be protected by a .IR lock (2). .PP Programs using threads must replace .B main by .IR threadmain . The thread library will set up a proc with a single thread and call .IR threadmain . .PP A new proc is created by a call to .IR proccreate . The arguments are a function .I f with a single .B void* argument to be called in the new proc, the argument .I arg to that function, and the size of the stack for the new proc. .I Proccreate .\" returns the thread id of the (single) thread in the newly created proc. returns the pid of the newly created proc. Processes are created by calling .I rfork (see .IR fork (2)) with flags .B RFPROC and .BR RFMEM . .I Procrfork is like .I proccreate but uses .I rforkflags or'ed with .B RFPROC and .BR RFMEM . .PP .I Arg can be used to pass arbitrary data to .IR f . Be aware, however, that .I f runs in a new process and that it can take some time before .I f is scheduled. .I Arg should not point to data on the stack of a function that could return before the new process is scheduled. .PP .I Threadcreate creates a new thread in the proc of the calling thread. The arguments are the same as those of .IR proccreate . .I Threadcreate returns a .IR "thread id" . .PP .I Yield gives up the processor to another thread in the calling proc. .PP .I Threadexits causes the calling thread to be destroyed. If the thread is the only remaining thread in its proc, the proc exits too (using the exit status supplied to .IR threadexits ). .PP .I Threadexitsall kills all threads in the application (and thus all procs) and exits with the status supplied. .PP .I Chancreate creates a buffered or unbuffered .BR Channel . The arguments are the size of the elements in the channel (must by greater than zero) and the number of elements in the fifo. If the number is zero, the channel is blocking (synchronous). If it is greater than zero, the channel is buffered and blocks only if the fifo is empty .RI ( recv ) or full .RI ( send ). .I Chancreate returns a pointer to the channel created. .PP .I Chaninit initializes an already allocated channel; .BR elemsize , and .B elemcnt are as in .BR chancreate . .PP .I Recv receives an element from the channel named by its first argument and stores it in the location pointed to by its second argument. It returns .B 1 for success, and .B -1 when it was interrupted. If the second argument is null, the received value is ignored. .PP .I Recvul and .I recvp receive an unsigned long or a pointer, respectively, from a channel whose element size must be .B sizeof(ulong) or .BR "sizeof(void *)" . .PP .IR Nbrecv , .IR nbrecvul , and .I nbrecvp are non-blocking versions of .IR recv , .IR recvul , and .IR recvp . Note that .I nbrecvul and .I nbrecvp can also return .B 0 when the channel is empty. Since .B 0 is both a valid data value and an error return, use .I nbrecv instead if you wish to distinguish an empty channel from one that contains a zero element. .PP .I Send sends the value pointed to by the second parameter to the channel pointed to by the first parameter. If the value pointer is 0, zeroes are sent. .I Send .IR yield s, so, if the receiving thread is blocked and in the same proc, it will run first. .PP .IR Sendul , .IR sendp , .IR nbsend , .IR nbsendul , and .I nbsendp are the specialized and nonblocking versions, analogous to the .I recv family of calls. .PP .I Alt can be used to recv from or send to one of a number of channels. .I Alt takes as its parameter an array of .B Alt structures. Each of these structures describes a potential send or recv operation: .B c and .B v are the channel and value pointer (which may be .BR nil ) and .B op specifies the operation: .B CHANSND for a send operation, .B CHANRECV for a recv operation; .B CHANNOP for no operation\(emthe entry should be skipped. This can be useful when .I alt calls are used with a varying set of operations. The array of .B Alt structures is terminated by a null entry whose opcode is .B CHANEND or .BR CHANNOBLK . .B CHANNOBLK is a default entry that `fires' when none of the other operations can fire. It makes an .I alt statement non-blocking. .PP .I Alt looks for channel operations in the array of .I Alt structures that can proceed. If there is one, the associated .I send or .I recv operation occurs. If there is more than one, one of them is chosen at random and the associated communication event occurs. If there are none, and the list is terminated by a .B CHANEND entry, .I alt blocks until one of the operations can proceed. If there are none and the list is terminated by a .B CHANNOBLK entry, that entry will fire. .I Alt returns the index of the operation that succeeded. The fields .B tag and .B q in the .B Alt structure are used by the implementation of alt. They are not used between .I alt calls. .PP .I Chanfree frees a channel that is no longer used. .I 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 instantly). .PP .I Threadgetname and .I threadsetname can be used to read or set the name of a thread. This can be useful for debugging. .PP .I Threadkill kills the thread identified by its .I "thread ID (as returned by threadcreate) and cleans up its stack. .PP .I Procdata returns a pointer to a per-process location (big enough to hold a pointer) into which applications can store per-proc data. .PP Threads have a group number that is inherited on proc and thread creation, much like a process group. .I Threadsetgrp can be used to set this group to an arbitrary integer. .I Threadgetgrp returns the group of the current thread. .I Threadkillgrp can be used to kill all threads in a group. .PP .I Threadpid returns the .I pid of the proc of the thread whose .I id is given. If .I id equals zero, the pid of the proc of the current thread is returned and if .I id does not correspond to an existing thread, \-1 is returned. .PP .I Procexecl and .I procexec may only be called from a thread which is the sole thread in a proc. The thread is removed from the program and the process executes independently. The first argument, if not nil, is a channel on which the pid of the exec-ed process will be returned. .PP If the pid channel is set, .I procexec and .I procexecl will return (i.e., fail) if and only if they also send \-1 on the pid channel. .PP The rest of the arguments are the same as those of .I execl and .I exec (see .IR exec (2)). To simplify resource management, these routines first use .IR access (2) to check if the file exists and is executable before attempting to .IR exec (2) it. .PP .I Threadwaitchan returns a channel of .B Waitmsg structures (see