IOPROC(3) IOPROC(3)
NAME
closeioproc, iocall, ioclose, iointerrupt, iodial, ioopen,
ioproc, ioread, ioread9pmsg, ioreadn, iorecvfd, iosendfd,
iosleep, iowrite - slave I/O processes for threaded programs
SYNOPSIS
#include <u.h>
#include <libc.h>
#include <thread.h>
typedef struct Ioproc Ioproc;
Ioproc* ioproc(void);
int ioclose(Ioproc *io, int fd);
int iodial(Ioproc *io, char *addr, char *local, char *dir, char *cdfp);
int ioopen(Ioproc *io, char *file, int omode);
long ioread(Ioproc *io, int fd, void *a, long n);
int ioread9pmsg(Ioproc *io, int fd, void *a, uint n);
long ioreadn(Ioproc *io, int fd, void *a, long n);
int iorecvfd(Ioproc *io, int socket);
int iosendfd(Ioproc *io, int socket, int fd);
int iosleep(Ioproc *io, long milli);
long iowrite(Ioproc *io, int fd, void *a, long n);
void iointerrupt(Ioproc *io);
void closeioproc(Ioproc *io);
long iocall(Ioproc *io, long (*op)(va_list *arg), ...);
DESCRIPTION
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.
Ioproc forks a new slave proc and returns a pointer to the
Ioproc associated with it. Ioproc uses mallocz and
proccreate; if either fails, it calls sysfatal rather than
return an error.
Ioclose, iodial, ioopen, ioread, ioread9pmsg, ioreadn,
iorecvfd, iosendfd, iosleep, and iowrite execute the simi-
larly named library or system calls (see close(2), dial(3),
open(3), read(3), fcall(3), sendfd(3), and sleep(3)) in the
slave process associated with io. It is an error to execute
more than one call at a time in an I/O proc.
Iointerrupt interrupts the call currently executing in the
I/O proc. If no call is executing, iointerrupt is a no-op.
Page 1 Plan 9 (printed 11/18/25)
IOPROC(3) IOPROC(3)
Closeioproc terminates the I/O proc and frees the associated
Ioproc .
Iocall is a primitive that may be used to implement more
slave I/O routines. Iocall arranges for op to be called in
io's proc, with arg set to the variable parameter list,
returning the value that op returns.
EXAMPLE
Relay messages between two file descriptors, counting the
total number of bytes seen:
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);
}
The two relaythread instances are running in the same proc,
so the common access to tot is safe.
Implement ioread:
static long
_ioread(va_list *arg)
{
int fd;
void *a;
Page 2 Plan 9 (printed 11/18/25)
IOPROC(3) IOPROC(3)
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);
}
SOURCE
/usr/local/plan9/src/libthread
SEE ALSO
dial(3), open(3), read(3), thread(3)
BUGS
Iointerrupt is currently unimplemented.
C99 disallows the use of pointers to va_list. This inter-
face will have to change to use pointers to a structure con-
taining a va_list.
Page 3 Plan 9 (printed 11/18/25)