16 /* Process management */
18 /** process descriptor table */
19 procdescr process[MAXPROCESS];
21 /** pointer to current process descr */
24 /** current process index */
27 /** Round-Robin queue */
30 /** TRUE if operating in network */
33 /** queue of waiting messages */
34 message globmsgqueue[MAXMSGQUEUE];
36 /** number of waiting messages */
39 /** pointers to message queue */
40 int msghead = 0, msgtail = 0;
42 /** this machine node number */
45 /** console node number */
48 /** TRUE if remote node */
51 /** TRUE if must re-schedule */
52 bool reschedule = TRUE;
57 static void ansprot(message *);
58 static void localkill(message *);
60 static void backcreate(message *);
61 static void createprocess(message *);
62 static void localerror(message *);
63 static void killprocess(word);
64 static void mkglobal(word);
67 static void ansprot();
68 static void localkill();
70 static void backcreate();
71 static void createprocess();
72 static void localerror();
73 static void killprocess();
74 static void mkglobal();
80 /** pointer to Global Info Segment */
87 # ifndef NO_PROTOTYPES
88 static void signal_catch(void);
90 static void signal_catch();
92 static void signal_catch() {
101 signal(SIGALRM, signal_catch);
106 /** Choose next ready process to exec */
109 /* STRONGLY machine dependent */
114 signal(SIGALRM, signal_catch);
119 /* the most expensive method */
121 /* context switch is needed */
122 if (reschedule || c != last) {
124 #elif MSDOS && ( WORD_16BIT || DWORD_16BIT )
125 /* DOS real memory model */
128 static char *clk = (char *) 0x0040006CL;
130 /* context switch is needed */
131 if (reschedule || c != last) {
136 c = ginf->hundredths >> 3;
137 /* context switch is needed */
138 if (reschedule || c != last) {
141 #error Scheduler time counting method not implemented !
144 /* wait for event if no processes */
145 if (!(qempty(ready))) {
146 /* find another ready process */
147 ready = qrotate(ready);
148 /* transfer control to it */
149 transfer(pfront(ready));
155 /** Context switch to another process */
156 void transfer(word pix)
159 /* optimized for case of one process */
163 /* previous process is alive */
165 /* store previous context */
170 /* and load new context */
172 thisp = &process[thispix];
177 param = thisp->param;
178 apt = thisp->prochead + M[thisp->prochead];
179 display = apt + dispoff;
180 display2 = apt + disp2off;
183 /** Resume process on this node */
184 void activate(word pix)
186 /* flag process as ready to execute */
187 process[pix].status = EXECUTING;
188 /* insert into ready queue */
189 ready = pinsert(ready, pix);
190 /* force context switch */
193 fprintf(stderr, "activate process %d\n", pix);
197 /** Passivate process */
198 void passivate(int newstatus)
200 /* change to some wait status */
201 thisp->status = newstatus;
202 /* remove from ready queue */
203 ready = qremove(ready);
204 /* force context switch */
207 fprintf(stderr, "passivate process %d to state %d\n", thispix, newstatus);
212 /** Copy parameters from object to message or vice versa. */
213 void moveparams(word pix, word am, message *msg, int par1, int dir)
217 word i, tpd, ap, pd, prim, offset;
222 ptr = prototype[p->M[am + PROTNUM]];
223 cp = (char *) msg->params;
225 /* loop through parameters */
226 for (i = 0; i < ptr->lthparlist; i++) {
228 offset = M[ptr->parlist + i];
229 /* type description of param */
230 tpd = M[ptr->pfdescr + i];
234 cflag = (pd == PARIN || pd == PARINOUT || pd == FORMFUNC
237 cflag = (pd == PAROUT || pd == PARINOUT);
240 if (pd == FORMFUNC || pd == FORMPROC) {
244 else if (M[M[tpd + 2]] == CLASSTYPE) {
249 prim = M[tpd + 2] - ipradr;
251 /* process or coroutine */
252 convert = (prim == 4 || prim == 5);
255 /* param appetite in bytes */
258 /* copy parameter in right direction */
261 /* we always load parameters from OUR process */
262 assert(pix == thispix);
267 word ah = M[am + offset];
268 if (!isprocess((virtaddr*)(M + am + offset)) &&
269 M[ah + 1] == M[am + offset + 1]) {
270 if (prototype[M[M[ah] + PROTNUM]]->kind == PROCESS) {
273 pa.mark = thisp->mark;
276 /* only process may be global */
277 /*pat errsignal(RTENONGL); */
278 /*pat*/ obj2mess(p->M,(virtaddr*)(p->M+am+offset),&pa);
281 obj2mess(M, (virtaddr*)(M + am + offset), &pa);
285 obj2mess(p->M,(virtaddr*)(p->M+am+offset),&pa);
287 moveblock((char *)&pa, cp, ap = sizeof(procaddr));
289 moveblock((char *) &p->M[am + offset], cp, ap);
295 ap = sizeof(procaddr);
296 moveblock(cp, (char *)&pa, ap);
297 mess2obj(p, &pa, (virtaddr*)(p->M + am + offset));
299 moveblock(cp, (char *)&p->M[am + offset], ap);
305 assert(cp-msg->params <= sizeof(msg->params));
310 /* Determine node number for process */
311 word getnode(word am)
317 p = prototype[M[am + PROTNUM]]->preflist;
318 while (prototype[M[p]]->kind != PROCESS)
320 ptr = prototype[M[p]];
321 if (ptr->lthpreflist == 1)
324 i = prototype[M[p - 1]]->lthparlist;
325 return (M[am + M[ptr->parlist + i]]);
328 /* Perform RESUME instruction */
329 void resume(virtaddr *virt)
333 /* is it process realy ? */
334 if (isprocess(virt)) {
335 msg.control.type = RESUME;
336 obj2mess(M, virt, &msg.control.receiver);
337 /* request remote resume */
345 /* Create new process */
346 static void createprocess(message *msg)
349 /* find unused process descr. */
350 for (i = 0; i < MAXPROCESS; i++)
351 if (!process[i].used && process[i].mark != -MAXMARKER)
355 senderr(RTETMPRC, &(msg->control.sender));
357 /* memory not allocated yet */
358 if (process[i].M == NULL) {
359 process[i].M = mallocate(memorysize + 1);
360 if (process[i].M == NULL)
361 senderr(RTEMEMOV, &msg->control.sender);
363 moveblock((char *) process[0].M, (char *) process[i].M,
364 freem * sizeof(word));
366 /* process prototype number */
367 prot = msg->control.par;
368 initprocess(i, prot, &msg->control.sender);
369 moveparams(i, process[i].prochead, msg, PARIN, SAVEPAR);
370 /* execute process until RETURN */
371 process[i].status = GENERATING;
372 ready = pinsert(ready, i);
374 if ((remote) && (i==0)) {
381 /* Release process descriptor */
382 static void killprocess(word pix)
384 qfree(process[pix].msgqueue);
385 qfree(process[pix].rpcwait);
386 sfree(process[pix].rpcmask);
388 /* mark descriptor as unused */
389 process[pix].used = FALSE;
390 /* decrement marker */
393 if (pix == thispix) {
400 static void localkill(message *msg)
404 pix = msg->control.receiver.pix;
407 fprintf(stderr, "kill process %d\n", pix);
411 if (process[pix].mark == msg->control.receiver.mark) {
412 /* is process suspended ? */
413 if (process[pix].status != STOPPED)
414 senderr(RTEILLKL, &msg->control.sender);
420 /** Terminate current process */
421 void endprocess(int status)
427 fprintf(stderr, "terminate process %d\n", thispix);
429 killprocess(thispix);
432 for (i = 0; i < MAXPROCESS; i++)
439 static void backcreate(message *msg)
444 pix = msg->control.receiver.pix;
447 /* template physical address */
448 am = p->M[p->template.addr];
449 p->M[temporary] = am;
450 moveparams(pix, am, msg, PAROUT, SAVEPAR);
452 /*store new process address */
453 mess2obj(p,&(msg->control.sender),&(p->backobj));
454 /* end of waiting for NEW */
459 void senderr(int exception, procaddr *virt)
463 msg.control.type = ERRSIG;
464 msg.control.receiver = *virt;
465 msg.control.par = exception;
466 /* send error message */
468 /* continue from next instruction */
473 static void localerror(message *msg)
478 pix = msg->control.receiver.pix;
479 s = process[pix].status;
480 if (process[pix].mark == msg->control.receiver.mark && s != STOPPED) {
481 if (s == WAITFORNEW || s == WAITFORRPC)
484 while (pfront(ready) != pix)
485 ready = qrotate(ready);
487 transfer(pfront(ready));
488 errsignal(msg->control.par);
492 /* Ask for prototype of object */
493 void askprot(virtaddr *virt)
498 /* send question to remote process */
499 if (isprocess(virt)) {
500 obj2mess(M, virt, &msg.control.receiver);
501 msg.control.type = ASKPRO;
503 passivate(WAITASKPRO);
505 if (member(virt, &am))
506 M[temporary] = M[am + PROTNUM];
512 /** Answer with prototype of process */
513 static void ansprot(message *msg)
518 pix = msg->control.receiver.pix;
520 if (process[ pix ].mark == msg->control.receiver.mark) {
521 msg1.control.receiver = msg->control.sender;
522 msg1.control.type = PROACK;
523 msg1.control.par = process[pix].prot;
527 senderr(RTEREFTN, &msg->control.sender);
531 /* Message send/receive handling : */
533 /** Receive message interrupt handler */
534 void msginterrupt(message *msg)
536 moveblock((char *)msg, (char *)&globmsgqueue[msgtail],
537 (word) sizeof(message));
538 msgtail = (msgtail+1) % MAXMSGQUEUE;
542 /** Send message via net */
543 void sendmsg1(message *msg)
548 msg->control.sender.node = ournode;
549 msg->control.sender.pix = thispix;
550 msg->control.sender.mark = thisp->mark;
552 /* simulate receive message interrupt */
553 if ((msg->control.receiver.node == ournode) ||
554 (msg->control.receiver.node == 0)) {
555 msg->control.receiver.node == ournode;
556 /* call directly interrupt handler */
559 /* send message to kernel and then to NET module */
560 m.msg_type = MSG_NET;
561 m.param.pword[0] = NET_PROPAGATE;
562 m.param.pword[1] = MSG_INT;
563 m.param.pword[2] = my_ctx.node;
564 m.param.pword[3] = my_ctx.program_id;
565 memcpy(&m.int_msg, msg, sizeof(message));
566 result = send_to_net(&m);
568 /* 2010 local allocation */
569 msg->control.receiver.node == ournode;
570 /* call directly interrupt handler */
576 /** Check for waiting message */
583 /* at least one message is waiting */
585 /* get first message from queue */
586 msg = &globmsgqueue[msghead];
587 msghead = (msghead+1) % MAXMSGQUEUE;
589 switch(msg->control.type) {
595 pix = msg->control.receiver.pix;
596 if (process[ pix ].mark != msg->control.receiver.mark)
597 senderr(RTEREFTN, &msg->control.sender);
599 if (process[ pix ].status != STOPPED)
600 senderr(RTEILLRS, &msg->control.sender);
630 pix = msg->control.receiver.pix;
632 p->M[temporary] = msg->control.par;
637 fprintf(stderr, " Invalid message\n");
638 senderr(RTESYSER, &msg->control.sender);
645 /** Make global a process reference */
646 static void mkglobal(word ref)
650 if (!isprocess((virtaddr*)(M + ref)) && M[ah + 1] == M[ref + 1])
651 if (prototype[M[M[ah] + PROTNUM]]->kind == PROCESS) {
656 pa.mark = thisp->mark;
657 mess2obj(thisp, &pa, &va);
659 M[ref + 1] = va.mark;
661 fprintf(stderr, "mkglobal REAL (thisp=%d) "
662 "isprocess:node=%d pix=%d mark=%d\n",
663 thispix, pa.node, pa.pix, pa.mark);
667 /* only process may be global */
675 void show_m(char *s, message *msg) {
677 switch(msg->control.type) {
710 printf( "message %s type %s from %d:%d:%d to %d:%d:%d\n",
712 msg->control.sender.node,
713 msg->control.sender.pix,
714 msg->control.sender.mark,
715 msg->control.receiver.node,
716 msg->control.receiver.pix,
717 msg->control.receiver.mark