Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / sources / new-s5r4 / 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 #   ifdef RPCDBG
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 #   endif
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 #ifdef RPCDBG
95 fprintf(stderr,"activate after rpc(thisp=%d)\n",pix);fflush(stderr);
96 #endif
97     p = &process[ pix ];
98     am = p->M[ temporary ];             /* template physical address */
99     moveparams(pix, am, msg, PAROUT, SAVEPAR);
100     activate(pix);                      /* resume process waiting for RPC */
101 }
102
103
104 static void bitaccess(pix, prot, bytenr, bitmask)
105 word pix, prot;
106 int *bytenr;
107 char *bitmask;
108 {
109     int bitnr;
110
111     bitnr = prot-prototype[ process[ pix ].prot ]->maskbase;
112     *bytenr = bitnr / 8;
113     *bitmask = (char)(unsigned char)( 1 << (bitnr % 8) );
114 }
115
116
117 void enable(pix, prot)                  /* Enable remote procedure */
118 word pix, prot;
119 {
120     mask m;
121     int bytenr;
122     char bitmask;
123
124     m = top(process[ pix ].rpcmask);
125     bitaccess(pix, prot, &bytenr, &bitmask);
126     m[ bytenr ] |= bitmask;
127 }
128
129
130 void disable(pix, prot)                 /* Disable remote procedure */
131 word pix, 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 static bool isenabled(pix, prot)                /* Check if RPC allowed */
144 word pix, prot;
145 {
146     mask m;
147     int bytenr;
148     char bitmask;
149
150     m = top(process[ pix ].rpcmask);
151     bitaccess(pix, prot, &bytenr, &bitmask);
152     return( m[ bytenr ] & bitmask );
153 }
154
155
156 void pushmask(pix)                      /* Push empty RPC mask onto stack */
157 word pix;
158 {
159     mask m;
160     int i, size;
161
162     size = prototype[ process[ pix ].prot ]->masksize;
163     m = (mask) ballocate(size);
164     if (m == NULL) errsignal(RTEMEMOV);
165     for (i = 0;  i < size;  i++ )  m[ i ] = '\0';       /* disable all */
166     process[ pix ].rpcmask = push(process[ pix ].rpcmask, m);
167 }
168
169
170 static void dupmask(pix)                /* Duplicate RPC mask from stack top */
171 word pix;
172 {
173     mask m;
174     int size;
175
176     size = prototype[ process[ pix ].prot ]->masksize;
177     m = (mask) ballocate(size);
178     if (m == NULL) errsignal(RTEMEMOV);
179     moveblock(top(process[ pix ].rpcmask), m, (word) size);
180     process[ pix ].rpcmask = push(process[ pix ].rpcmask, m);
181 }
182
183
184 void popmask(pix)                       /* Pop RPC mask from stack (restore) */
185 word pix;
186 {
187     mask m;
188
189     m = top(process[ pix ].rpcmask);
190     process[ pix ].rpcmask = pop(process[ pix ].rpcmask);
191     free((char *) m);
192 }
193
194
195 void evaluaterpc(pix)           /* Check if any waiting RPC is enabled */
196 word pix;
197 {
198     queue q;
199     message *msg;
200
201     q = process[ pix ].rpcwait;
202     if (!qempty(q))
203     {
204         do
205         {
206             msg = mfront(q);
207             if (isenabled(pix, msg->control.par))
208             {
209                 process[ pix ].msgqueue = mpush(process[ pix ].msgqueue, msg);
210                 process[ pix ].rpcwait = mdelete(process[ pix ].rpcwait, msg);
211                 return;
212             }
213             q = qrotate(q);
214         } while (q != process[ pix ].rpcwait);
215     }
216 }
217
218
219 void rpc_accept(length)                 /* Accept remote procedure call */
220 word length;
221 {
222     int i;
223
224     dupmask(thispix);
225     for (i = 0;  i < length;  i++)
226         enable(thispix, virtprot(M[ ic++ ]));
227     evaluaterpc(thispix);
228     if (!rpcready(thispix))
229         passivate(ACCEPTING);
230 }
231
232
233 static bool rpcready(pix)
234 word pix;
235 {
236     procdescr *p;
237     message *msg;
238     word prot;
239
240     p = &process[ pix ];
241     while (!qempty(p->msgqueue))
242     {
243         msg = mfront(p->msgqueue);
244         prot = msg->control.par;
245         if (isenabled(pix, prot))  return(TRUE);
246         p->msgqueue = qremove(p->msgqueue);
247         p->rpcwait = minsert(p->rpcwait, msg);
248     }
249     return(FALSE);
250 }
251
252
253 word virtprot(prot)                     /* Get actual prototype for virtual */
254 word prot;
255 {
256     bool sign;
257     word virtnr;
258
259     sign = (prot < 0);
260     prot = absolute(prot);
261     virtnr = prototype[ prot ]->virtnumber;
262     if (virtnr != -1) prot = M[ prototype[ thisp->prot ]->virtlist+virtnr ];
263     if (sign) return(-prot);  else return(prot);
264 }
265
266