Reorg
This commit is contained in:
parent
2df2758496
commit
522b0689c3
180 changed files with 245 additions and 6144 deletions
|
|
@ -1,6 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I${PREFIX}/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
|
|
@ -1,27 +1,7 @@
|
|||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
9SRC=..
|
||||
include $(9SRC)/Makehdr
|
||||
|
||||
LIB=libthread.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libthread
|
||||
NAME=libthread
|
||||
|
||||
OFILES=\
|
||||
$(OBJTYPE).$O\
|
||||
|
|
@ -53,73 +33,17 @@ OFILES=\
|
|||
sched.$O\
|
||||
|
||||
HFILES=\
|
||||
thread.h\
|
||||
$(9SRC)/include/thread.h\
|
||||
label.h\
|
||||
threadimpl.h\
|
||||
|
||||
all: $(LIB)
|
||||
include $(9SRC)/Makesyslib
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 thread.3 $(PREFIX)/man/man3/thread.3
|
||||
install -m 0644 ioproc.3 $(PREFIX)/man/man3/ioproc.3
|
||||
install -m 0644 thread.h $(PREFIX)/include/thread.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
tprimes: $(LIB) tprimes.$O
|
||||
$(CC) -o tprimes tprimes.$O $(LIB) -L$(PREFIX)/lib -l9 -lfmt -lutf
|
||||
tprimes: tprimes.$O
|
||||
$(CC) -o tprimes tprimes.$O -L$(9SRC)/lib -lthread -l9 -lfmt -lutf
|
||||
|
||||
texec: $(LIB) texec.$O
|
||||
$(CC) -o texec texec.$O $(LIB) -L$(PREFIX)/lib -l9 -lfmt -lutf
|
||||
$(CC) -o texec texec.$O -L$(9SRC)/lib -lthread -l9 -lfmt -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
CLEANFILES+=tprimes texec
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I/usr/X11R6/include -I../sam -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I/usr/X11R6/include -I../sam -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
LIB=libthread.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libthread
|
||||
NAME=libthread
|
||||
|
||||
OFILES=\
|
||||
$(OBJTYPE).$O\
|
||||
asm-$(SYSNAME)-$(OBJTYPE).$O\
|
||||
channel.$O\
|
||||
chanprint.$O\
|
||||
create.$O\
|
||||
debug.$O\
|
||||
exec-unix.$O\
|
||||
exit.$O\
|
||||
getpid.$O\
|
||||
id.$O\
|
||||
iocall.$O\
|
||||
ioclose.$O\
|
||||
ioopen.$O\
|
||||
ioproc.$O\
|
||||
ioread.$O\
|
||||
ioreadn.$O\
|
||||
iowrite.$O\
|
||||
kill.$O\
|
||||
lib.$O\
|
||||
main.$O\
|
||||
memset.$O\
|
||||
memsetd.$O\
|
||||
note.$O\
|
||||
proctab.$O\
|
||||
ref.$O\
|
||||
rendez.$O\
|
||||
sched.$O\
|
||||
|
||||
HFILES=\
|
||||
thread.h\
|
||||
label.h\
|
||||
threadimpl.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 thread.3 $(PREFIX)/man/man3/thread.3
|
||||
install -m 0644 ioproc.3 $(PREFIX)/man/man3/ioproc.3
|
||||
install -m 0644 thread.h $(PREFIX)/include/thread.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
tprimes: $(LIB) tprimes.$O
|
||||
$(CC) -o tprimes tprimes.$O $(LIB) -L$(PREFIX)/lib -l9 -lfmt -lutf
|
||||
|
||||
texec: $(LIB) texec.$O
|
||||
$(CC) -o texec texec.$O $(LIB) -L$(PREFIX)/lib -l9 -lfmt -lutf
|
||||
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
--- Makefile ---
|
||||
# New ports collection makefile for: libthread
|
||||
# Date Created: 11 Feb 2003
|
||||
# Whom: rsc
|
||||
#
|
||||
|
||||
PORTNAME= libthread
|
||||
PORTVERSION= 1.0
|
||||
CATEGORIES= devel
|
||||
MASTER_SITES= http://pdos.lcs.mit.edu/~rsc/software/
|
||||
DISTNAME= libthread
|
||||
EXTRACT_SUFX= .tgz
|
||||
|
||||
MAINTAINER= rsc@post.harvard.edu
|
||||
|
||||
MAN3= print.3 fmtinstall.3
|
||||
MLINKS= XXX
|
||||
USE_REINPLACE= XXX (wkj says yes)
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
post-patch:
|
||||
${REINPLACE_CMD} -e 's,@@LOCAL@@,${PREFIX},g' ${WRKSRC}/Makefile
|
||||
|
||||
.include <bsd.port.post.mk>
|
||||
|
||||
--- pkg-comment ---
|
||||
Plan 9 thread library
|
||||
--- pkg-descr ---
|
||||
Libthread is a port of Plan 9's thread library.
|
||||
|
||||
WWW: http://pdos.lcs.mit.edu/~rsc/software/
|
||||
WWW: http://plan9.bell-labs.com/magic/man2html/2/thread
|
||||
|
||||
Russ Cox
|
||||
rsc@post.harvard.edu
|
||||
--- pkg-plist ---
|
||||
lib/libthread.a
|
||||
include/thread.h
|
||||
--- /dev/null ---
|
||||
This is just a way to make sure blank lines don't
|
||||
creep into pkg-plist.
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#include "threadimpl.h"
|
||||
|
||||
#define free
|
||||
Pqueue _threadpq;
|
||||
|
||||
static int nextID(void);
|
||||
|
|
|
|||
|
|
@ -1,179 +0,0 @@
|
|||
.TH IOPROC 2
|
||||
.SH NAME
|
||||
closeioproc,
|
||||
iocall,
|
||||
ioclose,
|
||||
iointerrupt,
|
||||
iodial,
|
||||
ioopen,
|
||||
ioproc,
|
||||
ioread,
|
||||
ioreadn,
|
||||
iowrite \- slave I/O processes for threaded programs
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
.de XX
|
||||
.ift .sp 0.5
|
||||
.ifn .sp
|
||||
..
|
||||
.EX
|
||||
.ta \w'Ioproc* 'u
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
.sp
|
||||
typedef struct Ioproc Ioproc;
|
||||
.sp
|
||||
Ioproc* ioproc(void);
|
||||
.XX
|
||||
int ioopen(Ioproc *io, char *file, int omode);
|
||||
int ioclose(Ioproc *io, int fd);
|
||||
long ioread(Ioproc *io, int fd, void *a, long n);
|
||||
long ioreadn(Ioproc *io, int fd, void *a, long n);
|
||||
long iowrite(Ioproc *io, int fd, void *a, long n);
|
||||
int iodial(Ioproc *io, char *addr, char *local, char *dir, char *cdfp);
|
||||
.XX
|
||||
void iointerrupt(Ioproc *io);
|
||||
void closeioproc(Ioproc *io);
|
||||
.XX
|
||||
long iocall(Ioproc *io, long (*op)(va_list *arg), ...);
|
||||
.EE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
These routines provide access to I/O in slave procs.
|
||||
Since the I/O itself is done in a slave proc, other threads
|
||||
in the calling proc can run while the calling thread
|
||||
waits for the I/O to complete.
|
||||
.PP
|
||||
.I Ioproc
|
||||
forks a new slave proc and returns a pointer to the
|
||||
.B Ioproc
|
||||
associated with it.
|
||||
.I Ioproc
|
||||
uses
|
||||
.I mallocz
|
||||
and
|
||||
.IR proccreate ;
|
||||
if either fails, it calls
|
||||
.I sysfatal
|
||||
rather than return an error.
|
||||
.PP
|
||||
.IR Ioopen ,
|
||||
.IR ioclose ,
|
||||
.IR ioread ,
|
||||
.IR ioreadn ,
|
||||
.IR iowrite ,
|
||||
and
|
||||
.IR iodial
|
||||
are execute the
|
||||
similarly named library or system calls
|
||||
(see
|
||||
.IR open (2),
|
||||
.IR read (2),
|
||||
and
|
||||
.IR dial (2))
|
||||
in the slave process associated with
|
||||
.IR io .
|
||||
It is an error to execute more than one call
|
||||
at a time in an I/O proc.
|
||||
.PP
|
||||
.I Iointerrupt
|
||||
interrupts the call currently executing in the I/O proc.
|
||||
If no call is executing,
|
||||
.IR iointerrupt
|
||||
is a no-op.
|
||||
.PP
|
||||
.I Closeioproc
|
||||
terminates the I/O proc and frees the associated
|
||||
.B Ioproc .
|
||||
.PP
|
||||
.I Iocall
|
||||
is a primitive that may be used to implement
|
||||
more slave I/O routines.
|
||||
.I Iocall
|
||||
arranges for
|
||||
.I op
|
||||
to be called in
|
||||
.IR io 's
|
||||
proc, with
|
||||
.I arg
|
||||
set to the variable parameter list,
|
||||
returning the value that
|
||||
.I op
|
||||
returns.
|
||||
.SH EXAMPLE
|
||||
Relay messages between two file descriptors,
|
||||
counting the total number of bytes seen:
|
||||
.IP
|
||||
.EX
|
||||
.ta +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u
|
||||
int tot;
|
||||
|
||||
void
|
||||
relaythread(void *v)
|
||||
{
|
||||
int *fd, n;
|
||||
char buf[1024];
|
||||
Ioproc *io;
|
||||
|
||||
fd = v;
|
||||
io = ioproc();
|
||||
while((n = ioread(io, fd[0], buf, sizeof buf)) > 0){
|
||||
if(iowrite(io, fd[1], buf, n) != n)
|
||||
sysfatal("iowrite: %r");
|
||||
tot += n;
|
||||
}
|
||||
closeioproc(io);
|
||||
}
|
||||
|
||||
void
|
||||
relay(int fd0, int fd1)
|
||||
{
|
||||
int fd[4];
|
||||
|
||||
fd[0] = fd[3] = fd0;
|
||||
fd[1] = fd[2] = fd1;
|
||||
threadcreate(relaythread, fd, 8192);
|
||||
threadcreate(relaythread, fd+2, 8192);
|
||||
}
|
||||
.EE
|
||||
.LP
|
||||
If the two
|
||||
.I relaythread
|
||||
instances were running in different procs, the
|
||||
common access to
|
||||
.I tot
|
||||
would be unsafe.
|
||||
.EE
|
||||
.PP
|
||||
Implement
|
||||
.IR ioread :
|
||||
.IP
|
||||
.EX
|
||||
static long
|
||||
_ioread(va_list *arg)
|
||||
{
|
||||
int fd;
|
||||
void *a;
|
||||
long n;
|
||||
|
||||
fd = va_arg(*arg, int);
|
||||
a = va_arg(*arg, void*);
|
||||
n = va_arg(*arg, long);
|
||||
return read(fd, a, n);
|
||||
}
|
||||
|
||||
long
|
||||
ioread(Ioproc *io, int fd, void *a, long n)
|
||||
{
|
||||
return iocall(io, _ioread, fd, a, n);
|
||||
}
|
||||
.EE
|
||||
.SH SOURCE
|
||||
.B /sys/src/libthread/io*.c
|
||||
.SH SEE ALSO
|
||||
.IR dial (2),
|
||||
.IR open (2),
|
||||
.IR read (2),
|
||||
.IR thread (2)
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
<../libutf/mkfile
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
Summary: Port of Plan 9's thread library
|
||||
Name: libthread
|
||||
Version: 2.0
|
||||
Release: 1
|
||||
Group: Development/C
|
||||
Copyright: BSD-like
|
||||
Packager: Russ Cox <rsc@post.harvard.edu>
|
||||
Source: http://pdos.lcs.mit.edu/~rsc/software/libthread-2.0.tgz
|
||||
URL: http://pdos.lcs.mit.edu/~rsc/software/#libthread
|
||||
|
||||
%description
|
||||
Libthread is a port of Plan 9's thread library
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
make
|
||||
|
||||
%install
|
||||
make install
|
||||
|
||||
%files
|
||||
/usr/local/include/thread.h
|
||||
/usr/local/lib/libthread.a
|
||||
/usr/local/man/man3/thread.3
|
||||
/usr/local/man/man3/ioproc.3
|
||||
|
|
@ -1,576 +0,0 @@
|
|||
.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)
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
#ifndef _THREADH_
|
||||
#define _THREADH_ 1
|
||||
|
||||
/* avoid conflicts with socket library */
|
||||
#undef send
|
||||
#define send _threadsend
|
||||
#undef recv
|
||||
#define recv _threadrecv
|
||||
|
||||
typedef struct Alt Alt;
|
||||
typedef struct Channel Channel;
|
||||
typedef struct Ref Ref;
|
||||
|
||||
/* Channel structure. S is the size of the buffer. For unbuffered channels
|
||||
* s is zero. v is an array of s values. If s is zero, v is unused.
|
||||
* f and n represent the state of the queue pointed to by v.
|
||||
*/
|
||||
|
||||
enum {
|
||||
Nqwds = 2,
|
||||
Nqshift = 5, // 2log #of bits in long
|
||||
Nqmask = - 1,
|
||||
Nqbits = (1 << Nqshift) * 2,
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
int s; // Size of the channel (may be zero)
|
||||
unsigned int f; // Extraction point (insertion pt: (f + n) % s)
|
||||
unsigned int n; // Number of values in the channel
|
||||
int e; // Element size
|
||||
int freed; // Set when channel is being deleted
|
||||
volatile Alt **qentry; // Receivers/senders waiting (malloc)
|
||||
volatile int nentry; // # of entries malloc-ed
|
||||
unsigned char v[1]; // Array of s values in the channel
|
||||
};
|
||||
|
||||
|
||||
/* Channel operations for alt: */
|
||||
typedef enum {
|
||||
CHANEND,
|
||||
CHANSND,
|
||||
CHANRCV,
|
||||
CHANNOP,
|
||||
CHANNOBLK,
|
||||
} ChanOp;
|
||||
|
||||
struct Alt {
|
||||
Channel *c; /* channel */
|
||||
void *v; /* pointer to value */
|
||||
ChanOp op; /* operation */
|
||||
|
||||
/* the next variables are used internally to alt
|
||||
* they need not be initialized
|
||||
*/
|
||||
Channel **tag; /* pointer to rendez-vous tag */
|
||||
int entryno; /* entry number */
|
||||
};
|
||||
|
||||
struct Ref {
|
||||
long ref;
|
||||
};
|
||||
|
||||
int alt(Alt alts[]);
|
||||
Channel* chancreate(int elemsize, int bufsize);
|
||||
int chaninit(Channel *c, int elemsize, int elemcnt);
|
||||
void chanfree(Channel *c);
|
||||
int chanprint(Channel *, char *, ...);
|
||||
long decref(Ref *r); /* returns 0 iff value is now zero */
|
||||
void incref(Ref *r);
|
||||
int nbrecv(Channel *c, void *v);
|
||||
void* nbrecvp(Channel *c);
|
||||
unsigned long nbrecvul(Channel *c);
|
||||
int nbsend(Channel *c, void *v);
|
||||
int nbsendp(Channel *c, void *v);
|
||||
int nbsendul(Channel *c, unsigned long v);
|
||||
int proccreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
|
||||
int procrfork(void (*f)(void *arg), void *arg, unsigned int stacksize, int flag);
|
||||
void** procdata(void);
|
||||
void procexec(Channel *, char *, char *[]);
|
||||
void procexecl(Channel *, char *, ...);
|
||||
int recv(Channel *c, void *v);
|
||||
void* recvp(Channel *c);
|
||||
unsigned long recvul(Channel *c);
|
||||
int send(Channel *c, void *v);
|
||||
int sendp(Channel *c, void *v);
|
||||
int sendul(Channel *c, unsigned long v);
|
||||
int threadcreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
|
||||
void** threaddata(void);
|
||||
void threadexits(char *);
|
||||
void threadexitsall(char *);
|
||||
int threadgetgrp(void); /* return thread group of current thread */
|
||||
char* threadgetname(void);
|
||||
void threadint(int); /* interrupt thread */
|
||||
void threadintgrp(int); /* interrupt threads in grp */
|
||||
void threadkill(int); /* kill thread */
|
||||
void threadkillgrp(int); /* kill threads in group */
|
||||
void threadmain(int argc, char *argv[]);
|
||||
void threadnonotes(void);
|
||||
int threadnotify(int (*f)(void*, char*), int in);
|
||||
int threadid(void);
|
||||
int threadpid(int);
|
||||
int threadsetgrp(int); /* set thread group, return old */
|
||||
void threadsetname(char *name);
|
||||
Channel* threadwaitchan(void);
|
||||
int tprivalloc(void);
|
||||
void tprivfree(int);
|
||||
void **tprivaddr(int);
|
||||
void yield(void);
|
||||
|
||||
long threadstack(void);
|
||||
|
||||
extern int mainstacksize;
|
||||
|
||||
/* slave I/O processes */
|
||||
typedef struct Ioproc Ioproc;
|
||||
|
||||
Ioproc* ioproc(void);
|
||||
void closeioproc(Ioproc*);
|
||||
void iointerrupt(Ioproc*);
|
||||
|
||||
int ioclose(Ioproc*, int);
|
||||
int iodial(Ioproc*, char*, char*, char*, int*);
|
||||
int ioopen(Ioproc*, char*, int);
|
||||
long ioread(Ioproc*, int, void*, long);
|
||||
long ioreadn(Ioproc*, int, void*, long);
|
||||
long iowrite(Ioproc*, int, void*, long);
|
||||
int iosleep(Ioproc*, long);
|
||||
|
||||
long iocall(Ioproc*, long (*)(va_list*), ...);
|
||||
void ioret(Ioproc*, int);
|
||||
|
||||
#endif /* _THREADH_ */
|
||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue