| .TH IOPROC 3 |
| .SH NAME |
| closeioproc, |
| iocall, |
| ioclose, |
| iointerrupt, |
| iodial, |
| ioopen, |
| ioproc, |
| ioread, |
| ioread9pmsg, |
| ioreadn, |
| iorecvfd, |
| iosendfd, |
| 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 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); |
| .XX |
| 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 Ioclose , |
| .IR iodial , |
| .IR ioopen , |
| .IR ioread , |
| .IR ioread9pmsg , |
| .IR ioreadn , |
| .IR iorecvfd , |
| .IR iosendfd , |
| .IR iosleep , |
| and |
| .I iowrite |
| execute the |
| similarly named library or system calls |
| (see |
| .IR close (2), |
| .IR dial (3), |
| .IR open (3), |
| .IR read (3), |
| .IR fcall (3), |
| .IR sendfd (3), |
| and |
| .IR sleep (3)) |
| in the slave process associated with |
| .IR io . |
| It is an error to execute more than one call |
| at a time in an I/O proc. |
| .PP |
| .I Iointerrupt |
| interrupts the call currently executing in the I/O proc. |
| If no call is executing, |
| .IR iointerrupt |
| is a no-op. |
| .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 |
| The two |
| .I relaythread |
| instances are running in the same proc, so the |
| common access to |
| .I tot |
| is safe. |
| .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 \*9/src/libthread |
| .SH SEE ALSO |
| .IR dial (3), |
| .IR open (3), |
| .IR read (3), |
| .IR thread (3) |
| .SH BUGS |
| .I Iointerrupt |
| is currently unimplemented. |
| .PP |
| C99 disallows the use of pointers to |
| .BR va_list . |
| This interface will have to change to |
| use pointers to a structure containing a |
| .BR va_list . |