TH IOPROC 2
SH NAME
closeioproc,
iocall,
ioclose,
ioflush,
iointerrupt,
iodial,
ioopen,
ioproc,
ioread,
ioreadn,
iosleep,
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, int *cdfp);
int     iosleep(Ioproc *io, long n);
XX
int     ioflush(Ioproc *io);
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 ,
IR iosleep ,
and
IR iodial
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 .
PP
I Iointerrupt
interrupts the next or currently executing call in the I/O proc.  If
there was no call executing, the interrupt will stay pending and the
next I/O call will get interrupted.
PP
I Ioflush
executes a non-op in the I/O proc. It is commonly called after
IR iointerrupt
to clear a pending interrupt.
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.
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 sleep (2),
IR thread (2)