Blame


1 d3df3087 2003-12-06 devnull /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
2 d3df3087 2003-12-06 devnull /* See COPYRIGHT */
3 d3df3087 2003-12-06 devnull
4 d3df3087 2003-12-06 devnull /*
5 d3df3087 2003-12-06 devnull * Generic RPC packet multiplexor. Inspired by but not derived from
6 d3df3087 2003-12-06 devnull * Plan 9 kernel. Originally developed as part of Tra, later used in
7 d3df3087 2003-12-06 devnull * libnventi, and then finally split out into a generic library.
8 d3df3087 2003-12-06 devnull */
9 d3df3087 2003-12-06 devnull
10 d3df3087 2003-12-06 devnull #include <u.h>
11 d3df3087 2003-12-06 devnull #include <libc.h>
12 d3df3087 2003-12-06 devnull #include <mux.h>
13 d3df3087 2003-12-06 devnull
14 d3df3087 2003-12-06 devnull static int gettag(Mux*, Muxrpc*);
15 d3df3087 2003-12-06 devnull static void puttag(Mux*, Muxrpc*);
16 d3df3087 2003-12-06 devnull static void enqueue(Mux*, Muxrpc*);
17 d3df3087 2003-12-06 devnull static void dequeue(Mux*, Muxrpc*);
18 d3df3087 2003-12-06 devnull
19 d3df3087 2003-12-06 devnull void
20 d3df3087 2003-12-06 devnull muxinit(Mux *mux)
21 d3df3087 2003-12-06 devnull {
22 b214663d 2004-01-09 devnull memset(&mux->lk, 0, sizeof(Mux)-offsetof(Mux, lk));
23 d3df3087 2003-12-06 devnull mux->tagrend.l = &mux->lk;
24 b214663d 2004-01-09 devnull mux->rpcfork.l = &mux->lk;
25 d3df3087 2003-12-06 devnull mux->sleep.next = &mux->sleep;
26 d3df3087 2003-12-06 devnull mux->sleep.prev = &mux->sleep;
27 d3df3087 2003-12-06 devnull }
28 d3df3087 2003-12-06 devnull
29 d3df3087 2003-12-06 devnull void*
30 d3df3087 2003-12-06 devnull muxrpc(Mux *mux, void *tx)
31 d3df3087 2003-12-06 devnull {
32 ceb04770 2003-12-09 devnull int tag;
33 d3df3087 2003-12-06 devnull Muxrpc *r, *r2;
34 d3df3087 2003-12-06 devnull void *p;
35 d3df3087 2003-12-06 devnull
36 d3df3087 2003-12-06 devnull /* must malloc because stack could be private */
37 d3df3087 2003-12-06 devnull r = mallocz(sizeof(Muxrpc), 1);
38 a28c0548 2005-07-13 devnull if(r == nil){
39 a28c0548 2005-07-13 devnull werrstr("mallocz: %r");
40 d3df3087 2003-12-06 devnull return nil;
41 a28c0548 2005-07-13 devnull }
42 d3df3087 2003-12-06 devnull r->r.l = &mux->lk;
43 d3df3087 2003-12-06 devnull
44 43db87f1 2004-12-27 devnull /* assign the tag, add selves to response queue */
45 ceb04770 2003-12-09 devnull qlock(&mux->lk);
46 d3df3087 2003-12-06 devnull tag = gettag(mux, r);
47 43db87f1 2004-12-27 devnull //print("gettag %p %d\n", r, tag);
48 43db87f1 2004-12-27 devnull enqueue(mux, r);
49 ceb04770 2003-12-09 devnull qunlock(&mux->lk);
50 43db87f1 2004-12-27 devnull
51 43db87f1 2004-12-27 devnull /* actually send the packet */
52 ceb04770 2003-12-09 devnull if(tag < 0 || mux->settag(mux, tx, tag) < 0 || _muxsend(mux, tx) < 0){
53 a28c0548 2005-07-13 devnull werrstr("settag/send tag %d: %r", tag);
54 a28c0548 2005-07-13 devnull fprint(2, "%r\n");
55 ceb04770 2003-12-09 devnull qlock(&mux->lk);
56 d165fa68 2005-01-04 devnull dequeue(mux, r);
57 d3df3087 2003-12-06 devnull puttag(mux, r);
58 ceb04770 2003-12-09 devnull qunlock(&mux->lk);
59 d3df3087 2003-12-06 devnull return nil;
60 d3df3087 2003-12-06 devnull }
61 d3df3087 2003-12-06 devnull
62 d3df3087 2003-12-06 devnull qlock(&mux->lk);
63 d3df3087 2003-12-06 devnull /* wait for our packet */
64 c6687d45 2004-09-21 devnull while(mux->muxer && !r->p){
65 d3df3087 2003-12-06 devnull rsleep(&r->r);
66 c6687d45 2004-09-21 devnull }
67 d3df3087 2003-12-06 devnull
68 d3df3087 2003-12-06 devnull /* if not done, there's no muxer: start muxing */
69 d3df3087 2003-12-06 devnull if(!r->p){
70 d3df3087 2003-12-06 devnull if(mux->muxer)
71 d3df3087 2003-12-06 devnull abort();
72 d3df3087 2003-12-06 devnull mux->muxer = 1;
73 d3df3087 2003-12-06 devnull while(!r->p){
74 d3df3087 2003-12-06 devnull qunlock(&mux->lk);
75 d3df3087 2003-12-06 devnull p = _muxrecv(mux);
76 d3df3087 2003-12-06 devnull if(p)
77 0b22e9bd 2005-01-30 devnull tag = mux->gettag(mux, p) - mux->mintag;
78 d3df3087 2003-12-06 devnull else
79 d3df3087 2003-12-06 devnull tag = ~0;
80 43db87f1 2004-12-27 devnull //print("mux tag %d\n", tag);
81 d3df3087 2003-12-06 devnull qlock(&mux->lk);
82 d3df3087 2003-12-06 devnull if(p == nil){ /* eof -- just give up and pass the buck */
83 d3df3087 2003-12-06 devnull dequeue(mux, r);
84 d3df3087 2003-12-06 devnull break;
85 d3df3087 2003-12-06 devnull }
86 d3df3087 2003-12-06 devnull /* hand packet to correct sleeper */
87 d3df3087 2003-12-06 devnull if(tag < 0 || tag >= mux->mwait){
88 d3df3087 2003-12-06 devnull fprint(2, "%s: bad rpc tag %ux\n", argv0, tag);
89 d3df3087 2003-12-06 devnull /* must leak packet! don't know how to free it! */
90 d3df3087 2003-12-06 devnull continue;
91 d3df3087 2003-12-06 devnull }
92 d3df3087 2003-12-06 devnull r2 = mux->wait[tag];
93 d165fa68 2005-01-04 devnull if(r2 == nil || r2->prev == nil){
94 43db87f1 2004-12-27 devnull fprint(2, "%s: bad rpc tag %ux (no one waiting on that tag)\n", argv0, tag);
95 43db87f1 2004-12-27 devnull /* must leak packet! don't know how to free it! */
96 43db87f1 2004-12-27 devnull continue;
97 43db87f1 2004-12-27 devnull }
98 d3df3087 2003-12-06 devnull r2->p = p;
99 e95a7088 2003-12-09 devnull dequeue(mux, r2);
100 d3df3087 2003-12-06 devnull rwakeup(&r2->r);
101 d3df3087 2003-12-06 devnull }
102 d3df3087 2003-12-06 devnull mux->muxer = 0;
103 d3df3087 2003-12-06 devnull
104 d3df3087 2003-12-06 devnull /* if there is anyone else sleeping, wake them to mux */
105 d3df3087 2003-12-06 devnull if(mux->sleep.next != &mux->sleep)
106 d3df3087 2003-12-06 devnull rwakeup(&mux->sleep.next->r);
107 d3df3087 2003-12-06 devnull }
108 43db87f1 2004-12-27 devnull //print("finished %p\n", r);
109 d3df3087 2003-12-06 devnull p = r->p;
110 d165fa68 2005-01-04 devnull puttag(mux, r);
111 d3df3087 2003-12-06 devnull qunlock(&mux->lk);
112 a28c0548 2005-07-13 devnull if(p == nil)
113 a28c0548 2005-07-13 devnull werrstr("unexpected eof");
114 d3df3087 2003-12-06 devnull return p;
115 d3df3087 2003-12-06 devnull }
116 d3df3087 2003-12-06 devnull
117 d3df3087 2003-12-06 devnull static void
118 d3df3087 2003-12-06 devnull enqueue(Mux *mux, Muxrpc *r)
119 d3df3087 2003-12-06 devnull {
120 d3df3087 2003-12-06 devnull r->next = mux->sleep.next;
121 d3df3087 2003-12-06 devnull r->prev = &mux->sleep;
122 d3df3087 2003-12-06 devnull r->next->prev = r;
123 d3df3087 2003-12-06 devnull r->prev->next = r;
124 d3df3087 2003-12-06 devnull }
125 d3df3087 2003-12-06 devnull
126 d3df3087 2003-12-06 devnull static void
127 d3df3087 2003-12-06 devnull dequeue(Mux *mux, Muxrpc *r)
128 d3df3087 2003-12-06 devnull {
129 d3df3087 2003-12-06 devnull r->next->prev = r->prev;
130 d3df3087 2003-12-06 devnull r->prev->next = r->next;
131 d3df3087 2003-12-06 devnull r->prev = nil;
132 d3df3087 2003-12-06 devnull r->next = nil;
133 d3df3087 2003-12-06 devnull }
134 d3df3087 2003-12-06 devnull
135 d3df3087 2003-12-06 devnull static int
136 d3df3087 2003-12-06 devnull gettag(Mux *mux, Muxrpc *r)
137 d3df3087 2003-12-06 devnull {
138 ceb04770 2003-12-09 devnull int i, mw;
139 ceb04770 2003-12-09 devnull Muxrpc **w;
140 d3df3087 2003-12-06 devnull
141 ceb04770 2003-12-09 devnull for(;;){
142 ceb04770 2003-12-09 devnull /* wait for a free tag */
143 ceb04770 2003-12-09 devnull while(mux->nwait == mux->mwait){
144 ceb04770 2003-12-09 devnull if(mux->mwait < mux->maxtag-mux->mintag){
145 ceb04770 2003-12-09 devnull mw = mux->mwait;
146 ceb04770 2003-12-09 devnull if(mw == 0)
147 ceb04770 2003-12-09 devnull mw = 1;
148 ceb04770 2003-12-09 devnull else
149 ceb04770 2003-12-09 devnull mw <<= 1;
150 ceb04770 2003-12-09 devnull w = realloc(mux->wait, mw*sizeof(w[0]));
151 ceb04770 2003-12-09 devnull if(w == nil)
152 ceb04770 2003-12-09 devnull return -1;
153 e95a7088 2003-12-09 devnull memset(w+mux->mwait, 0, (mw-mux->mwait)*sizeof(w[0]));
154 ceb04770 2003-12-09 devnull mux->wait = w;
155 ceb04770 2003-12-09 devnull mux->freetag = mux->mwait;
156 ceb04770 2003-12-09 devnull mux->mwait = mw;
157 ceb04770 2003-12-09 devnull break;
158 ceb04770 2003-12-09 devnull }
159 ceb04770 2003-12-09 devnull rsleep(&mux->tagrend);
160 d3df3087 2003-12-06 devnull }
161 ceb04770 2003-12-09 devnull
162 ceb04770 2003-12-09 devnull i=mux->freetag;
163 ceb04770 2003-12-09 devnull if(mux->wait[i] == 0)
164 ceb04770 2003-12-09 devnull goto Found;
165 ceb04770 2003-12-09 devnull for(; i<mux->mwait; i++)
166 ceb04770 2003-12-09 devnull if(mux->wait[i] == 0)
167 ceb04770 2003-12-09 devnull goto Found;
168 ceb04770 2003-12-09 devnull for(i=0; i<mux->freetag; i++)
169 ceb04770 2003-12-09 devnull if(mux->wait[i] == 0)
170 ceb04770 2003-12-09 devnull goto Found;
171 ceb04770 2003-12-09 devnull /* should not fall out of while without free tag */
172 ceb04770 2003-12-09 devnull fprint(2, "libfs: nwait botch\n");
173 ceb04770 2003-12-09 devnull abort();
174 ceb04770 2003-12-09 devnull }
175 ceb04770 2003-12-09 devnull
176 ceb04770 2003-12-09 devnull Found:
177 ceb04770 2003-12-09 devnull mux->nwait++;
178 ceb04770 2003-12-09 devnull mux->wait[i] = r;
179 ceb04770 2003-12-09 devnull r->tag = i+mux->mintag;
180 0b22e9bd 2005-01-30 devnull return r->tag;
181 d3df3087 2003-12-06 devnull }
182 d3df3087 2003-12-06 devnull
183 d3df3087 2003-12-06 devnull static void
184 d3df3087 2003-12-06 devnull puttag(Mux *mux, Muxrpc *r)
185 d3df3087 2003-12-06 devnull {
186 ceb04770 2003-12-09 devnull int i;
187 ceb04770 2003-12-09 devnull
188 ceb04770 2003-12-09 devnull i = r->tag - mux->mintag;
189 ceb04770 2003-12-09 devnull assert(mux->wait[i] == r);
190 ceb04770 2003-12-09 devnull mux->wait[i] = nil;
191 d3df3087 2003-12-06 devnull mux->nwait--;
192 ceb04770 2003-12-09 devnull mux->freetag = i;
193 d3df3087 2003-12-06 devnull rwakeup(&mux->tagrend);
194 ceb04770 2003-12-09 devnull free(r);
195 d3df3087 2003-12-06 devnull }