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(int socket);
    int	iosendfd(int socket, int fd);
    int	iosleep(int 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 similarly 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.

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)
        {
        	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
/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 interface will have to change to use pointers to a structure containing a va_list.