Blame


1 619085f0 2004-12-25 devnull #include <u.h>
2 619085f0 2004-12-25 devnull #include <libc.h>
3 619085f0 2004-12-25 devnull #include <thread.h>
4 619085f0 2004-12-25 devnull #include "ioproc.h"
5 619085f0 2004-12-25 devnull
6 619085f0 2004-12-25 devnull enum
7 619085f0 2004-12-25 devnull {
8 cbeb0b26 2006-04-01 devnull STACK = 32768
9 619085f0 2004-12-25 devnull };
10 619085f0 2004-12-25 devnull
11 619085f0 2004-12-25 devnull void
12 619085f0 2004-12-25 devnull iointerrupt(Ioproc *io)
13 619085f0 2004-12-25 devnull {
14 619085f0 2004-12-25 devnull if(!io->inuse)
15 619085f0 2004-12-25 devnull return;
16 af89fc10 2005-01-06 devnull fprint(2, "bug: cannot iointerrupt %p yet\n", io);
17 619085f0 2004-12-25 devnull }
18 619085f0 2004-12-25 devnull
19 619085f0 2004-12-25 devnull static void
20 619085f0 2004-12-25 devnull xioproc(void *a)
21 619085f0 2004-12-25 devnull {
22 619085f0 2004-12-25 devnull Ioproc *io, *x;
23 2c87dda8 2004-12-28 devnull
24 2c87dda8 2004-12-28 devnull threadsetname("ioproc");
25 619085f0 2004-12-25 devnull io = a;
26 619085f0 2004-12-25 devnull /*
27 619085f0 2004-12-25 devnull * first recvp acquires the ioproc.
28 619085f0 2004-12-25 devnull * second tells us that the data is ready.
29 619085f0 2004-12-25 devnull */
30 619085f0 2004-12-25 devnull for(;;){
31 619085f0 2004-12-25 devnull while(recv(io->c, &x) == -1)
32 619085f0 2004-12-25 devnull ;
33 619085f0 2004-12-25 devnull if(x == 0) /* our cue to leave */
34 619085f0 2004-12-25 devnull break;
35 619085f0 2004-12-25 devnull assert(x == io);
36 619085f0 2004-12-25 devnull
37 619085f0 2004-12-25 devnull /* caller is now committed -- even if interrupted he'll return */
38 619085f0 2004-12-25 devnull while(recv(io->creply, &x) == -1)
39 619085f0 2004-12-25 devnull ;
40 619085f0 2004-12-25 devnull if(x == 0) /* caller backed out */
41 619085f0 2004-12-25 devnull continue;
42 619085f0 2004-12-25 devnull assert(x == io);
43 619085f0 2004-12-25 devnull
44 619085f0 2004-12-25 devnull io->ret = io->op(&io->arg);
45 619085f0 2004-12-25 devnull if(io->ret < 0)
46 619085f0 2004-12-25 devnull rerrstr(io->err, sizeof io->err);
47 619085f0 2004-12-25 devnull while(send(io->creply, &io) == -1)
48 619085f0 2004-12-25 devnull ;
49 619085f0 2004-12-25 devnull while(recv(io->creply, &x) == -1)
50 619085f0 2004-12-25 devnull ;
51 619085f0 2004-12-25 devnull }
52 619085f0 2004-12-25 devnull }
53 619085f0 2004-12-25 devnull
54 619085f0 2004-12-25 devnull Ioproc*
55 619085f0 2004-12-25 devnull ioproc(void)
56 619085f0 2004-12-25 devnull {
57 619085f0 2004-12-25 devnull Ioproc *io;
58 619085f0 2004-12-25 devnull
59 619085f0 2004-12-25 devnull io = mallocz(sizeof(*io), 1);
60 619085f0 2004-12-25 devnull if(io == nil)
61 619085f0 2004-12-25 devnull sysfatal("ioproc malloc: %r");
62 619085f0 2004-12-25 devnull io->c = chancreate(sizeof(void*), 0);
63 619085f0 2004-12-25 devnull chansetname(io->c, "ioc%p", io->c);
64 619085f0 2004-12-25 devnull io->creply = chancreate(sizeof(void*), 0);
65 619085f0 2004-12-25 devnull chansetname(io->creply, "ior%p", io->c);
66 619085f0 2004-12-25 devnull io->tid = proccreate(xioproc, io, STACK);
67 619085f0 2004-12-25 devnull return io;
68 619085f0 2004-12-25 devnull }
69 619085f0 2004-12-25 devnull
70 619085f0 2004-12-25 devnull void
71 619085f0 2004-12-25 devnull closeioproc(Ioproc *io)
72 619085f0 2004-12-25 devnull {
73 619085f0 2004-12-25 devnull if(io == nil)
74 619085f0 2004-12-25 devnull return;
75 619085f0 2004-12-25 devnull iointerrupt(io);
76 619085f0 2004-12-25 devnull while(send(io->c, 0) == -1)
77 619085f0 2004-12-25 devnull ;
78 619085f0 2004-12-25 devnull chanfree(io->c);
79 619085f0 2004-12-25 devnull chanfree(io->creply);
80 619085f0 2004-12-25 devnull free(io);
81 619085f0 2004-12-25 devnull }
82 619085f0 2004-12-25 devnull
83 619085f0 2004-12-25 devnull long
84 619085f0 2004-12-25 devnull iocall(Ioproc *io, long (*op)(va_list*), ...)
85 619085f0 2004-12-25 devnull {
86 619085f0 2004-12-25 devnull char e[ERRMAX];
87 619085f0 2004-12-25 devnull int ret, inted;
88 619085f0 2004-12-25 devnull Ioproc *msg;
89 619085f0 2004-12-25 devnull
90 619085f0 2004-12-25 devnull if(send(io->c, &io) == -1){
91 619085f0 2004-12-25 devnull werrstr("interrupted");
92 619085f0 2004-12-25 devnull return -1;
93 619085f0 2004-12-25 devnull }
94 619085f0 2004-12-25 devnull assert(!io->inuse);
95 619085f0 2004-12-25 devnull io->inuse = 1;
96 619085f0 2004-12-25 devnull io->op = op;
97 619085f0 2004-12-25 devnull va_start(io->arg, op);
98 619085f0 2004-12-25 devnull msg = io;
99 619085f0 2004-12-25 devnull inted = 0;
100 619085f0 2004-12-25 devnull while(send(io->creply, &msg) == -1){
101 619085f0 2004-12-25 devnull msg = nil;
102 619085f0 2004-12-25 devnull inted = 1;
103 619085f0 2004-12-25 devnull }
104 619085f0 2004-12-25 devnull if(inted){
105 619085f0 2004-12-25 devnull werrstr("interrupted");
106 619085f0 2004-12-25 devnull return -1;
107 619085f0 2004-12-25 devnull }
108 619085f0 2004-12-25 devnull
109 619085f0 2004-12-25 devnull /*
110 619085f0 2004-12-25 devnull * If we get interrupted, we have stick around so that
111 619085f0 2004-12-25 devnull * the IO proc has someone to talk to. Send it an interrupt
112 619085f0 2004-12-25 devnull * and try again.
113 619085f0 2004-12-25 devnull */
114 619085f0 2004-12-25 devnull inted = 0;
115 619085f0 2004-12-25 devnull while(recv(io->creply, nil) == -1){
116 619085f0 2004-12-25 devnull inted = 1;
117 619085f0 2004-12-25 devnull iointerrupt(io);
118 619085f0 2004-12-25 devnull }
119 619085f0 2004-12-25 devnull USED(inted);
120 619085f0 2004-12-25 devnull va_end(io->arg);
121 619085f0 2004-12-25 devnull ret = io->ret;
122 619085f0 2004-12-25 devnull if(ret < 0)
123 619085f0 2004-12-25 devnull strecpy(e, e+sizeof e, io->err);
124 619085f0 2004-12-25 devnull io->inuse = 0;
125 619085f0 2004-12-25 devnull
126 619085f0 2004-12-25 devnull /* release resources */
127 619085f0 2004-12-25 devnull while(send(io->creply, &io) == -1)
128 619085f0 2004-12-25 devnull ;
129 619085f0 2004-12-25 devnull if(ret < 0)
130 619085f0 2004-12-25 devnull errstr(e, sizeof e);
131 619085f0 2004-12-25 devnull return ret;
132 619085f0 2004-12-25 devnull }