16 /* Process management */
18 procdescr process[ MAXPROCESS ]; /* process descriptor table */
19 procdescr *thisp; /* pointer to current process descr */
20 word thispix; /* current process index */
21 queue ready; /* Round-Robin queue */
22 bool network; /* TRUE if operating in network */
23 message globmsgqueue[ MAXMSGQUEUE ]; /* queue of waiting messages */
24 int msgready = 0; /* number of waiting messages */
25 int msghead = 0, msgtail = 0; /* pointers to message queue */
26 word ournode; /* this machine node number */
27 word console; /* console node number */
28 bool remote = FALSE; /* TRUE if remote node */
29 bool reschedule = TRUE; /* TRUE if must re-schedule */
34 static void ansprot(message *);
35 static void localkill(message *);
37 static void backcreate(message *);
38 static void createprocess(message *);
39 static void localerror(message *);
40 static void killprocess(word);
41 static void mkglobal(word);
44 static void ansprot();
45 static void localkill();
47 static void backcreate();
48 static void createprocess();
49 static void localerror();
50 static void killprocess();
51 static void mkglobal();
57 PGINFOSEG ginf; /* pointer to Global Info Segment */
63 # ifndef NO_PROTOTYPES
64 static void signal_catch( void );
66 static void signal_catch();
68 static void signal_catch(){ reschedule=TRUE; }
72 void init_scheduler(){
74 signal(SIGALRM,signal_catch);
79 void schedule() /* Choose next ready process to exec */
81 trapmsg(); /* STRONGLY machine dependent */
85 signal(SIGALRM,signal_catch);
90 c = clock() >> 5; /* the most expensive method */
91 if (reschedule || c != last) /* context switch is needed */
94 #elif MSDOS && ( WORD_16BIT || DWORD_16BIT ) /* DOS real memory model */
97 static char *clk = (char *) 0x0040006CL;
99 if (reschedule || c != last) /* context switch is needed */
105 c = ginf->hundredths >> 3;
106 if (reschedule || c != last) /* context switch is needed */
110 #error Scheduler time counting method not implemented !
113 if (!(qempty(ready))) /* wait for event if no processes */
115 ready = qrotate(ready); /* find another ready process */
116 transfer(pfront(ready)); /* transfer control to it */
123 void transfer(pix) /* Context switch to another process */
127 if (pix == thispix) return; /* optimized for case of one process */
129 if( thisp != NULL ) /* previous process is alive */
131 thisp->ic = ic; /* store previous context */
135 thispix = pix; /* and load new context */
136 thisp = &process[ thispix ];
141 param = thisp->param;
142 apt = thisp->prochead+M[ thisp->prochead ];
143 display = apt+dispoff;
144 display2 = apt+disp2off;
148 void activate(pix) /* Resume process on this node */
151 process[ pix ].status = EXECUTING; /* flag process as ready to execute */
152 ready = pinsert(ready, pix); /* insert into ready queue */
153 reschedule = TRUE; /* force context switch */
155 fprintf(stderr,"activate process %d\n",pix);
160 void passivate(newstatus) /* Passivate process */
164 thisp->status = newstatus; /* change to some wait status */
165 ready = qremove(ready); /* remove from ready queue */
166 reschedule = TRUE; /* force context switch */
168 fprintf(stderr,"passivate process %d to state %d\n",thispix,newstatus);
173 /* Copy parameters from object to message or vice versa. */
176 void moveparams(pix, am, msg, par1, dir)
183 word i, tpd, ap, pd, prim, offset;
188 ptr = prototype[ p->M[ am+PROTNUM ] ];
189 cp = (char *) msg->params;
191 for (i = 0; i < ptr->lthparlist; i++) /* loop through parameters */
194 offset = M[ ptr->parlist+i ];
195 tpd = M[ ptr->pfdescr+i ]; /* type description of param */
199 cflag = ( pd==PARIN || pd==PARINOUT || pd==FORMFUNC || pd==FORMPROC );
201 cflag = ( pd==PAROUT || pd==PARINOUT );
205 if (pd == FORMFUNC || pd == FORMPROC)
211 if (M[ M[ tpd+2 ] ] == CLASSTYPE)
218 prim = M[ tpd+2 ]-ipradr;
219 ap = primapet[ prim ];
220 convert = (prim == 4 || prim == 5); /* process or coroutine */
223 ap *= sizeof(word); /* param appetite in bytes */
225 switch (dir) /* copy parameter in right direction */
230 /* we always load parameters from OUR process */
231 assert(pix==thispix);
236 word ah=M[am+offset];
237 if( !isprocess((virtaddr*)(M+am+offset)) &&
238 M[ ah+1 ] == M[ am+offset+1 ]
240 if (prototype[ M[ M[ ah ]+PROTNUM ] ]->kind == PROCESS)
244 pa.mark = thisp->mark;
247 /*pat errsignal(RTENONGL); */ /* only process may be global */
248 /*pat*/ obj2mess(p->M,(virtaddr*)(p->M+am+offset),&pa);
250 obj2mess(M,(virtaddr*)(M+am+offset),&pa);
254 obj2mess(p->M,(virtaddr*)(p->M+am+offset),&pa);
256 moveblock((char *)&pa, cp, ap=sizeof(procaddr));
258 moveblock((char *) &p->M[ am+offset ], cp, ap);
267 moveblock(cp,(char *)&pa, ap);
268 mess2obj(p,&pa,(virtaddr*)(p->M+am+offset));
270 moveblock(cp, (char *) &p->M[ am+offset ], ap);
276 assert(cp-msg->params <= sizeof(msg->params));
282 word getnode(am) /* Determine node number for process */
289 p = prototype[ M[ am+PROTNUM ] ]->preflist;
290 while (prototype[ M[ p ] ]->kind != PROCESS) p++;
291 ptr = prototype[ M[ p ] ];
292 if (ptr->lthpreflist == 1) i = 0;
293 else i = prototype[ M[ p-1 ] ]->lthparlist;
294 return (M[ am+M[ ptr->parlist+i ] ]);
298 void resume(virt) /* Perform RESUME instruction */
303 if (isprocess(virt)) /* is it process realy ? */
305 msg.control.type = RESUME;
306 obj2mess( M, virt, &msg.control.receiver );
307 sendmsg1( &msg); /* request remote resume */
309 else errsignal(RTEILLRS); /* illegal RESUME */
313 static void createprocess(msg) /* Create new process */
317 for (i = 0; i < MAXPROCESS; i++) /* find unused process descr. */
318 if (!process[ i ].used && process[ i ].mark != -MAXMARKER) break;
319 if (i == MAXPROCESS) senderr(RTETMPRC, &(msg->control.sender) );
320 if (process[ i ].M == NULL) /* memory not allocated yet */
322 process[ i ].M = mallocate(memorysize+1);
323 if (process[ i ].M == NULL) senderr(RTEMEMOV, &msg->control.sender);
324 moveblock((char *) process[ 0 ].M, (char *) process[ i ].M,
325 freem * sizeof(word));
327 prot = msg->control.par; /* process prototype number */
328 initprocess(i, prot, &msg->control.sender);
329 moveparams(i, process[ i ].prochead, msg, PARIN, SAVEPAR);
330 process[ i ].status = GENERATING; /* execute process until RETURN */
331 ready = pinsert(ready, i);
333 if ((remote) && (i==0)) { thispix=1;thisp=NULL;transfer(i); }
337 static void killprocess(pix) /* Release process descriptor */
340 qfree(process[ pix ].msgqueue);
341 qfree(process[ pix ].rpcwait);
342 sfree(process[ pix ].rpcmask);
344 process[ pix ].used = FALSE; /* mark descriptor as unused */
345 process[ pix ].mark--; /* decrement marker */
355 static void localkill(msg)
360 pix = msg->control.receiver.pix;
363 fprintf( stderr, "kill process %d\n", pix );
366 if (process[ pix ].mark == msg->control.receiver.mark) /* not none */
368 if (process[ pix ].status != STOPPED) /* is process suspended ? */
369 senderr(RTEILLKL, &msg->control.sender);
375 void endprocess(status) /* Terminate current process */
382 fprintf( stderr, "terminate process %d\n", thispix );
384 killprocess(thispix);
385 if (remote) longjmp(contenv, 1);
386 for (i = 0; i < MAXPROCESS; i++)
387 if (process[ i ].used) longjmp(contenv, 1);
392 static void backcreate(msg)
398 pix = msg->control.receiver.pix;
401 am = p->M[ p->template.addr ]; /* template physical address */
402 p->M[ temporary ] = am;
403 moveparams(pix, am, msg, PAROUT, SAVEPAR);
405 /*store new process address */
406 mess2obj(p,&(msg->control.sender),&(p->backobj));
407 activate(pix); /* end of waiting for NEW */
411 void senderr(exception, virt)
417 msg.control.type = ERRSIG;
418 msg.control.receiver=*virt;
419 msg.control.par = exception;
420 sendmsg1(&msg); /* send error message */
421 longjmp(contenv, 1); /* continue from next instruction */
425 static void localerror(msg)
431 pix = msg->control.receiver.pix;
432 s = process[ pix ].status;
433 if (process[ pix ].mark == msg->control.receiver.mark && s != STOPPED)
435 if (s == WAITFORNEW || s == WAITFORRPC) activate(pix);
436 while (pfront(ready) != pix)
437 ready = qrotate(ready);
438 transfer(pfront(ready));
439 errsignal(msg->control.par);
444 void askprot(virt) /* Ask for prototype of object */
450 if (isprocess(virt)) /* send question to remote process */
452 obj2mess( M, virt, &msg.control.receiver );
453 msg.control.type = ASKPRO;
455 passivate(WAITASKPRO);
459 if (member(virt, &am))
460 M[ temporary ] = M[ am+PROTNUM ];
461 else errsignal(RTEREFTN);
466 static void ansprot(msg) /* Answer with prototype of process */
472 pix = msg->control.receiver.pix;
473 if (process[ pix ].mark == msg->control.receiver.mark) /* not none */
475 msg1.control.receiver = msg->control.sender;
476 msg1.control.type = PROACK;
477 msg1.control.par = process[ pix ].prot;
480 else senderr(RTEREFTN, &msg->control.sender);
484 /* Message send/receive handling : */
486 void msginterrupt(msg) /* Receive message interrupt handler */
489 moveblock((char *)msg, (char *)&globmsgqueue[ msgtail ],
490 (word) sizeof(message));
491 msgtail = (msgtail+1) % MAXMSGQUEUE;
497 void sendmsg1(msg) /* Send message via net */
503 msg->control.sender.node = ournode;
504 msg->control.sender.pix = thispix;
505 msg->control.sender.mark = thisp->mark;
507 msg->control.receiver.node == ournode
509 msg->control.receiver.node == 0
511 /* simulate receive message interrupt */
514 msg->control.receiver.node == ournode;
515 msginterrupt(msg); /* call directly interrupt handler */
517 else /* send message to kernel and then to NET module */
519 m.msg_type = MSG_NET;
520 m.param.pword[0] = NET_PROPAGATE;
521 m.param.pword[1] = MSG_INT;
522 m.param.pword[2] = my_ctx.node;
523 m.param.pword[3] = my_ctx.program_id;
524 memcpy(&m.int_msg,msg,sizeof(message));
525 result = send_to_net(&m);
527 /* 2010 local allocation */
528 msg->control.receiver.node == ournode;
529 msginterrupt(msg); /* call directly interrupt handler */
535 void trapmsg() /* Check for waiting message */
541 if (msgready > 0) /* at least one message is waiting */
543 msg = &globmsgqueue[ msghead ]; /* get first message from queue */
544 msghead = (msghead+1) % MAXMSGQUEUE;
546 switch(msg->control.type)
553 pix = msg->control.receiver.pix;
554 if (process[ pix ].mark != msg->control.receiver.mark)
555 senderr(RTEREFTN, &msg->control.sender);
556 if (process[ pix ].status != STOPPED)
557 senderr(RTEILLRS, &msg->control.sender);
586 pix = msg->control.receiver.pix;
588 p->M[ temporary ] = msg->control.par;
593 fprintf( stderr, " Invalid message\n" );
594 senderr(RTESYSER, &msg->control.sender);
602 static void mkglobal(ref) /* Make global a process reference */
607 if (!isprocess((virtaddr*)(M+ref)) && M[ ah+1 ] == M[ ref+1 ])
608 if (prototype[ M[ M[ ah ]+PROTNUM ] ]->kind == PROCESS)
614 pa.mark = thisp->mark;
615 mess2obj(thisp,&pa,&va);
617 M[ ref+1 ] = va.mark;
619 fprintf(stderr,"mkglobal REAL (thisp=%d) isprocess:node=%d pix=%d mark=%d\n",thispix,pa.node,pa.pix,pa.mark);fflush(stderr);
622 else errsignal(RTENONGL); /* only process may be global */
628 void show_m( char *s, message *msg ){
630 switch(msg->control.type)
632 case ERRSIG : n = "ERRSIG"; break;
633 case RESUME : n = "RESUME"; break;
634 case CREATE : n = "CREATE"; break;
635 case CREACK : n = "CREACK"; break;
636 case KILLPR : n = "KILLPR"; break;
637 case RPCALL : n = "RPCALL"; break;
638 case RPCACK : n = "RPCACK"; break;
639 case ASKPRO : n = "ASKPRO"; break;
640 case PROACK : n = "PROACK"; break;
641 default : n = "??????"; break;
644 printf( "message %s type %s from %d:%d:%d to %d:%d:%d\n",
646 msg->control.sender.node,
647 msg->control.sender.pix,
648 msg->control.sender.mark,
649 msg->control.receiver.node,
650 msg->control.receiver.pix,
651 msg->control.receiver.mark