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