IOPROC(2) IOPROC(2)
NAME
closeioproc, iocall, ioclose, ioflush, iointerrupt, iodial,
ioopen, ioproc, ioread, ioreadn, 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 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, int *cdfp);
int iosleep(Ioproc *io, long n);
int ioflush(Ioproc *io);
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.
Ioopen, ioclose, ioread, ioreadn, iowrite, iosleep, and
iodial execute the similarly named library or system calls
(see open(2), read(2), and dial(2)) in the slave process
associated with io.
Iointerrupt interrupts the next or currently executing call
in the I/O proc. If there was no call executing, the inter-
rupt will stay pending and the next I/O call will get inter-
rupted.
Ioflush executes a non-op in the I/O proc. It is commonly
Page 1 Plan 9 (printed 11/5/25)
IOPROC(2) IOPROC(2)
called after iointerrupt to clear a pending interrupt.
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);
}
If the two relaythread instances were running in different
procs, the common access to tot would be unsafe.
Implement ioread:
static long
_ioread(va_list *arg)
{
Page 2 Plan 9 (printed 11/5/25)
IOPROC(2) IOPROC(2)
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);
}
SOURCE
/sys/src/libthread/io*.c
SEE ALSO
dial(2), open(2), read(2), sleep(2), thread(2)
Page 3 Plan 9 (printed 11/5/25)