Documentation fixes
[vlp.git] / src / int / rpcall.c
1 #include "depend.h"
2 #include "genint.h"
3 #include "int.h"
4 #include "process.h"
5 #include "intproto.h"
6
7 /**
8  * @file
9  */
10
11 #ifndef NO_PROTOTYPES
12 static bool isenabled(word,word);
13 static bool rpcready(word);
14 static void bitaccess(word, word, int *, char *);
15 static void dupmask(word);
16 #else
17 static bool isenabled();
18 static bool rpcready();
19 static void bitaccess();
20 static void dupmask();
21 #endif
22
23 /**
24  * preprocess RPC request
25  */
26 void rpc1(message *msg)
27 {
28         word pix, prot;
29         procdescr *p;
30         message *msg1;
31
32         pix = msg->control.receiver.pix;
33         p = &process[pix];
34         if (p->mark != msg->control.receiver.mark)
35                 senderr(RTEREFTN, &msg->control.sender);
36
37         msg1 = (message *) ballocate(sizeof(message));
38
39         if (msg1 == NULL)
40                 errsignal(RTEMEMOV);
41
42         moveblock((char *) msg, (char *) msg1, (word) sizeof(message));
43         prot = msg->control.par;
44         if (isenabled(pix, prot)) {
45                 p->msgqueue = minsert(p->msgqueue, msg1);
46
47                 if (p->status == ACCEPTING)
48                         activate(pix);
49         }
50         else
51                 p->rpcwait = minsert(p->rpcwait, msg1);
52 }
53
54
55 void rpc2()
56 {
57         if (rpcready(thispix))
58                 rpc3();
59 }
60
61 /**
62  * Actual remote procedure call
63  */
64 void rpc3()
65 {
66         word prot, ah, am;
67         message *msg;
68
69         /* remove first RPC message (enabled) */
70         msg = mfront(thisp->msgqueue);
71
72         /*
73         fprintf(stderr, "rpc(thisp=%d) from: node=%d, pix=%d, mark=%d\n",
74                 thispix,
75                 msg->control.sender.node,
76                 msg->control.sender.pix,
77                 msg->control.sender.mark
78         );*/
79
80         thisp->msgqueue = qremove(thisp->msgqueue);
81         /* disable all procedures */
82         pushmask(thispix);
83         prot = msg->control.par;
84
85         /* open procedure object */
86         slopen(prot, &thisp->procref, &ah, &am);
87
88         {
89                 virtaddr v;
90                 mess2obj(thisp, &(msg->control.sender), &v);
91                 /* set up remote DL */
92                 storevirt(v, am + M[am] + RPCDL);
93         }
94
95         moveparams(thispix, am, msg, PARIN, SAVEPAR);
96
97         /* transfer control to procedure */
98         go(ah, am);
99
100         free(msg);
101 }
102
103 /* After return from RPC */
104 void rpcend(message *msg)
105 {
106         word pix, am;
107         procdescr *p;
108
109         pix = msg->control.receiver.pix;
110
111
112         p = &process[pix];
113         /* template physical address */
114         am = p->M[temporary];
115         moveparams(pix, am, msg, PAROUT, SAVEPAR);
116         /* resume process waiting for RPC */
117         activate(pix);
118 }
119
120
121 static void bitaccess(word pix, word prot, int *bytenr, char *bitmask)
122 {
123         int bitnr;
124
125         bitnr = prot-prototype[process[pix].prot]->maskbase;
126         *bytenr = bitnr / 8;
127         *bitmask = (char)(unsigned char)(1 << (bitnr % 8));
128 }
129
130 /* Enable remote procedure */
131 void enable(word pix, word prot)
132 {
133         mask m;
134         int bytenr;
135         char bitmask;
136
137         m = top(process[pix].rpcmask);
138         bitaccess(pix, prot, &bytenr, &bitmask);
139         m[bytenr] |= bitmask;
140 }
141
142 /**
143  * Disable remote procedure
144  */
145 void disable(word pix, word prot)
146 {
147         mask m;
148         int bytenr;
149         char bitmask;
150
151         m = top(process[pix].rpcmask);
152         bitaccess(pix, prot, &bytenr, &bitmask);
153         m[bytenr] &= ~ bitmask;
154 }
155
156 /**
157  * Check if RPC allowed
158  */
159 static bool isenabled(word pix, word prot)
160 {
161         mask m;
162         int bytenr;
163         char bitmask;
164
165         m = top(process[pix].rpcmask);
166         bitaccess(pix, prot, &bytenr, &bitmask);
167         return m[bytenr] & bitmask;
168 }
169
170 /**
171  * Push empty RPC mask onto stack
172  */
173 void pushmask(word pix)
174 {
175         mask m;
176         int i, size;
177
178         size = prototype[process[pix].prot]->masksize;
179         m = (mask) ballocate(size);
180         if (m == NULL)
181                 errsignal(RTEMEMOV);
182         for (i = 0; i < size; i++) {
183                 /* disable all */
184                 m[i] = '\0';
185         }
186         process[pix].rpcmask = push(process[pix].rpcmask, m);
187 }
188
189 /**
190  * Duplicate RPC mask from stack top
191  */
192 static void dupmask(word pix)
193 {
194         mask m;
195         int size;
196
197         size = prototype[process[pix].prot]->masksize;
198         m = (mask) ballocate(size);
199         if (m == NULL)
200                 errsignal(RTEMEMOV);
201         moveblock(top(process[pix].rpcmask), m, (word) size);
202         process[pix].rpcmask = push(process[pix].rpcmask, m);
203 }
204
205 /**
206  * Pop RPC mask from stack (restore)
207  */
208 void popmask(word pix)
209 {
210         mask m;
211
212         m = top(process[pix].rpcmask);
213         process[pix].rpcmask = pop(process[pix].rpcmask);
214         free((char *) m);
215 }
216
217 /**
218  * Check if any waiting RPC is enabled
219  */
220 void evaluaterpc(word pix)
221 {
222         queue q;
223         message *msg;
224
225         q = process[pix].rpcwait;
226         if (!qempty(q)) {
227                 do {
228                         msg = mfront(q);
229                         if (isenabled(pix, msg->control.par)) {
230                                 process[pix].msgqueue =
231                                         mpush(process[pix].msgqueue, msg);
232                                 process[pix].rpcwait =
233                                         mdelete(process[pix].rpcwait, msg);
234                                 return;
235                         }
236                         q = qrotate(q);
237                 } while (q != process[pix].rpcwait);
238         }
239 }
240
241 /**
242  * Accept remote procedure call
243  */
244 void rpc_accept(word length)
245 {
246         int i;
247
248         dupmask(thispix);
249         for (i = 0;  i < length;  i++)
250                 enable(thispix, virtprot(M[ic++]));
251
252         evaluaterpc(thispix);
253
254         if (!rpcready(thispix))
255                 passivate(ACCEPTING);
256 }
257
258
259 static bool rpcready(word pix)
260 {
261         procdescr *p;
262         message *msg;
263         word prot;
264
265         p = &process[pix];
266         while (!qempty(p->msgqueue)) {
267                 msg = mfront(p->msgqueue);
268                 prot = msg->control.par;
269                 if (isenabled(pix, prot))
270                         return TRUE;
271                 p->msgqueue = qremove(p->msgqueue);
272                 p->rpcwait = minsert(p->rpcwait, msg);
273         }
274         return FALSE;
275 }
276
277 /**
278  * Get actual prototype for virtual
279  */
280 word virtprot(word prot)
281 {
282         bool sign;
283         word virtnr;
284
285         sign = (prot < 0);
286         prot = absolute(prot);
287         virtnr = prototype[ prot ]->virtnumber;
288         if (virtnr != -1)
289                 prot = M[prototype[thisp->prot]->virtlist + virtnr];
290
291         if (sign)
292                 return -prot;
293         else
294                 return prot;
295 }
296
297