18 * @brief Process management
21 /** process descriptor table */
22 procdescr process[MAXPROCESS];
24 /** pointer to current process descr */
27 /** current process index */
30 /** Round-Robin queue */
33 /** TRUE if operating in network */
36 /** queue of waiting messages */
37 message globmsgqueue[MAXMSGQUEUE];
39 /** number of waiting messages */
42 /** pointers to message queue */
43 int msghead = 0, msgtail = 0;
45 /** this machine node number */
48 /** console node number */
51 /** TRUE if remote node */
54 /** TRUE if must re-schedule */
55 bool reschedule = TRUE;
60 static void ansprot(message *);
61 static void localkill(message *);
63 static void backcreate(message *);
64 static void createprocess(message *);
65 static void localerror(message *);
66 static void killprocess(word);
67 static void mkglobal(word);
70 static void ansprot();
71 static void localkill();
73 static void backcreate();
74 static void createprocess();
75 static void localerror();
76 static void killprocess();
77 static void mkglobal();
83 /** pointer to Global Info Segment */
90 # ifndef NO_PROTOTYPES
91 static void signal_catch(void);
93 static void signal_catch();
95 static void signal_catch() {
101 void init_scheduler()
104 signal(SIGALRM, signal_catch);
109 /** Choose next ready process to exec */
112 /* STRONGLY machine dependent */
117 signal(SIGALRM, signal_catch);
122 /* the most expensive method */
124 /* context switch is needed */
125 if (reschedule || c != last) {
127 #elif MSDOS && ( WORD_16BIT || DWORD_16BIT )
128 /* DOS real memory model */
131 static char *clk = (char *) 0x0040006CL;
133 /* context switch is needed */
134 if (reschedule || c != last) {
139 c = ginf->hundredths >> 3;
140 /* context switch is needed */
141 if (reschedule || c != last) {
144 #error Scheduler time counting method not implemented !
147 /* wait for event if no processes */
148 if (!(qempty(ready))) {
149 /* find another ready process */
150 ready = qrotate(ready);
151 /* transfer control to it */
152 transfer(pfront(ready));
158 /** Context switch to another process */
159 void transfer(word pix)
162 /* optimized for case of one process */
166 /* previous process is alive */
168 /* store previous context */
173 /* and load new context */
175 thisp = &process[thispix];
180 param = thisp->param;
181 apt = thisp->prochead + M[thisp->prochead];
182 display = apt + dispoff;
183 display2 = apt + disp2off;
186 /** Resume process on this node */
187 void activate(word pix)
189 /* flag process as ready to execute */
190 process[pix].status = EXECUTING;
191 /* insert into ready queue */
192 ready = pinsert(ready, pix);
193 /* force context switch */
196 fprintf(stderr, "activate process %d\n", pix);
200 /** Passivate process */
201 void passivate(int newstatus)
203 /* change to some wait status */
204 thisp->status = newstatus;
205 /* remove from ready queue */
206 ready = qremove(ready);
207 /* force context switch */
210 fprintf(stderr, "passivate process %d to state %d\n", thispix, newstatus);
215 /** Copy parameters from object to message or vice versa. */
216 void moveparams(word pix, word am, message *msg, int par1, int dir)
220 word i, tpd, ap, pd, prim, offset;
225 ptr = prototype[p->M[am + PROTNUM]];
226 cp = (char *) msg->params;
228 /* loop through parameters */
229 for (i = 0; i < ptr->lthparlist; i++) {
231 offset = M[ptr->parlist + i];
232 /* type description of param */
233 tpd = M[ptr->pfdescr + i];
237 cflag = (pd == PARIN || pd == PARINOUT || pd == FORMFUNC
240 cflag = (pd == PAROUT || pd == PARINOUT);
243 if (pd == FORMFUNC || pd == FORMPROC) {
247 else if (M[M[tpd + 2]] == CLASSTYPE) {
252 prim = M[tpd + 2] - ipradr;
254 /* process or coroutine */
255 convert = (prim == 4 || prim == 5);
258 /* param appetite in bytes */
261 /* copy parameter in right direction */
264 /* we always load parameters from OUR process */
265 assert(pix == thispix);
270 word ah = M[am + offset];
271 if (!isprocess((virtaddr*)(M + am + offset)) &&
272 M[ah + 1] == M[am + offset + 1]) {
273 if (prototype[M[M[ah] + PROTNUM]]->kind == PROCESS) {
276 pa.mark = thisp->mark;
279 /* only process may be global */
280 /*pat errsignal(RTENONGL); */
281 /*pat*/ obj2mess(p->M,(virtaddr*)(p->M+am+offset),&pa);
284 obj2mess(M, (virtaddr*)(M + am + offset), &pa);
288 obj2mess(p->M,(virtaddr*)(p->M+am+offset),&pa);
290 moveblock((char *)&pa, cp, ap = sizeof(procaddr));
292 moveblock((char *) &p->M[am + offset], cp, ap);
298 ap = sizeof(procaddr);
299 moveblock(cp, (char *)&pa, ap);
300 mess2obj(p, &pa, (virtaddr*)(p->M + am + offset));
302 moveblock(cp, (char *)&p->M[am + offset], ap);
308 assert(cp-msg->params <= sizeof(msg->params));
313 /* Determine node number for process */
314 word getnode(word am)
320 p = prototype[M[am + PROTNUM]]->preflist;
321 while (prototype[M[p]]->kind != PROCESS)
323 ptr = prototype[M[p]];
324 if (ptr->lthpreflist == 1)
327 i = prototype[M[p - 1]]->lthparlist;
328 return (M[am + M[ptr->parlist + i]]);
331 /* Perform RESUME instruction */
332 void resume(virtaddr *virt)
336 /* is it process realy ? */
337 if (isprocess(virt)) {
338 msg.control.type = RESUME;
339 obj2mess(M, virt, &msg.control.receiver);
340 /* request remote resume */
348 /* Create new process */
349 static void createprocess(message *msg)
352 /* find unused process descr. */
353 for (i = 0; i < MAXPROCESS; i++)
354 if (!process[i].used && process[i].mark != -MAXMARKER)
358 senderr(RTETMPRC, &(msg->control.sender));
360 /* memory not allocated yet */
361 if (process[i].M == NULL) {
362 process[i].M = mallocate(memorysize + 1);
363 if (process[i].M == NULL)
364 senderr(RTEMEMOV, &msg->control.sender);
366 moveblock((char *) process[0].M, (char *) process[i].M,
367 freem * sizeof(word));
369 /* process prototype number */
370 prot = msg->control.par;
371 initprocess(i, prot, &msg->control.sender);
372 moveparams(i, process[i].prochead, msg, PARIN, SAVEPAR);
373 /* execute process until RETURN */
374 process[i].status = GENERATING;
375 ready = pinsert(ready, i);
377 if ((remote) && (i==0)) {
384 /* Release process descriptor */
385 static void killprocess(word pix)
387 qfree(process[pix].msgqueue);
388 qfree(process[pix].rpcwait);
389 sfree(process[pix].rpcmask);
391 /* mark descriptor as unused */
392 process[pix].used = FALSE;
393 /* decrement marker */
396 if (pix == thispix) {
403 static void localkill(message *msg)
407 pix = msg->control.receiver.pix;
410 fprintf(stderr, "kill process %d\n", pix);
414 if (process[pix].mark == msg->control.receiver.mark) {
415 /* is process suspended ? */
416 if (process[pix].status != STOPPED)
417 senderr(RTEILLKL, &msg->control.sender);
423 /** Terminate current process */
424 void endprocess(int status)
430 fprintf(stderr, "terminate process %d\n", thispix);
432 killprocess(thispix);
435 for (i = 0; i < MAXPROCESS; i++)
442 static void backcreate(message *msg)
447 pix = msg->control.receiver.pix;
450 /* template physical address */
451 am = p->M[p->template.addr];
452 p->M[temporary] = am;
453 moveparams(pix, am, msg, PAROUT, SAVEPAR);
455 /*store new process address */
456 mess2obj(p,&(msg->control.sender),&(p->backobj));
457 /* end of waiting for NEW */
462 void senderr(int exception, procaddr *virt)
466 msg.control.type = ERRSIG;
467 msg.control.receiver = *virt;
468 msg.control.par = exception;
469 /* send error message */
471 /* continue from next instruction */
476 static void localerror(message *msg)
481 pix = msg->control.receiver.pix;
482 s = process[pix].status;
483 if (process[pix].mark == msg->control.receiver.mark && s != STOPPED) {
484 if (s == WAITFORNEW || s == WAITFORRPC)
487 while (pfront(ready) != pix)
488 ready = qrotate(ready);
490 transfer(pfront(ready));
491 errsignal(msg->control.par);
495 /* Ask for prototype of object */
496 void askprot(virtaddr *virt)
501 /* send question to remote process */
502 if (isprocess(virt)) {
503 obj2mess(M, virt, &msg.control.receiver);
504 msg.control.type = ASKPRO;
506 passivate(WAITASKPRO);
508 if (member(virt, &am))
509 M[temporary] = M[am + PROTNUM];
515 /** Answer with prototype of process */
516 static void ansprot(message *msg)
521 pix = msg->control.receiver.pix;
523 if (process[ pix ].mark == msg->control.receiver.mark) {
524 msg1.control.receiver = msg->control.sender;
525 msg1.control.type = PROACK;
526 msg1.control.par = process[pix].prot;
530 senderr(RTEREFTN, &msg->control.sender);
534 /* Message send/receive handling : */
536 /** Receive message interrupt handler */
537 void msginterrupt(message *msg)
539 moveblock((char *)msg, (char *)&globmsgqueue[msgtail],
540 (word) sizeof(message));
541 msgtail = (msgtail+1) % MAXMSGQUEUE;
545 /** Send message via net */
546 void sendmsg1(message *msg)
551 msg->control.sender.node = ournode;
552 msg->control.sender.pix = thispix;
553 msg->control.sender.mark = thisp->mark;
555 /* simulate receive message interrupt */
556 if ((msg->control.receiver.node == ournode) ||
557 (msg->control.receiver.node == 0)) {
558 msg->control.receiver.node == ournode;
559 /* call directly interrupt handler */
562 /* send message to kernel and then to NET module */
563 m.msg_type = MSG_NET;
564 m.param.pword[0] = NET_PROPAGATE;
565 m.param.pword[1] = MSG_INT;
566 m.param.pword[2] = my_ctx.node;
567 m.param.pword[3] = my_ctx.program_id;
568 memcpy(&m.int_msg, msg, sizeof(message));
569 result = send_to_net(&m);
571 /* 2010 local allocation */
572 msg->control.receiver.node == ournode;
573 /* call directly interrupt handler */
579 /** Check for waiting message */
586 /* at least one message is waiting */
588 /* get first message from queue */
589 msg = &globmsgqueue[msghead];
590 msghead = (msghead+1) % MAXMSGQUEUE;
592 switch(msg->control.type) {
598 pix = msg->control.receiver.pix;
599 if (process[ pix ].mark != msg->control.receiver.mark)
600 senderr(RTEREFTN, &msg->control.sender);
602 if (process[ pix ].status != STOPPED)
603 senderr(RTEILLRS, &msg->control.sender);
633 pix = msg->control.receiver.pix;
635 p->M[temporary] = msg->control.par;
640 fprintf(stderr, " Invalid message\n");
641 senderr(RTESYSER, &msg->control.sender);
648 /** Make global a process reference */
649 static void mkglobal(word ref)
653 if (!isprocess((virtaddr*)(M + ref)) && M[ah + 1] == M[ref + 1])
654 if (prototype[M[M[ah] + PROTNUM]]->kind == PROCESS) {
659 pa.mark = thisp->mark;
660 mess2obj(thisp, &pa, &va);
662 M[ref + 1] = va.mark;
664 fprintf(stderr, "mkglobal REAL (thisp=%d) "
665 "isprocess:node=%d pix=%d mark=%d\n",
666 thispix, pa.node, pa.pix, pa.mark);
670 /* only process may be global */
678 void show_m(char *s, message *msg) {
680 switch(msg->control.type) {
713 printf( "message %s type %s from %d:%d:%d to %d:%d:%d\n",
715 msg->control.sender.node,
716 msg->control.sender.pix,
717 msg->control.sender.mark,
718 msg->control.receiver.node,
719 msg->control.receiver.pix,
720 msg->control.receiver.mark