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
iointerrupt(Ioproc * io)12 iointerrupt(Ioproc *io)
13 {
14 if(!io->inuse)
15 return;
16 threadint(io->tid);
17 }
18
19 static void
xioproc(void * a)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*
ioproc(void)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
closeioproc(Ioproc * io)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