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