diff options
Diffstat (limited to 'src/libthread/ioproc.c')
-rw-r--r-- | src/libthread/ioproc.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/libthread/ioproc.c b/src/libthread/ioproc.c new file mode 100644 index 00000000..2b2a6025 --- /dev/null +++ b/src/libthread/ioproc.c @@ -0,0 +1,74 @@ +#include "threadimpl.h" + +enum +{ + STACK = 8192, +}; + +void +iointerrupt(Ioproc *io) +{ + if(!io->inuse) + return; + threadint(io->tid); +} + +static void +xioproc(void *a) +{ + Ioproc *io, *x; + io = a; + /* + * first recvp acquires the ioproc. + * second tells us that the data is ready. + */ + for(;;){ + while(recv(io->c, &x) == -1) + ; + if(x == 0) /* our cue to leave */ + break; + assert(x == io); + + /* caller is now committed -- even if interrupted he'll return */ + while(recv(io->creply, &x) == -1) + ; + if(x == 0) /* caller backed out */ + continue; + assert(x == io); + + io->ret = io->op(&io->arg); + if(io->ret < 0) + rerrstr(io->err, sizeof io->err); + while(send(io->creply, &io) == -1) + ; + while(recv(io->creply, &x) == -1) + ; + } +} + +Ioproc* +ioproc(void) +{ + Ioproc *io; + + io = mallocz(sizeof(*io), 1); + if(io == nil) + sysfatal("ioproc malloc: %r"); + io->c = chancreate(sizeof(void*), 0); + io->creply = chancreate(sizeof(void*), 0); + io->tid = proccreate(xioproc, io, STACK); + return io; +} + +void +closeioproc(Ioproc *io) +{ + if(io == nil) + return; + iointerrupt(io); + while(send(io->c, 0) == -1) + ; + chanfree(io->c); + chanfree(io->creply); + free(io); +} |