|
|
1.1 root 1: /*
2:
3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /* routines for handling processes */
10:
11:
12:
13: #include "mint.h"
14:
15: #include "xbra.h"
16:
17:
18:
19: static void do_wakeup_things P_((void));
20:
21:
22:
23: extern short proc_clock;
24:
25:
26:
27: /* global process variables */
28:
29: PROC *proclist; /* list of all active processes */
30:
31: PROC *curproc; /* current process */
32:
33: PROC *rootproc; /* pid 0 -- MiNT itself */
34:
35: PROC *sys_q[NUM_QUEUES];
36:
37:
38:
39: #define TIME_SLICE 1 /* number of 20ms ticks before process is
40:
41: pre-empted */
42:
43:
44:
45:
46:
47: /* macro for calculating number of missed time slices, based on a
48:
49: * process' priority
50:
51: */
52:
53: #define SLICES(pri) (((pri) >= 0) ? 0 : -(pri))
54:
55:
56:
57: extern FILESYS bios_filesys;
58:
59:
60:
61: /*
62:
63: * get a new process struct
64:
65: */
66:
67: #define NPROC 5 /* get this many PROC structures at a time */
68:
69:
70:
71: PROC *pfreelist = 0;
72:
73:
74:
75: PROC *
76:
77: new_proc()
78:
79: {
80:
81: PROC *p;
82:
83: #if 0
84:
85: int i;
86:
87:
88:
89: if (pfreelist == 0) {
90:
91: p = (PROC *)kmalloc(NPROC * SIZEOF(PROC));
92:
93: if (!p) {
94:
95: ALERT("new_proc: couldn't get a PROC structure");
96:
97: return 0;
98:
99: }
100:
101: else {
102:
103: for (i = 0; i < NPROC; i++) {
104:
105: p->gl_next = pfreelist;
106:
107: pfreelist = p;
108:
109: p++;
110:
111: }
112:
113: }
114:
115: }
116:
117: p = pfreelist;
118:
119: pfreelist = p->gl_next;
120:
121: p->gl_next = 0;
122:
123: #else
124:
125: p = (PROC *)kmalloc(SIZEOF(PROC));
126:
127: #endif
128:
129: return p;
130:
131: }
132:
133:
134:
135: /*
136:
137: * dispose of an old proc
138:
139: */
140:
141:
142:
143: void
144:
145: dispose_proc(p)
146:
147: PROC *p;
148:
149: {
150:
151: #if 0
152:
153: p->gl_next = pfreelist;
154:
155: pfreelist = p;
156:
157: #else
158:
159: kfree(p);
160:
161: #endif
162:
163: }
164:
165:
166:
167: /*
168:
169: * create a new process that is (practically) a duplicate of the
170:
171: * current one
172:
173: */
174:
175:
176:
177: PROC *
178:
179: fork_proc()
180:
181: {
182:
183: PROC *p;
184:
185: int i;
186:
187: FILEPTR *f;
188:
189:
190:
191: if (!(p = new_proc())) {
192:
193: nomem:
194:
195: DEBUG("fork_proc: insufficient memory");
196:
197: mint_errno = ENSMEM; return 0;
198:
199: }
200:
201:
202:
203: *p = *curproc; /* child shares most things with parent... */
204:
205:
206:
207: /* ... except for these: */
208:
209: p->ppid = curproc->pid;
210:
211: p->pid = newpid();
212:
213: p->sigpending = 0;
214:
215: p->sysstack = (long)(p->stack + STKSIZE - 12);
216:
217: p->ctxt[CURRENT].ssp = p->sysstack;
218:
219: p->ctxt[SYSCALL].ssp = (long)(p->stack + ISTKSIZE);
220:
221: p->alarmtim = 0;
222:
223: p->curpri = p->pri;
224:
225: p->slices = SLICES(p->pri);
226:
227: p->starttime = timestamp;
228:
229: p->startdate = datestamp;
230:
231:
232:
233: ((long *)p->sysstack)[1] = FRAME_MAGIC;
234:
235: ((long *)p->sysstack)[2] = 0;
236:
237: ((long *)p->sysstack)[3] = 0;
238:
239:
240:
241: p->usrtime = p->systime = p->chldstime = p->chldutime = 0;
242:
243:
244:
245: /* copy open handles */
246:
247: for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
248:
249: if ((f = p->handle[i]) != 0) {
250:
251: if (f->flags & O_NOINHERIT)
252:
253: /* oops, we didn't really want to copy this handle */
254:
255: p->handle[i] = 0;
256:
257: else
258:
259: f->links++;
260:
261: }
262:
263: }
264:
265:
266:
267: /* clear directory search info */
268:
269: zero((char *)p->srchdta, NUM_SEARCH * SIZEOF(DTABUF *));
270:
271:
272:
273: /* copy memory */
274:
275: p->mem = (MEMREGION **) kmalloc(p->num_reg * SIZEOF(MEMREGION *));
276:
277: if (!p->mem) {
278:
279: dispose_proc(p);
280:
281: goto nomem;
282:
283: }
284:
285: p->addr = (virtaddr *)kmalloc(p->num_reg * SIZEOF(virtaddr));
286:
287: if (!p->addr) {
288:
289: kfree(p->mem);
290:
291: dispose_proc(p);
292:
293: goto nomem;
294:
295: }
296:
297:
298:
299: for (i = 0; i < curproc->num_reg; i++) {
300:
301: if (p->mem[i] = curproc->mem[i]) /* yes, "=" is right */
302:
303: p->mem[i]->links++;
304:
305: p->addr[i] = curproc->addr[i];
306:
307: }
308:
309:
310:
311: p->starttime = Tgettime();
312:
313: p->startdate = Tgetdate();
314:
315:
316:
317: p->q_next = 0;
318:
319: p->wait_q = 0;
320:
321: p->gl_next = proclist;
322:
323: proclist = p; /* hook into the process list */
324:
325: return p;
326:
327: }
328:
329:
330:
331: /*
332:
333: * initialize the process table
334:
335: */
336:
337:
338:
339: void
340:
341: init_proc()
342:
343: {
344:
345: int i;
346:
347: FILESYS *fs;
348:
349: fcookie dir;
350:
351: extern BASEPAGE **tosbp; /* in main.c */
352:
353:
354:
355: rootproc = curproc = new_proc();
356:
357: assert(curproc);
358:
359:
360:
361: zero((char *)curproc, (long)sizeof(PROC));
362:
363:
364:
365: curproc->ppid = -1; /* no parent */
366:
367: curproc->domain = DOM_TOS; /* TOS domain */
368:
369: curproc->sysstack = (long) (curproc->stack+STKSIZE-12);
370:
371: curproc->magic = CTXT_MAGIC;
372:
373: ((long *)curproc->sysstack)[1] = FRAME_MAGIC;
374:
375: ((long *)curproc->sysstack)[2] = 0;
376:
377: ((long *)curproc->sysstack)[3] = 0;
378:
379:
380:
381: curproc->base = (BASEPAGE *) *tosbp;
382:
383:
384:
385: strcpy(curproc->name, "MiNT");
386:
387:
388:
389: /* get some memory */
390:
391: curproc->mem = (MEMREGION **)kmalloc(NUM_REGIONS*SIZEOF(MEMREGION *));
392:
393: curproc->addr = (virtaddr *)kmalloc(NUM_REGIONS*SIZEOF(virtaddr));
394:
395: assert(curproc->mem && curproc->addr);
396:
397:
398:
399: /* make sure it's filled with zeros */
400:
401: zero((char *)curproc->addr, NUM_REGIONS * SIZEOF(virtaddr));
402:
403: zero((char *)curproc->mem, NUM_REGIONS * SIZEOF(MEMREGION *));
404:
405: curproc->num_reg = NUM_REGIONS;
406:
407:
408:
409: /* get root and current directories for all drives */
410:
411: for (i = 0; i < NUM_DRIVES; i++) {
412:
413: if ((fs = drives[i]) != 0 && (*fs->root)(i, &dir) == E_OK) {
414:
415: curproc->root[i] = curproc->curdir[i] = dir;
416:
417: } else {
418:
419: curproc->root[i].fs = curproc->curdir[i].fs = 0;
420:
421: curproc->root[i].dev = curproc->curdir[i].dev = i;
422:
423: }
424:
425: }
426:
427:
428:
429: /* Set the correct drive. The current directory we
430:
431: * set later, after all file systems have been loaded.
432:
433: */
434:
435:
436:
437: curproc->curdrv = Dgetdrv();
438:
439: proclist = curproc;
440:
441:
442:
443: curproc->umask = 0;
444:
445:
446:
447: /*
448:
449: * some more protection against job control; unless these signals are
450:
451: * re-activated by a shell that knows about job control, they'll have
452:
453: * no effect
454:
455: */
456:
457: curproc->sighandle[SIGTTIN] = curproc->sighandle[SIGTTOU] =
458:
459: curproc->sighandle[SIGTSTP] = SIG_IGN;
460:
461:
462:
463: /* set up some more per-process variables */
464:
465: curproc->starttime = Tgettime();
466:
467: curproc->startdate = Tgetdate();
468:
469: if (has_bconmap)
470:
471: curproc->bconmap = curbconmap;
472:
473: else
474:
475: curproc->bconmap = 1;
476:
477:
478:
479: curproc->logbase = (void *)Logbase();
480:
481: curproc->criticerr = *((long (**) P_((long)))0x404L);
482:
483: }
484:
485:
486:
487: /*
488:
489: * reset all process priorities to their base level
490:
491: * called once per second, so that cpu hogs can get _some_ time
492:
493: * slices :-).
494:
495: */
496:
497:
498:
499: void
500:
501: reset_priorities()
502:
503: {
504:
505: PROC *p;
506:
507:
508:
509: for (p = proclist; p; p = p->gl_next) {
510:
511: p->curpri = p->pri;
512:
513: p->slices = SLICES(p->curpri);
514:
515: }
516:
517: }
518:
519:
520:
521: /*
522:
523: * more priority code stuff:
524:
525: * run_next(p, slices): schedule process "p" to run next, with "slices"
526:
527: * initial time slices; "p" does not actually start running until
528:
529: * the next context switch
530:
531: * fresh_slices(slices): give the current process "slices" more slices in
532:
533: * which to run
534:
535: */
536:
537:
538:
539: void
540:
541: run_next(p, slices)
542:
543: PROC *p;
544:
545: int slices; /* BUG: currently ignored */
546:
547: {
548:
549: p->slices = 0;
550:
551: p->curpri = MAX_NICE;
552:
553: p->wait_q = READY_Q;
554:
555: p->q_next = sys_q[READY_Q];
556:
557: sys_q[READY_Q] = p;
558:
559: }
560:
561:
562:
563: void
564:
565: fresh_slices(slices)
566:
567: int slices;
568:
569: {
570:
571: curproc->slices = 0;
572:
573: curproc->curpri = MAX_NICE+1;
574:
575: proc_clock = slices;
576:
577: }
578:
579:
580:
581: /*
582:
583: * add a process to a wait (or ready) queue.
584:
585: *
586:
587: * processes go onto a queue in first in-first out order
588:
589: */
590:
591:
592:
593: void
594:
595: add_q(que, proc)
596:
597: int que;
598:
599: PROC *proc;
600:
601: {
602:
603: PROC *q, **lastq;
604:
605:
606:
607: /* "proc" should not already be on a list */
608:
609: assert(proc->wait_q == 0);
610:
611: assert(proc->q_next == 0);
612:
613:
614:
615: lastq = &sys_q[que];
616:
617: q = *lastq;
618:
619: while(q) {
620:
621: lastq = &q->q_next;
622:
623: q = *lastq;
624:
625: }
626:
627: *lastq = proc;
628:
629: proc->wait_q = que;
630:
631: if (que != READY_Q) {
632:
633: proc->curpri = proc->pri; /* reward the process */
634:
635: proc->slices = SLICES(proc->curpri);
636:
637: }
638:
639: }
640:
641:
642:
643: /*
644:
645: * remove a process from a queue
646:
647: */
648:
649:
650:
651: void
652:
653: rm_q(que, proc)
654:
655: int que;
656:
657: PROC *proc;
658:
659: {
660:
661: PROC *q;
662:
663: PROC *old = 0;
664:
665:
666:
667: assert(proc->wait_q == que);
668:
669:
670:
671: q = sys_q[que];
672:
673: while (q && q != proc) {
674:
675: old = q;
676:
677: q = q->q_next;
678:
679: }
680:
681: if (q == 0)
682:
683: FATAL("rm_q: unable to remove process from queue");
684:
685:
686:
687: if (old)
688:
689: old->q_next = proc->q_next;
690:
691: else
692:
693: sys_q[que] = proc->q_next;
694:
695:
696:
697: proc->wait_q = 0;
698:
699: proc->q_next = 0;
700:
701: }
702:
703:
704:
705: /*
706:
707: * preempt(): called by the vbl routine and/or the trap handlers when
708:
709: * they detect that a process has exceeded its time slice and hasn't
710:
711: * yielded gracefully. For now, it just does sleep(READY_Q); later,
712:
713: * we might want to keep track of statistics or something.
714:
715: */
716:
717:
718:
719: void
720:
721: preempt()
722:
723: {
724:
725: extern short bconbsiz; /* in bios.c */
726:
727:
728:
729: if (bconbsiz)
730:
731: (void)bflush();
732:
733: else {
734:
735: /* punish the pre-empted process */
736:
737: if (curproc->curpri >= MIN_NICE)
738:
739: curproc->curpri -= 1;
740:
741: }
742:
743: sleep(READY_Q, curproc->wait_cond);
744:
745: }
746:
747:
748:
749: /*
750:
751: * sleep(que, cond): put the current process on the given queue, then switch
752:
753: * contexts. Before a new process runs, give it a fresh time slice. "cond"
754:
755: * is the condition for which the process is waiting, and is placed in
756:
757: * curproc->wait_cond
758:
759: */
760:
761:
762:
763: static void
764:
765: do_wakeup_things()
766:
767: {
768:
769: /*
770:
771: * check for stack underflow, just in case
772:
773: */
774:
775: auto int foo;
776:
777:
778:
779: if ( curproc->pid != 0 &&
780:
781: ((long)&foo) < (long)curproc->stack + ISTKSIZE + 512 ) {
782:
783: ALERT("sleep: stack overflow");
784:
785: handle_sig(SIGBUS);
786:
787: }
788:
789: /*
790:
791: * check processes for alarms
792:
793: */
794:
795:
796:
797: checkalarms();
798:
799:
800:
801: check_time(); /* check for CPU limit exceeded */
802:
803: check_sigs(); /* check for signals */
804:
805:
806:
807: proc_clock = TIME_SLICE; /* get a fresh time slice */
808:
809: curproc->slices = SLICES(curproc->curpri);
810:
811: }
812:
813:
814:
815: void
816:
817: sleep(que, cond)
818:
819: int que;
820:
821: long cond;
822:
823: {
824:
825: PROC *p;
826:
827: short sr;
828:
829: extern short kintr; /* in bios.c */
830:
831: extern short bconbsiz;
832:
833: #ifdef FASTTEXT
834:
835: extern int hardscroll; /* in fasttext.c */
836:
837: #endif
838:
839: assert(bconbsiz == 0);
840:
841:
842:
843: /*
844:
845: * if there have been keyboard interrupts since our last sleep, check for
846:
847: * special keys like CTRL-ALT-Fx
848:
849: */
850:
851:
852:
853: if (kintr) {
854:
855: (void)checkkeys();
856:
857: kintr = 0;
858:
859: }
860:
861:
862:
863: if (que == READY_Q && !sys_q[READY_Q]) {
864:
865: /* we're just going to wake up again right away! */
866:
867: do_wakeup_things();
868:
869: return;
870:
871: }
872:
873:
874:
875: sr = spl7();
876:
877:
878:
879: add_q(que, curproc);
880:
881: curproc->wait_cond = cond;
882:
883:
884:
885: if (!sys_q[READY_Q]) {
886:
887: /* hmm, no-one is ready to run. might be a deadlock, might not.
888:
889: * first, try waking up any napping processes; if that doesn't work,
890:
891: * run the root process, just so we have someone to charge time
892:
893: * to.
894:
895: */
896:
897: wake(SELECT_Q, (long)&nap);
898:
899: if (!sys_q[READY_Q]) {
900:
901: p = rootproc; /* pid 0 */
902:
903: rm_q(p->wait_q, p);
904:
905: add_q(READY_Q, p);
906:
907: }
908:
909: }
910:
911:
912:
913: /*
914:
915: * Walk through the ready list, to find what process should run next.
916:
917: * Lower priority processes don't get to run every time through this
918:
919: * loop; if "p->slices" is positive, it's the number of times that they
920:
921: * will have to miss a turn before getting to run again
922:
923: */
924:
925: p = 0;
926:
927:
928:
929: while (!p) {
930:
931: for (p = sys_q[READY_Q]; p; p = p->q_next) {
932:
933: if (p->slices > 0)
934:
935: p->slices--;
936:
937: else
938:
939: break;
940:
941: }
942:
943: }
944:
945: rm_q(READY_Q, p);
946:
947:
948:
949: spl(sr);
950:
951:
952:
953: if (save_context(&(curproc->ctxt[CURRENT]))) {
954:
955: if (curproc->q_next) {
956:
957: DEBUG("sleep: why is curproc on a queue???");
958:
959: }
960:
961: /*
962:
963: * restore per-process variables here
964:
965: */
966:
967: #ifdef FASTTEXT
968:
969: if (!hardscroll)
970:
971: #endif
972:
973: *((void **)0x44eL) = curproc->logbase;
974:
975: do_wakeup_things();
976:
977: return;
978:
979: }
980:
981: /*
982:
983: * save per-process variables here
984:
985: */
986:
987: #ifdef FASTTEXT
988:
989: if (!hardscroll)
990:
991: #endif
992:
993: curproc->logbase = *((void **)0x44eL);
994:
995: curproc->ctxt[CURRENT].regs[0] = 1;
996:
997: curproc = p;
998:
999: proc_clock = TIME_SLICE; /* fresh time */
1000:
1001: if ((p->ctxt[CURRENT].sr & 0x2000) == 0) { /* user mode? */
1002:
1003: leave_kernel();
1004:
1005: }
1006:
1007: assert(p->magic == CTXT_MAGIC);
1008:
1009: restore_context(&(p->ctxt[CURRENT]));
1010:
1011: }
1012:
1013:
1014:
1015: /*
1016:
1017: * wake(que, cond): wake up all processes on the given queue that are waiting
1018:
1019: * for the indicated condition
1020:
1021: */
1022:
1023:
1024:
1025: void
1026:
1027: wake(que, cond)
1028:
1029: int que;
1030:
1031: long cond;
1032:
1033: {
1034:
1035: PROC *p;
1036:
1037:
1038:
1039: if (que == READY_Q) {
1040:
1041: ALERT("wake: why wake up ready processes??");
1042:
1043: return;
1044:
1045: }
1046:
1047: top:
1048:
1049: for(p = sys_q[que]; p; p = p->q_next) {
1050:
1051: if (p->wait_cond == cond) {
1052:
1053: rm_q(que, p);
1054:
1055: add_q(READY_Q, p);
1056:
1057: goto top;
1058:
1059: }
1060:
1061: }
1062:
1063: }
1064:
1065:
1066:
1067: /*
1068:
1069: * wakeselect(p): wake process p from a select() system call
1070:
1071: * may be called by an interrupt handler or whatever
1072:
1073: */
1074:
1075:
1076:
1077: void
1078:
1079: wakeselect(param)
1080:
1081: long param;
1082:
1083: {
1084:
1085: PROC *p = (PROC *)param;
1086:
1087: short s;
1088:
1089:
1090:
1091: s = spl7(); /* block interrupts */
1092:
1093: if(p->wait_cond == (long)&wakeselect) {
1094:
1095: p->wait_cond = 0;
1096:
1097: }
1098:
1099: if (p->wait_q == SELECT_Q) {
1100:
1101: rm_q(SELECT_Q, p);
1102:
1103: add_q(READY_Q, p);
1104:
1105: }
1106:
1107: spl(s);
1108:
1109: }
1110:
1111:
1112:
1113: /*
1114:
1115: * check_time(): check to see if process' time limit has been exceeded
1116:
1117: */
1118:
1119:
1120:
1121: void
1122:
1123: check_time()
1124:
1125: {
1126:
1127: if (curproc->maxcpu) {
1128:
1129: if (curproc->maxcpu <= curproc->systime + curproc->usrtime) {
1130:
1131: DEBUG("cpu limit exceeded");
1132:
1133: raise(SIGXCPU);
1134:
1135: }
1136:
1137: }
1138:
1139: }
1140:
1141:
1142:
1143: /*
1144:
1145: * dump out information about processes
1146:
1147: */
1148:
1149:
1150:
1151: /*
1152:
1153: * kludge alert! In order to get the right pid printed by ALERT, we use
1154:
1155: * curproc as the loop variable.
1156:
1157: */
1158:
1159:
1160:
1161: void
1162:
1163: DUMPPROC()
1164:
1165: {
1166:
1167: PROC *p = curproc;
1168:
1169:
1170:
1171: for (curproc = proclist; curproc; curproc = curproc->gl_next) {
1172:
1173: ALERT("queue %d cond %lx PC: %lx USP: %lx SSP: %lx SYSSP: %lx FRAME: %lx",
1174:
1175: curproc->wait_q, curproc->wait_cond,
1176:
1177: curproc->ctxt[SYSCALL].pc,
1178:
1179: curproc->ctxt[SYSCALL].usp,
1180:
1181: curproc->ctxt[SYSCALL].ssp,
1182:
1183: curproc->sysstack,
1184:
1185: ((long *)curproc->sysstack)[2]
1186:
1187: );
1188:
1189: }
1190:
1191: curproc = p; /* restore the real curproc */
1192:
1193: }
1194:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.