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