2004-04-10 18:53:55 +00:00
|
|
|
.TH THREAD 3
|
2003-09-30 17:47:41 +00:00
|
|
|
.SH NAME
|
|
|
|
alt,
|
|
|
|
chancreate,
|
|
|
|
chanfree,
|
|
|
|
chanprint,
|
2005-01-03 06:40:20 +00:00
|
|
|
chansetname,
|
2003-09-30 17:47:41 +00:00
|
|
|
mainstacksize,
|
|
|
|
proccreate,
|
|
|
|
procdata,
|
|
|
|
recv,
|
|
|
|
recvp,
|
|
|
|
recvul,
|
|
|
|
send,
|
|
|
|
sendp,
|
|
|
|
sendul,
|
|
|
|
nbrecv,
|
|
|
|
nbrecvp,
|
|
|
|
nbrecvul,
|
|
|
|
nbsend,
|
|
|
|
nbsendp,
|
|
|
|
nbsendul,
|
|
|
|
threadcreate,
|
|
|
|
threaddata,
|
2005-01-03 06:40:20 +00:00
|
|
|
threadexec,
|
|
|
|
threadexecl,
|
2003-09-30 17:47:41 +00:00
|
|
|
threadexits,
|
|
|
|
threadexitsall,
|
|
|
|
threadgetgrp,
|
|
|
|
threadgetname,
|
|
|
|
threadint,
|
|
|
|
threadintgrp,
|
|
|
|
threadkill,
|
|
|
|
threadkillgrp,
|
|
|
|
threadmain,
|
2020-12-30 05:10:11 +00:00
|
|
|
threadmaybackground,
|
2003-09-30 17:47:41 +00:00
|
|
|
threadnotify,
|
|
|
|
threadid,
|
|
|
|
threadpid,
|
2006-06-26 05:47:59 +00:00
|
|
|
threadpin,
|
|
|
|
threadunpin,
|
2003-09-30 17:47:41 +00:00
|
|
|
threadsetgrp,
|
|
|
|
threadsetname,
|
2005-01-03 06:40:20 +00:00
|
|
|
threadsetstate,
|
|
|
|
threadspawn,
|
2012-10-22 16:32:09 +00:00
|
|
|
threadspawnd,
|
2005-01-18 18:31:09 +00:00
|
|
|
threadspawnl,
|
2003-09-30 17:47:41 +00:00
|
|
|
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;
|
2005-01-03 06:40:20 +00:00
|
|
|
char *name;
|
2003-09-30 17:47:41 +00:00
|
|
|
};
|
|
|
|
.fi
|
|
|
|
.de XX
|
2004-04-19 19:22:56 +00:00
|
|
|
.if t .sp 0.5
|
|
|
|
.if n .sp
|
2003-09-30 17:47:41 +00:00
|
|
|
..
|
|
|
|
.PP
|
|
|
|
.nf
|
|
|
|
.ft L
|
|
|
|
.ta \w'\fLChannel* 'u +4n +4n +4n +4n
|
|
|
|
void threadmain(int argc, char *argv[])
|
2020-12-30 05:10:11 +00:00
|
|
|
int threadmaybackground(void)
|
2003-09-30 17:47:41 +00:00
|
|
|
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)
|
2006-06-26 05:47:59 +00:00
|
|
|
int threadpin(void)
|
|
|
|
int threadunpin(void)
|
2003-09-30 17:47:41 +00:00
|
|
|
.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
|
|
|
|
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
|
2005-01-18 18:31:09 +00:00
|
|
|
int threadspawnl(int fd[3], char *file, ...)
|
2005-01-03 06:40:20 +00:00
|
|
|
int threadspawn(int fd[3], char *file, char *args[])
|
2012-10-22 16:32:09 +00:00
|
|
|
int threadspawnd(int fd[3], char *file, char *args[], char *dir)
|
2005-01-03 06:40:20 +00:00
|
|
|
int threadexecl(Channel *cpid, int fd[3], char *file, ...)
|
|
|
|
int threadexec(Channel *cpid, int fd[3], char *file, char *args[])
|
2003-09-30 17:47:41 +00:00
|
|
|
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
|
2020-12-30 05:16:10 +00:00
|
|
|
.IR threadmain .
|
|
|
|
.PP
|
|
|
|
Every thread is backed by an operating system-provided
|
2020-01-09 03:47:51 +00:00
|
|
|
.I pthread
|
2020-12-30 05:16:10 +00:00
|
|
|
and runs on its system-provided stack;
|
|
|
|
.I mainstacksize
|
|
|
|
and the the stack size arguments to
|
|
|
|
.I proccreate
|
|
|
|
and
|
|
|
|
.I threadcreate
|
|
|
|
are ignored.
|
|
|
|
Although each thread is backed by a separate
|
|
|
|
.IR pthread ,
|
|
|
|
the threads in a proc are still scheduled non-preemptively
|
|
|
|
as on Plan 9 and as described below.
|
2003-09-30 17:47:41 +00:00
|
|
|
.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 .
|
2020-12-30 05:10:11 +00:00
|
|
|
Thread stacks are allocated in shared memory, making it valid to pass
|
2003-09-30 17:47:41 +00:00
|
|
|
pointers to stack variables between threads and procs.
|
2005-01-03 06:40:20 +00:00
|
|
|
.I Proccreate
|
2003-09-30 17:47:41 +00:00
|
|
|
creates a new proc, and inside that proc creates
|
|
|
|
a single thread as
|
|
|
|
.I threadcreate
|
|
|
|
would,
|
|
|
|
returning the id of the created thread.
|
2005-01-03 06:40:20 +00:00
|
|
|
.\" .I Procrfork
|
|
|
|
.\" creates the new proc by calling
|
|
|
|
.\" .B rfork
|
|
|
|
.\" (see
|
|
|
|
.\" .IR fork (3))
|
|
|
|
.\" 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
|
2020-12-30 05:10:11 +00:00
|
|
|
.\" is identical to
|
2005-01-03 06:40:20 +00:00
|
|
|
.\" .I procrfork
|
|
|
|
.\" with
|
|
|
|
.\" .I rforkflag
|
|
|
|
.\" set to zero.
|
2003-09-30 17:47:41 +00:00
|
|
|
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
|
2005-01-03 06:40:20 +00:00
|
|
|
When the last thread in
|
|
|
|
.IR 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.
|
2020-12-30 05:10:11 +00:00
|
|
|
This functionality can only be relied upon if the program defines a function
|
|
|
|
.I threadmaybackground
|
|
|
|
returning a non-zero result.
|
|
|
|
Programs that do not define such a
|
|
|
|
.I threadmaybackground
|
|
|
|
will crash instead should the last thread in
|
|
|
|
.IR threadmain 's
|
|
|
|
proc exit leaving behind other running procs.
|
2005-01-03 06:40:20 +00:00
|
|
|
.PP
|
2003-09-30 17:47:41 +00:00
|
|
|
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 ,
|
2005-01-03 06:40:20 +00:00
|
|
|
.IR threadexec ,
|
|
|
|
.IR threadexecl ,
|
2003-09-30 17:47:41 +00:00
|
|
|
.IR threadexits ,
|
2005-01-03 06:40:20 +00:00
|
|
|
.IR threadspawn ,
|
2012-10-22 16:32:09 +00:00
|
|
|
.IR threadspawnd ,
|
|
|
|
.IR threadspawnl ,
|
2003-09-30 17:47:41 +00:00
|
|
|
.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
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR lock (3) )
|
2003-09-30 17:47:41 +00:00
|
|
|
or channel communication.
|
|
|
|
System calls such as
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR read (3)
|
2003-09-30 17:47:41 +00:00
|
|
|
block the entire proc;
|
|
|
|
all threads in a proc block until the system call finishes.
|
|
|
|
.PP
|
2006-06-26 05:47:59 +00:00
|
|
|
.I Threadpin
|
|
|
|
disables scheduling inside a proc, `pinning' the current
|
|
|
|
thread as the only runnable one in the current proc.
|
|
|
|
.I Threadunpin
|
|
|
|
reenables scheduling, allowing other procs to run once the current
|
|
|
|
thread relinquishes the processor.
|
|
|
|
.I Threadpin
|
|
|
|
and
|
|
|
|
.I threadunpin
|
|
|
|
can lead to deadlock.
|
|
|
|
Used carefully, they can make library routines that use
|
|
|
|
.B qlocks
|
|
|
|
appear atomic relative to the current proc, like a system call.
|
|
|
|
.PP
|
2003-09-30 17:47:41 +00:00
|
|
|
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
|
2005-01-03 06:40:20 +00:00
|
|
|
Also for debugging,
|
|
|
|
threads have a string state associated with them.
|
|
|
|
.I Threadsetstate
|
|
|
|
sets the state string.
|
2020-12-30 05:10:11 +00:00
|
|
|
There is no
|
2005-01-03 06:40:20 +00:00
|
|
|
.IR threadgetstate ;
|
|
|
|
since the thread scheduler resets the state to
|
|
|
|
.B Running
|
2020-12-30 05:10:11 +00:00
|
|
|
every time it runs the thread,
|
2005-01-03 06:40:20 +00:00
|
|
|
it is only useful for debuggers to inspect the state.
|
|
|
|
.PP
|
2003-09-30 17:47:41 +00:00
|
|
|
.I Threaddata
|
|
|
|
returns a pointer to a per-thread pointer
|
|
|
|
that may be modified by threaded programs for
|
|
|
|
per-thread storage.
|
2020-12-30 05:10:11 +00:00
|
|
|
Similarly,
|
2003-09-30 17:47:41 +00:00
|
|
|
.I procdata
|
|
|
|
returns a pointer to a per-proc pointer.
|
|
|
|
.PP
|
2005-01-03 06:40:20 +00:00
|
|
|
.I Threadexecl
|
2003-09-30 17:47:41 +00:00
|
|
|
and
|
2005-01-03 06:40:20 +00:00
|
|
|
.I threadexec
|
2003-09-30 17:47:41 +00:00
|
|
|
are threaded analogues of
|
|
|
|
.I exec
|
|
|
|
and
|
|
|
|
.I execl
|
|
|
|
(see
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR exec (3) );
|
2003-09-30 17:47:41 +00:00
|
|
|
on success,
|
2005-01-03 06:40:20 +00:00
|
|
|
they replace the calling thread
|
2003-09-30 17:47:41 +00:00
|
|
|
and invoke the external program, never returning.
|
2005-01-03 06:40:20 +00:00
|
|
|
(Unlike on Plan 9, the calling thread need not be the only thread in its proc\(emthe other
|
|
|
|
threads will continue executing.)
|
2003-09-30 17:47:41 +00:00
|
|
|
On error, they return \-1.
|
|
|
|
If
|
|
|
|
.I cpid
|
|
|
|
is not null, the pid of the invoked program
|
|
|
|
will be sent along
|
|
|
|
.I cpid
|
2005-01-03 06:40:20 +00:00
|
|
|
(using
|
|
|
|
.IR sendul )
|
2003-09-30 17:47:41 +00:00
|
|
|
once the program has been started, or \-1 will be sent if an
|
|
|
|
error occurs.
|
2005-01-03 06:40:20 +00:00
|
|
|
.I Threadexec
|
2003-09-30 17:47:41 +00:00
|
|
|
and
|
2005-01-03 06:40:20 +00:00
|
|
|
.I threadexecl
|
2003-09-30 17:47:41 +00:00
|
|
|
will not access their arguments after sending a result
|
|
|
|
along
|
|
|
|
.IR cpid .
|
|
|
|
Thus, programs that malloc the
|
|
|
|
.I argv
|
|
|
|
passed to
|
2005-01-03 06:40:20 +00:00
|
|
|
.I threadexec
|
2003-09-30 17:47:41 +00:00
|
|
|
can safely free it once they have
|
|
|
|
received the
|
|
|
|
.I cpid
|
|
|
|
response.
|
2005-01-03 06:40:20 +00:00
|
|
|
.PP
|
|
|
|
.I Threadexecl
|
|
|
|
and
|
|
|
|
.I threadexec
|
2020-12-30 05:10:11 +00:00
|
|
|
will duplicate
|
2005-01-03 06:40:20 +00:00
|
|
|
(see
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR dup (3) )
|
2005-01-03 06:40:20 +00:00
|
|
|
the three file descriptors in
|
2020-12-30 05:10:11 +00:00
|
|
|
.I fd
|
2005-01-03 06:40:20 +00:00
|
|
|
onto standard input, output, and error for the external program
|
|
|
|
and then close them in the calling thread.
|
|
|
|
Beware of code that sets
|
|
|
|
.IP
|
|
|
|
.EX
|
|
|
|
fd[0] = 0;
|
|
|
|
fd[1] = 1;
|
|
|
|
fd[2] = 2;
|
|
|
|
.EE
|
2005-01-13 04:49:19 +00:00
|
|
|
.LP
|
2005-01-03 06:40:20 +00:00
|
|
|
to use the current standard files. The correct code is
|
|
|
|
.IP
|
|
|
|
.EX
|
|
|
|
fd[0] = dup(0, -1);
|
|
|
|
fd[1] = dup(1, -1);
|
|
|
|
fd[2] = dup(2, -1);
|
|
|
|
.EE
|
|
|
|
.PP
|
2005-01-18 18:31:09 +00:00
|
|
|
.I Threadspawnl
|
|
|
|
and
|
|
|
|
.I threadspawn
|
|
|
|
are like
|
|
|
|
.I threadexecl
|
|
|
|
and
|
2005-01-03 06:40:20 +00:00
|
|
|
.I threadexec
|
2005-01-18 18:31:09 +00:00
|
|
|
but do not replace the current thread.
|
|
|
|
They return the pid of the invoked program on success, or
|
2005-01-03 06:40:20 +00:00
|
|
|
\-1 on error.
|
2012-10-22 16:32:09 +00:00
|
|
|
.I Threadspawnd
|
|
|
|
is like
|
|
|
|
.I 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.
|
2005-01-03 06:40:20 +00:00
|
|
|
.PP
|
2003-09-30 17:47:41 +00:00
|
|
|
.I Threadwaitchan
|
|
|
|
returns a channel of pointers to
|
|
|
|
.B Waitmsg
|
|
|
|
structures (see
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR wait (3) ).
|
2003-09-30 17:47:41 +00:00
|
|
|
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
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR malloc (3)
|
2003-09-30 17:47:41 +00:00
|
|
|
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" .
|
2009-04-30 15:00:40 +00:00
|
|
|
.IR Chancreate
|
2020-12-30 05:10:11 +00:00
|
|
|
allocates a new channel
|
2003-09-30 17:47:41 +00:00
|
|
|
for messages of size
|
2020-12-30 05:10:11 +00:00
|
|
|
.I elsize
|
2003-09-30 17:47:41 +00:00
|
|
|
and with a buffer holding
|
|
|
|
.I nel
|
|
|
|
messages.
|
|
|
|
If
|
|
|
|
.I nel
|
|
|
|
is zero, the channel is unbuffered.
|
|
|
|
.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
|
2005-01-03 06:40:20 +00:00
|
|
|
The
|
|
|
|
.B name
|
|
|
|
element in the
|
|
|
|
.B Channel
|
|
|
|
structure is a description intended for use in debugging.
|
|
|
|
.I Chansetname
|
|
|
|
sets the name.
|
|
|
|
.PP
|
2003-09-30 17:47:41 +00:00
|
|
|
.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
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR print (3)
|
2003-09-30 17:47:41 +00:00
|
|
|
and sends the result to the channel
|
|
|
|
.IR c.
|
|
|
|
The string delivered by
|
|
|
|
.I chanprint
|
|
|
|
is allocated with
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR malloc (3)
|
2003-09-30 17:47:41 +00:00
|
|
|
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
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR notify (3) ).
|
2003-09-30 17:47:41 +00:00
|
|
|
.PP
|
|
|
|
It is safe to use
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR sysfatal (3)
|
2003-09-30 17:47:41 +00:00
|
|
|
in threaded programs.
|
|
|
|
.I Sysfatal
|
|
|
|
will print the error string and call
|
|
|
|
.IR threadexitsall .
|
|
|
|
.PP
|
2005-01-03 06:40:20 +00:00
|
|
|
It is not safe to call
|
2003-09-30 17:47:41 +00:00
|
|
|
.IR rfork
|
2005-01-03 06:40:20 +00:00
|
|
|
in a threaded program, except to call
|
|
|
|
.B rfork(RFNOTEG)
|
|
|
|
from the main proc before any other procs have been created.
|
|
|
|
To create new processes, use
|
|
|
|
.IR proccreate .
|
|
|
|
.\" .PP
|
2020-12-30 05:10:11 +00:00
|
|
|
.\" It is safe to use
|
2005-01-03 06:40:20 +00:00
|
|
|
.\" .IR rfork
|
|
|
|
.\" (see
|
|
|
|
.\" .IR fork (3))
|
|
|
|
.\" 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
|
2020-12-30 05:10:11 +00:00
|
|
|
.\" and
|
2005-01-03 06:40:20 +00:00
|
|
|
.\" .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 .
|
2003-09-30 17:47:41 +00:00
|
|
|
.SH FILES
|
2005-01-11 17:37:33 +00:00
|
|
|
.B \*9/acid/thread
|
2003-09-30 17:47:41 +00:00
|
|
|
contains useful
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR acid (1)
|
2003-09-30 17:47:41 +00:00
|
|
|
functions for debugging threaded programs.
|
|
|
|
.PP
|
2005-01-11 17:37:33 +00:00
|
|
|
.B \*9/src/libthread/test
|
2005-01-03 06:40:20 +00:00
|
|
|
contains some example programs.
|
2003-09-30 17:47:41 +00:00
|
|
|
.SH SOURCE
|
2005-01-11 17:37:33 +00:00
|
|
|
.B \*9/src/libthread
|
2003-09-30 17:47:41 +00:00
|
|
|
.SH SEE ALSO
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR intro (3) ,
|
|
|
|
.MR ioproc (3)
|
2005-01-03 06:40:20 +00:00
|
|
|
.SH BUGS
|
|
|
|
To avoid name conflicts,
|
|
|
|
.IR alt ,
|
|
|
|
.IR nbrecv ,
|
|
|
|
.IR nbrecvp ,
|
|
|
|
.IR nbrecvul ,
|
|
|
|
.IR nbsend ,
|
|
|
|
.IR nbsendp ,
|
|
|
|
.IR nbsendul ,
|
|
|
|
.IR recv ,
|
|
|
|
.IR recvp ,
|
|
|
|
.IR recvul ,
|
|
|
|
.IR send ,
|
|
|
|
.IR sendp ,
|
|
|
|
and
|
|
|
|
.IR sendul
|
|
|
|
are defined as macros that expand to
|
|
|
|
.IR chanalt ,
|
|
|
|
.IR channbrecv ,
|
|
|
|
and so on.
|
2005-01-13 04:49:19 +00:00
|
|
|
.I Yield
|
2005-01-03 06:40:20 +00:00
|
|
|
is defined as a macro that expands to
|
|
|
|
.IR threadyield .
|
2005-01-13 04:49:19 +00:00
|
|
|
See
|
2020-08-16 00:07:38 +00:00
|
|
|
.MR intro (3) .
|
2005-01-03 06:40:20 +00:00
|
|
|
.PP
|
2008-07-21 17:23:17 +00:00
|
|
|
Threadint,
|
|
|
|
threadintgrp,
|
|
|
|
threadkill,
|
|
|
|
threadkillgrp and threadpid are unimplemented.
|
|
|
|
.PP
|
2005-01-03 06:40:20 +00:00
|
|
|
The implementation of
|
|
|
|
.I threadnotify
|
|
|
|
may not be correct.
|
2005-03-18 19:01:16 +00:00
|
|
|
.PP
|
|
|
|
There appears to be a race in the Linux NPTL
|
|
|
|
implementation of
|
|
|
|
.I pthread_exit .
|
|
|
|
Call
|
|
|
|
.I threadexitsall
|
|
|
|
rather than coordinating a simultaneous
|
|
|
|
.I threadexits
|
|
|
|
among many threads.
|