Initial revision
This commit is contained in:
parent
5f7d5e8d18
commit
b2cfc4e2e7
242 changed files with 18177 additions and 0 deletions
576
man/man3/thread.3
Normal file
576
man/man3/thread.3
Normal file
|
|
@ -0,0 +1,576 @@
|
|||
.TH THREAD 2
|
||||
.SH NAME
|
||||
alt,
|
||||
chancreate,
|
||||
chanfree,
|
||||
chaninit,
|
||||
chanprint,
|
||||
mainstacksize,
|
||||
proccreate,
|
||||
procdata,
|
||||
procexec,
|
||||
procexecl,
|
||||
procrfork,
|
||||
recv,
|
||||
recvp,
|
||||
recvul,
|
||||
send,
|
||||
sendp,
|
||||
sendul,
|
||||
nbrecv,
|
||||
nbrecvp,
|
||||
nbrecvul,
|
||||
nbsend,
|
||||
nbsendp,
|
||||
nbsendul,
|
||||
threadcreate,
|
||||
threaddata,
|
||||
threadexits,
|
||||
threadexitsall,
|
||||
threadgetgrp,
|
||||
threadgetname,
|
||||
threadint,
|
||||
threadintgrp,
|
||||
threadkill,
|
||||
threadkillgrp,
|
||||
threadmain,
|
||||
threadnotify,
|
||||
threadid,
|
||||
threadpid,
|
||||
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
|
||||
.sp
|
||||
.ta \w' 'u +\w'Channel 'u
|
||||
typedef struct Alt Alt;
|
||||
struct Alt {
|
||||
Channel *c;
|
||||
void *v;
|
||||
int op;
|
||||
Channel **tag;
|
||||
int entryno;
|
||||
};
|
||||
.fi
|
||||
.de XX
|
||||
.ift .sp 0.5
|
||||
.ifn .sp
|
||||
..
|
||||
.PP
|
||||
.nf
|
||||
.ft L
|
||||
.ta \w'\fLChannel* 'u +4n +4n +4n +4n
|
||||
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)
|
||||
.XX
|
||||
int threadid(void)
|
||||
int threadgrp(void)
|
||||
int threadsetgrp(int group)
|
||||
int threadpid(int id)
|
||||
.XX
|
||||
int threadint(int id)
|
||||
int threadintgrp(int group)
|
||||
int threadkill(int id)
|
||||
int threadkillgrp(int group)
|
||||
.XX
|
||||
void threadsetname(char *name)
|
||||
char* threadgetname(void)
|
||||
.XX
|
||||
void** threaddata(void)
|
||||
void** procdata(void)
|
||||
.XX
|
||||
int chaninit(Channel *c, int elsize, int nel)
|
||||
Channel* chancreate(int elsize, int nel)
|
||||
void chanfree(Channel *c)
|
||||
.XX
|
||||
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, ...)
|
||||
.XX
|
||||
int procexecl(Channel *cpid, char *file, ...)
|
||||
int procexec(Channel *cpid, char *file, char *args[])
|
||||
Channel* threadwaitchan(void)
|
||||
.XX
|
||||
int threadnotify(int (*f)(void*, char*), int in)
|
||||
.EE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
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
|
||||
.I channels
|
||||
and shared variables.
|
||||
.PP
|
||||
A
|
||||
.I proc
|
||||
is a Plan 9 process that contains one or more cooperatively scheduled
|
||||
.IR threads .
|
||||
Programs using threads must replace
|
||||
.I main
|
||||
by
|
||||
.IR threadmain .
|
||||
The thread library provides a
|
||||
.I main
|
||||
function that sets up a proc with a single thread executing
|
||||
.I threadmain
|
||||
on a stack of size
|
||||
.I mainstacksize
|
||||
(default eight kilobytes).
|
||||
To set
|
||||
.IR mainstacksize ,
|
||||
declare a global variable
|
||||
initialized to the desired value
|
||||
.RI ( e.g. ,
|
||||
.B int
|
||||
.B mainstacksize
|
||||
.B =
|
||||
.BR 1024 ).
|
||||
.PP
|
||||
.I Threadcreate
|
||||
creates a new thread in the calling proc, returning a unique integer
|
||||
identifying the thread; the thread
|
||||
executes
|
||||
.I fn(arg)
|
||||
on a stack of size
|
||||
.IR stacksize .
|
||||
Thread stacks are allocated in shared memory, making it valid to pass
|
||||
pointers to stack variables between threads and procs.
|
||||
.I Procrfork
|
||||
creates a new proc, and inside that proc creates
|
||||
a single thread as
|
||||
.I threadcreate
|
||||
would,
|
||||
returning the id of the created thread.
|
||||
.I Procrfork
|
||||
creates the new proc by calling
|
||||
.B rfork
|
||||
(see
|
||||
.IR fork (2))
|
||||
with flags
|
||||
.BR RFPROC|RFMEM|RFNOWAIT| \fIrforkflag\fR.
|
||||
(The thread library depends on all its procs
|
||||
running in the same rendezvous group.
|
||||
Do not include
|
||||
.B RFREND
|
||||
in
|
||||
.IR rforkflag .)
|
||||
.I Proccreate
|
||||
is identical to
|
||||
.I procrfork
|
||||
with
|
||||
.I rforkflag
|
||||
set to zero.
|
||||
Be aware that the calling thread may continue
|
||||
execution before
|
||||
the newly created proc and thread
|
||||
are scheduled.
|
||||
Because of this,
|
||||
.I arg
|
||||
should not point to data on the stack of a function that could
|
||||
return before the new process is scheduled.
|
||||
.PP
|
||||
.I Threadexits
|
||||
terminates the calling thread.
|
||||
If the thread is the last in its proc,
|
||||
.I threadexits
|
||||
also terminates the proc, using
|
||||
.I status
|
||||
as the exit status.
|
||||
.I Threadexitsall
|
||||
terminates all procs in the program,
|
||||
using
|
||||
.I status
|
||||
as the exit status.
|
||||
.PP
|
||||
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
|
||||
.IR yield ,
|
||||
.IR proccreate ,
|
||||
.IR procexec ,
|
||||
.IR procexecl ,
|
||||
.IR threadexits ,
|
||||
.IR alt ,
|
||||
.IR send ,
|
||||
and
|
||||
.I recv
|
||||
(and the calls related to
|
||||
.I send
|
||||
and
|
||||
.IR recv \(emsee
|
||||
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
|
||||
.B qlocks
|
||||
(see
|
||||
.IR lock (2))
|
||||
or channel communication.
|
||||
System calls such as
|
||||
.IR read (2)
|
||||
block the entire proc;
|
||||
all threads in a proc block until the system call finishes.
|
||||
.PP
|
||||
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.
|
||||
.I 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.
|
||||
.I Threadgrp
|
||||
returns the group id for the current thread;
|
||||
.I threadsetgrp
|
||||
sets it.
|
||||
.I Threadpid
|
||||
returns the pid of the Plan 9 process containing
|
||||
the thread identified by
|
||||
.IR id ,
|
||||
or \-1
|
||||
if no such thread is found.
|
||||
.PP
|
||||
.I Threadint
|
||||
interrupts a thread that is blocked in a channel operation
|
||||
or system call.
|
||||
.I Threadintgrp
|
||||
interrupts all threads with the given group id.
|
||||
.I 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.
|
||||
.I Threadkillgrp
|
||||
kills all threads with the given group id.
|
||||
Note that
|
||||
.I threadkill
|
||||
and
|
||||
.I threadkillgrp
|
||||
will not terminate a thread that never relinquishes
|
||||
the processor.
|
||||
.PP
|
||||
Primarily for debugging,
|
||||
threads can have string names associated with them.
|
||||
.I Threadgetname
|
||||
returns the current thread's name;
|
||||
.I threadsetname
|
||||
sets it.
|
||||
The pointer returned by
|
||||
.I threadgetname
|
||||
is only valid until the next call to
|
||||
.IR threadsetname .
|
||||
.PP
|
||||
.I Threaddata
|
||||
returns a pointer to a per-thread pointer
|
||||
that may be modified by threaded programs for
|
||||
per-thread storage.
|
||||
Similarly,
|
||||
.I procdata
|
||||
returns a pointer to a per-proc pointer.
|
||||
.PP
|
||||
.I Procexecl
|
||||
and
|
||||
.I procexec
|
||||
are threaded analogues of
|
||||
.I exec
|
||||
and
|
||||
.I execl
|
||||
(see
|
||||
.IR exec (2));
|
||||
on success,
|
||||
they replace the calling thread (which must be the only thread in its proc)
|
||||
and invoke the external program, never returning.
|
||||
On error, they return \-1.
|
||||
If
|
||||
.I cpid
|
||||
is not null, the pid of the invoked program
|
||||
will be sent along
|
||||
.I cpid
|
||||
once the program has been started, or \-1 will be sent if an
|
||||
error occurs.
|
||||
.I Procexec
|
||||
and
|
||||
.I procexecl
|
||||
will not access their arguments after sending a result
|
||||
along
|
||||
.IR cpid .
|
||||
Thus, programs that malloc the
|
||||
.I argv
|
||||
passed to
|
||||
.I procexec
|
||||
can safely free it once they have
|
||||
received the
|
||||
.I cpid
|
||||
response.
|
||||
.I Threadwaitchan
|
||||
returns a channel of pointers to
|
||||
.B Waitmsg
|
||||
structures (see
|
||||
.IR wait (2)).
|
||||
When an exec'ed process exits, a pointer to a
|
||||
.B Waitmsg
|
||||
is sent to this channel.
|
||||
These
|
||||
.B Waitmsg
|
||||
structures have been allocated with
|
||||
.IR malloc (2)
|
||||
and should be freed after use.
|
||||
.PP
|
||||
A
|
||||
.B Channel
|
||||
is a buffered or unbuffered queue for fixed-size messages.
|
||||
Procs and threads
|
||||
.I send
|
||||
messages into the channel and
|
||||
.I recv
|
||||
messages from the channel. If the channel is unbuffered, a
|
||||
.I send
|
||||
operation blocks until the corresponding
|
||||
.I recv
|
||||
operation occurs and
|
||||
.IR "vice versa" .
|
||||
.I Chaninit
|
||||
initializes a
|
||||
.B Channel
|
||||
for messages of size
|
||||
.I elsize
|
||||
and with a buffer holding
|
||||
.I nel
|
||||
messages.
|
||||
If
|
||||
.I nel
|
||||
is zero, the channel is unbuffered.
|
||||
.IR Chancreate
|
||||
allocates a new channel and initializes it.
|
||||
.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
|
||||
.I chanfree
|
||||
returns immediately).
|
||||
.PP
|
||||
.I Send
|
||||
sends the element pointed at by
|
||||
.I v
|
||||
to the channel
|
||||
.IR c .
|
||||
If
|
||||
.I v
|
||||
is null, zeros are sent.
|
||||
.I Recv
|
||||
receives an element from
|
||||
.I c
|
||||
and stores it in
|
||||
.IR v .
|
||||
If
|
||||
.I v
|
||||
is null,
|
||||
the received value is discarded.
|
||||
.I Send
|
||||
and
|
||||
.I recv
|
||||
return 1 on success, \-1 if interrupted.
|
||||
.I Nbsend
|
||||
and
|
||||
.I nbrecv
|
||||
behave similarly, but return 0 rather than blocking.
|
||||
.PP
|
||||
.IR Sendp ,
|
||||
.IR nbsendp ,
|
||||
.IR sendul ,
|
||||
and
|
||||
.I nbsendul
|
||||
send a pointer or an unsigned long; the channel must
|
||||
have been initialized with the appropriate
|
||||
.IR elsize .
|
||||
.IR Recvp ,
|
||||
.IR nbrecvp ,
|
||||
.IR recvul ,
|
||||
and
|
||||
.I nbrecvul
|
||||
receive a pointer or an unsigned long;
|
||||
they return zero when a zero is received,
|
||||
when interrupted, or
|
||||
(for
|
||||
.I nbrecvp
|
||||
and
|
||||
.IR nbrecvul )
|
||||
when the operation would have blocked.
|
||||
To distinguish between these three cases,
|
||||
use
|
||||
.I recv
|
||||
or
|
||||
.IR nbrecv .
|
||||
.PP
|
||||
.I Alt
|
||||
can be used to recv from or send to one of a number of channels,
|
||||
as directed by an array of
|
||||
.B Alt
|
||||
structures,
|
||||
each of which describes a potential send or receive operation.
|
||||
In an
|
||||
.B Alt
|
||||
structure,
|
||||
.B c
|
||||
is the channel;
|
||||
.B v
|
||||
the value pointer (which may be null); and
|
||||
.B op
|
||||
the operation:
|
||||
.B CHANSND
|
||||
for a send operation,
|
||||
.B CHANRECV
|
||||
for a recv operation;
|
||||
.B CHANNOP
|
||||
for no operation
|
||||
(useful
|
||||
when
|
||||
.I alt
|
||||
is called with a varying set of operations).
|
||||
The array of
|
||||
.B Alt
|
||||
structures is terminated by an entry with
|
||||
.I op
|
||||
.B CHANEND
|
||||
or
|
||||
.BR CHANNOBLK .
|
||||
If at least one
|
||||
.B Alt
|
||||
structure can proceed, one of them is
|
||||
chosen at random to be executed.
|
||||
.I Alt
|
||||
returns the index of the chosen structure.
|
||||
If no operations can proceed and the list is terminated with
|
||||
.BR CHANNOBLK ,
|
||||
.I alt
|
||||
returns the index of the terminating
|
||||
.B CHANNOBLK
|
||||
structure.
|
||||
Otherwise,
|
||||
.I alt
|
||||
blocks until one of the operations can proceed,
|
||||
eventually returning the index of the structure executes.
|
||||
.I Alt
|
||||
returns \-1 when interrupted.
|
||||
The
|
||||
.B tag
|
||||
and
|
||||
.B entryno
|
||||
fields in the
|
||||
.B Alt
|
||||
structure are used internally by
|
||||
.I alt
|
||||
and need not be initialized.
|
||||
They are not used between
|
||||
.I alt
|
||||
calls.
|
||||
.PP
|
||||
.I Chanprint
|
||||
formats its arguments in the manner of
|
||||
.IR print (2)
|
||||
and sends the result to the channel
|
||||
.IR c.
|
||||
The string delivered by
|
||||
.I chanprint
|
||||
is allocated with
|
||||
.IR malloc (2)
|
||||
and should be freed upon receipt.
|
||||
.PP
|
||||
Thread library functions do not return on failure;
|
||||
if errors occur, the entire program is aborted.
|
||||
.PP
|
||||
Threaded programs should use
|
||||
.I threadnotify
|
||||
in place of
|
||||
.I atnotify
|
||||
(see
|
||||
.IR notify (2)).
|
||||
.PP
|
||||
It is safe to use
|
||||
.B sysfatal
|
||||
(see
|
||||
.IR perror (2))
|
||||
in threaded programs.
|
||||
.I Sysfatal
|
||||
will print the error string and call
|
||||
.IR threadexitsall .
|
||||
.PP
|
||||
It is safe to use
|
||||
.IR rfork
|
||||
(see
|
||||
.IR fork (2))
|
||||
to manage the namespace, file descriptors, note group, and environment of a
|
||||
single process.
|
||||
That is, it is safe to call
|
||||
.I rfork
|
||||
with the flags
|
||||
.BR RFNAMEG ,
|
||||
.BR RFFDG ,
|
||||
.BR RFCFDG ,
|
||||
.BR RFNOTEG ,
|
||||
.BR RFENVG ,
|
||||
and
|
||||
.BR RFCENVG.
|
||||
(To create new processes, use
|
||||
.I proccreate
|
||||
and
|
||||
.IR procrfork .)
|
||||
As mentioned above,
|
||||
the thread library depends on all procs being in the
|
||||
same rendezvous group; do not change the rendezvous
|
||||
group with
|
||||
.IR rfork .
|
||||
.SH FILES
|
||||
.B /sys/lib/acid/thread
|
||||
contains useful
|
||||
.IR acid (1)
|
||||
functions for debugging threaded programs.
|
||||
.PP
|
||||
.B /sys/src/libthread/example.c
|
||||
contains a full example program.
|
||||
.SH SOURCE
|
||||
.B /sys/src/libthread
|
||||
.SH SEE ALSO
|
||||
.IR intro (2),
|
||||
.IR ioproc (2)
|
||||
Loading…
Add table
Add a link
Reference in a new issue