1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 #include "threadimpl.h" 5 6 enum 7 { 8 STACK = 8192, 9 }; 10 11 void 12 iointerrupt(Ioproc *io) 13 { 14 if(!io->inuse) 15 return; 16 threadint(io->tid); 17 } 18 19 static void 20 xioproc(void *a) 21 { 22 Ioproc *io, *x; 23 io = a; 24 /* 25 * first recvp acquires the ioproc. 26 * second tells us that the data is ready. 27 */ 28 for(;;){ 29 while(recv(io->c, &x) == -1) 30 ; 31 if(x == 0) /* our cue to leave */ 32 break; 33 assert(x == io); 34 35 /* caller is now committed -- even if interrupted he'll return */ 36 while(recv(io->creply, &x) == -1) 37 ; 38 if(x == 0) /* caller backed out */ 39 continue; 40 assert(x == io); 41 42 io->ret = io->op(&io->arg); 43 if(io->ret < 0) 44 rerrstr(io->err, sizeof io->err); 45 while(send(io->creply, &io) == -1) 46 ; 47 while(recv(io->creply, &x) == -1) 48 ; 49 } 50 } 51 52 Ioproc* 53 ioproc(void) 54 { 55 Ioproc *io; 56 57 io = mallocz(sizeof(*io), 1); 58 if(io == nil) 59 sysfatal("ioproc malloc: %r"); 60 io->c = chancreate(sizeof(void*), 0); 61 io->creply = chancreate(sizeof(void*), 0); 62 io->tid = proccreate(xioproc, io, STACK); 63 return io; 64 } 65 66 void 67 closeioproc(Ioproc *io) 68 { 69 if(io == nil) 70 return; 71 iointerrupt(io); 72 while(send(io->c, 0) == -1) 73 ; 74 chanfree(io->c); 75 chanfree(io->creply); 76 free(io); 77 } 78