IOPROC(2)                                               IOPROC(2)

     NAME
          closeioproc, iocall, ioclose, iodial, iointerrupt, 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)
          int     iosleep(Ioproc *io, long milliseconds)
          long    iowrite(Ioproc *io, int fd, void *a, long n)
          int     iodial(Ioproc *io, char *addr, char *local, char *dir, char *cdfp)

          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, iosleep, iowrite, and
          iodial execute the similarly named library or system calls
          (see open(2), read(2), sleep(2), and dial(2)) 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 .

     Page 1                       Plan 9            (printed 12/22/24)

     IOPROC(2)                                               IOPROC(2)

          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);

     Page 2                       Plan 9            (printed 12/22/24)

     IOPROC(2)                                               IOPROC(2)

                   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 12/22/24)