|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.6 ! root 5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /* routines for handling processes */
14:
15:
16:
17: #include "mint.h"
18:
19: #include "xbra.h"
20:
21:
22:
1.1.1.6 ! root 23: static void do_wakeup_things P_((int sr, int newslice));
1.1 root 24:
25:
26:
27: extern short proc_clock;
28:
29:
30:
31: /* global process variables */
32:
33: PROC *proclist; /* list of all active processes */
34:
35: PROC *curproc; /* current process */
36:
37: PROC *rootproc; /* pid 0 -- MiNT itself */
38:
39: PROC *sys_q[NUM_QUEUES];
40:
41:
42:
1.1.1.3 root 43: short time_slice = 2; /* default; actual value comes from mint.cnf */
44:
45:
46:
47: #if 0
48:
49: #define TIME_SLICE 2 /* number of 20ms ticks before process is
1.1 root 50:
51: pre-empted */
52:
1.1.1.3 root 53: #else
54:
55: #define TIME_SLICE time_slice
1.1 root 56:
1.1.1.3 root 57: #endif
1.1 root 58:
59:
60:
61: /* macro for calculating number of missed time slices, based on a
62:
63: * process' priority
64:
65: */
66:
67: #define SLICES(pri) (((pri) >= 0) ? 0 : -(pri))
68:
69:
70:
71: extern FILESYS bios_filesys;
72:
73:
74:
75: /*
76:
77: * get a new process struct
78:
79: */
80:
81:
82:
83: PROC *
84:
85: new_proc()
86:
87: {
88:
89: PROC *p;
90:
1.1.1.3 root 91: void *pt;
92:
93:
94:
95: pt = kmalloc(page_table_size + 16);
96:
97: if (!pt) return 0;
98:
1.1 root 99:
100:
101: p = (PROC *)kmalloc(SIZEOF(PROC));
102:
1.1.1.3 root 103: if (!p) {
104:
105: kfree(pt);
106:
107: return 0;
108:
109: }
110:
111: /* page tables must be on 16 byte boundaries, so we
112:
113: * round off by 16 for that; however, we will want to
114:
115: * kfree that memory at some point, so we squirrel
116:
117: * away the original address for later use
118:
119: */
120:
121: p->page_table = ROUND16(pt);
122:
123: p->pt_mem = pt;
124:
1.1 root 125: return p;
126:
127: }
128:
129:
130:
131: /*
132:
133: * dispose of an old proc
134:
135: */
136:
137:
138:
139: void
140:
141: dispose_proc(p)
142:
143: PROC *p;
144:
145: {
146:
1.1.1.3 root 147: TRACELOW(("dispose_proc"));
148:
149: kfree(p->pt_mem);
150:
1.1 root 151: kfree(p);
152:
153: }
154:
155:
156:
157: /*
158:
159: * create a new process that is (practically) a duplicate of the
160:
161: * current one
162:
163: */
164:
165:
166:
167: PROC *
168:
169: fork_proc()
170:
171: {
172:
173: PROC *p;
174:
175: int i;
176:
177: FILEPTR *f;
178:
1.1.1.3 root 179: long_desc *pthold;
180:
181: void *ptmemhold;
182:
1.1 root 183:
184:
1.1.1.2 root 185: if ((p = new_proc()) == 0) {
1.1 root 186:
187: nomem:
188:
1.1.1.2 root 189: DEBUG(("fork_proc: insufficient memory"));
1.1 root 190:
191: mint_errno = ENSMEM; return 0;
192:
193: }
194:
195:
196:
1.1.1.3 root 197: /* child shares most things with parent, but hold on to page table ptr */
198:
199: pthold = p->page_table;
200:
201: ptmemhold = p->pt_mem;
202:
203: *p = *curproc;
204:
205: p->page_table = pthold;
1.1 root 206:
1.1.1.3 root 207: p->pt_mem = ptmemhold;
1.1 root 208:
209:
1.1.1.3 root 210:
211: /* these things are not inherited */
1.1 root 212:
213: p->ppid = curproc->pid;
214:
215: p->pid = newpid();
216:
217: p->sigpending = 0;
218:
1.1.1.5 root 219: p->nsigs = 0;
220:
1.1 root 221: p->sysstack = (long)(p->stack + STKSIZE - 12);
222:
223: p->ctxt[CURRENT].ssp = p->sysstack;
224:
225: p->ctxt[SYSCALL].ssp = (long)(p->stack + ISTKSIZE);
226:
227: p->alarmtim = 0;
228:
229: p->curpri = p->pri;
230:
231: p->slices = SLICES(p->pri);
232:
233: p->starttime = timestamp;
234:
235: p->startdate = datestamp;
236:
1.1.1.6 ! root 237: p->itimer[0].interval = 0;
! 238:
! 239: p->itimer[0].reqtime = 0;
! 240:
! 241: p->itimer[0].timeout = 0;
! 242:
! 243: p->itimer[1].interval = 0;
! 244:
! 245: p->itimer[1].reqtime = 0;
! 246:
! 247: p->itimer[1].timeout = 0;
! 248:
! 249: p->itimer[2].interval = 0;
! 250:
! 251: p->itimer[2].reqtime = 0;
! 252:
! 253: p->itimer[2].timeout = 0;
! 254:
1.1 root 255:
256:
257: ((long *)p->sysstack)[1] = FRAME_MAGIC;
258:
259: ((long *)p->sysstack)[2] = 0;
260:
261: ((long *)p->sysstack)[3] = 0;
262:
263:
264:
265: p->usrtime = p->systime = p->chldstime = p->chldutime = 0;
266:
267:
268:
1.1.1.5 root 269: /* allocate space for memory regions: do it here so that we can fail
270:
271: * before we duplicate anything else. The memory regions are
272:
273: * actually copied later
274:
275: */
276:
277: p->mem = (MEMREGION **) kmalloc(p->num_reg * SIZEOF(MEMREGION *));
278:
279: if (!p->mem) {
280:
281: dispose_proc(p);
282:
283: goto nomem;
284:
285: }
286:
287: p->addr = (virtaddr *)kmalloc(p->num_reg * SIZEOF(virtaddr));
288:
289: if (!p->addr) {
290:
291: kfree(p->mem);
292:
293: dispose_proc(p);
294:
295: goto nomem;
296:
297: }
298:
299:
300:
1.1 root 301: /* copy open handles */
302:
303: for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
304:
305: if ((f = p->handle[i]) != 0) {
306:
1.1.1.6 ! root 307: if (f == (FILEPTR *)1 || f->flags & O_NOINHERIT)
1.1 root 308:
309: /* oops, we didn't really want to copy this handle */
310:
311: p->handle[i] = 0;
312:
313: else
314:
315: f->links++;
316:
317: }
318:
319: }
320:
321:
322:
1.1.1.3 root 323: /* copy root and current directories */
324:
325: for (i = 0; i < NUM_DRIVES; i++) {
326:
327: dup_cookie(&p->root[i], &curproc->root[i]);
328:
329: dup_cookie(&p->curdir[i], &curproc->curdir[i]);
330:
331: }
332:
333:
334:
1.1.1.4 root 335: /* jr: copy ploadinfo */
336:
1.1.1.6 ! root 337: strncpy(p->cmdlin, curproc->cmdlin, 128);
1.1.1.4 root 338:
1.1.1.6 ! root 339: strcpy(p->fname, curproc->fname);
1.1.1.4 root 340:
341:
342:
1.1 root 343: /* clear directory search info */
344:
345: zero((char *)p->srchdta, NUM_SEARCH * SIZEOF(DTABUF *));
346:
1.1.1.4 root 347: zero((char *)p->srchdir, SIZEOF(p->srchdir));
348:
1.1.1.3 root 349: p->searches = 0;
350:
1.1 root 351:
352:
353: /* copy memory */
354:
355: for (i = 0; i < curproc->num_reg; i++) {
356:
1.1.1.2 root 357: p->mem[i] = curproc->mem[i];
358:
359: if (p->mem[i] != 0)
1.1 root 360:
361: p->mem[i]->links++;
362:
363: p->addr[i] = curproc->addr[i];
364:
365: }
366:
367:
368:
1.1.1.3 root 369: /* now that memory ownership is copied, fill in page table */
370:
371: init_page_table(p);
372:
373:
374:
1.1.1.2 root 375: /* child isn't traced */
376:
377: p->ptracer = 0;
378:
379: p->ptraceflags = 0;
380:
381:
382:
1.1 root 383: p->starttime = Tgettime();
384:
385: p->startdate = Tgetdate();
386:
387:
388:
389: p->q_next = 0;
390:
391: p->wait_q = 0;
392:
393: p->gl_next = proclist;
394:
395: proclist = p; /* hook into the process list */
396:
397: return p;
398:
399: }
400:
401:
402:
403: /*
404:
405: * initialize the process table
406:
407: */
408:
409:
410:
411: void
412:
413: init_proc()
414:
415: {
416:
417: int i;
418:
419: FILESYS *fs;
420:
421: fcookie dir;
422:
1.1.1.3 root 423: long_desc *pthold;
424:
425: void *ptmemhold;
426:
1.1 root 427:
428:
429: rootproc = curproc = new_proc();
430:
431: assert(curproc);
432:
433:
434:
1.1.1.3 root 435: pthold = curproc->page_table;
436:
437: ptmemhold = curproc->pt_mem;
438:
1.1 root 439: zero((char *)curproc, (long)sizeof(PROC));
440:
1.1.1.3 root 441: curproc->page_table = pthold;
442:
443: curproc->pt_mem = ptmemhold;
444:
1.1 root 445:
446:
447: curproc->ppid = -1; /* no parent */
448:
449: curproc->domain = DOM_TOS; /* TOS domain */
450:
451: curproc->sysstack = (long) (curproc->stack+STKSIZE-12);
452:
453: curproc->magic = CTXT_MAGIC;
454:
1.1.1.3 root 455: curproc->memflags = F_PROT_S; /* default prot mode: super-only */
456:
1.1 root 457: ((long *)curproc->sysstack)[1] = FRAME_MAGIC;
458:
459: ((long *)curproc->sysstack)[2] = 0;
460:
461: ((long *)curproc->sysstack)[3] = 0;
462:
463:
464:
1.1.1.2 root 465: /* NOTE: in main.c this could be changed, later */
466:
467: curproc->base = _base;
1.1 root 468:
469:
470:
471: strcpy(curproc->name, "MiNT");
472:
473:
474:
475: /* get some memory */
476:
477: curproc->mem = (MEMREGION **)kmalloc(NUM_REGIONS*SIZEOF(MEMREGION *));
478:
479: curproc->addr = (virtaddr *)kmalloc(NUM_REGIONS*SIZEOF(virtaddr));
480:
481: assert(curproc->mem && curproc->addr);
482:
483:
484:
485: /* make sure it's filled with zeros */
486:
487: zero((char *)curproc->addr, NUM_REGIONS * SIZEOF(virtaddr));
488:
489: zero((char *)curproc->mem, NUM_REGIONS * SIZEOF(MEMREGION *));
490:
491: curproc->num_reg = NUM_REGIONS;
492:
493:
494:
495: /* get root and current directories for all drives */
496:
497: for (i = 0; i < NUM_DRIVES; i++) {
498:
499: if ((fs = drives[i]) != 0 && (*fs->root)(i, &dir) == E_OK) {
500:
1.1.1.3 root 501: dup_cookie(&curproc->curdir[i], &dir);
502:
503: curproc->root[i] = dir;
1.1 root 504:
505: } else {
506:
507: curproc->root[i].fs = curproc->curdir[i].fs = 0;
508:
509: curproc->root[i].dev = curproc->curdir[i].dev = i;
510:
511: }
512:
513: }
514:
515:
516:
1.1.1.3 root 517: init_page_table(curproc);
518:
519:
520:
1.1 root 521: /* Set the correct drive. The current directory we
522:
523: * set later, after all file systems have been loaded.
524:
525: */
526:
527:
528:
529: curproc->curdrv = Dgetdrv();
530:
531: proclist = curproc;
532:
533:
534:
535: curproc->umask = 0;
536:
537:
538:
539: /*
540:
541: * some more protection against job control; unless these signals are
542:
543: * re-activated by a shell that knows about job control, they'll have
544:
545: * no effect
546:
547: */
548:
549: curproc->sighandle[SIGTTIN] = curproc->sighandle[SIGTTOU] =
550:
551: curproc->sighandle[SIGTSTP] = SIG_IGN;
552:
553:
554:
555: /* set up some more per-process variables */
556:
557: curproc->starttime = Tgettime();
558:
559: curproc->startdate = Tgetdate();
560:
561: if (has_bconmap)
562:
1.1.1.6 ! root 563: /* init_xbios not happened yet */
! 564:
! 565: curproc->bconmap = (int) Bconmap(-1);
1.1 root 566:
567: else
568:
569: curproc->bconmap = 1;
570:
571:
572:
573: curproc->logbase = (void *)Logbase();
574:
1.1.1.2 root 575: curproc->criticerr = *((long ARGS_ON_STACK (**) P_((long)))0x404L);
1.1 root 576:
577: }
578:
579:
580:
581: /*
582:
583: * reset all process priorities to their base level
584:
585: * called once per second, so that cpu hogs can get _some_ time
586:
587: * slices :-).
588:
589: */
590:
591:
592:
593: void
594:
595: reset_priorities()
596:
597: {
598:
599: PROC *p;
600:
601:
602:
603: for (p = proclist; p; p = p->gl_next) {
604:
1.1.1.6 ! root 605: if (p->slices >= 0) {
1.1 root 606:
1.1.1.6 ! root 607: p->curpri = p->pri;
! 608:
! 609: p->slices = SLICES(p->curpri);
! 610:
! 611: }
1.1 root 612:
613: }
614:
615: }
616:
617:
618:
619: /*
620:
621: * more priority code stuff:
622:
623: * run_next(p, slices): schedule process "p" to run next, with "slices"
624:
625: * initial time slices; "p" does not actually start running until
626:
627: * the next context switch
628:
629: * fresh_slices(slices): give the current process "slices" more slices in
630:
631: * which to run
632:
633: */
634:
635:
636:
637: void
638:
639: run_next(p, slices)
640:
641: PROC *p;
642:
1.1.1.6 ! root 643: int slices;
1.1 root 644:
645: {
646:
1.1.1.6 ! root 647: short sr = spl7();
1.1.1.2 root 648:
1.1.1.6 ! root 649: p->slices = -slices;
1.1 root 650:
651: p->curpri = MAX_NICE;
652:
653: p->wait_q = READY_Q;
654:
655: p->q_next = sys_q[READY_Q];
656:
657: sys_q[READY_Q] = p;
658:
1.1.1.6 ! root 659: spl(sr);
! 660:
1.1 root 661: }
662:
663:
664:
665: void
666:
667: fresh_slices(slices)
668:
669: int slices;
670:
671: {
672:
1.1.1.6 ! root 673: reset_priorities();
! 674:
1.1 root 675: curproc->slices = 0;
676:
677: curproc->curpri = MAX_NICE+1;
678:
1.1.1.6 ! root 679: proc_clock = TIME_SLICE+slices;
1.1 root 680:
681: }
682:
683:
684:
685: /*
686:
687: * add a process to a wait (or ready) queue.
688:
689: *
690:
691: * processes go onto a queue in first in-first out order
692:
693: */
694:
695:
696:
697: void
698:
699: add_q(que, proc)
700:
701: int que;
702:
703: PROC *proc;
704:
705: {
706:
707: PROC *q, **lastq;
708:
709:
710:
711: /* "proc" should not already be on a list */
712:
713: assert(proc->wait_q == 0);
714:
715: assert(proc->q_next == 0);
716:
717:
718:
719: lastq = &sys_q[que];
720:
721: q = *lastq;
722:
723: while(q) {
724:
725: lastq = &q->q_next;
726:
727: q = *lastq;
728:
729: }
730:
731: *lastq = proc;
732:
733: proc->wait_q = que;
734:
1.1.1.6 ! root 735: if (que != READY_Q && proc->slices >= 0) {
1.1 root 736:
737: proc->curpri = proc->pri; /* reward the process */
738:
739: proc->slices = SLICES(proc->curpri);
740:
741: }
742:
743: }
744:
745:
746:
747: /*
748:
749: * remove a process from a queue
750:
751: */
752:
753:
754:
755: void
756:
757: rm_q(que, proc)
758:
759: int que;
760:
761: PROC *proc;
762:
763: {
764:
765: PROC *q;
766:
767: PROC *old = 0;
768:
769:
770:
771: assert(proc->wait_q == que);
772:
773:
774:
775: q = sys_q[que];
776:
777: while (q && q != proc) {
778:
779: old = q;
780:
781: q = q->q_next;
782:
783: }
784:
785: if (q == 0)
786:
787: FATAL("rm_q: unable to remove process from queue");
788:
789:
790:
791: if (old)
792:
793: old->q_next = proc->q_next;
794:
795: else
796:
797: sys_q[que] = proc->q_next;
798:
799:
800:
801: proc->wait_q = 0;
802:
803: proc->q_next = 0;
804:
805: }
806:
807:
808:
809: /*
810:
811: * preempt(): called by the vbl routine and/or the trap handlers when
812:
813: * they detect that a process has exceeded its time slice and hasn't
814:
815: * yielded gracefully. For now, it just does sleep(READY_Q); later,
816:
817: * we might want to keep track of statistics or something.
818:
819: */
820:
821:
822:
1.1.1.2 root 823: void ARGS_ON_STACK
1.1 root 824:
825: preempt()
826:
827: {
828:
829: extern short bconbsiz; /* in bios.c */
830:
831:
832:
833: if (bconbsiz)
834:
835: (void)bflush();
836:
837: else {
838:
839: /* punish the pre-empted process */
840:
841: if (curproc->curpri >= MIN_NICE)
842:
843: curproc->curpri -= 1;
844:
845: }
846:
847: sleep(READY_Q, curproc->wait_cond);
848:
849: }
850:
851:
852:
853: /*
854:
855: * sleep(que, cond): put the current process on the given queue, then switch
856:
857: * contexts. Before a new process runs, give it a fresh time slice. "cond"
858:
859: * is the condition for which the process is waiting, and is placed in
860:
861: * curproc->wait_cond
862:
863: */
864:
865:
866:
1.1.1.6 ! root 867: INLINE static void
1.1 root 868:
1.1.1.6 ! root 869: do_wakeup_things(sr, newslice)
! 870:
! 871: int sr;
! 872:
! 873: int newslice;
1.1 root 874:
875: {
876:
877: /*
878:
879: * check for stack underflow, just in case
880:
881: */
882:
883: auto int foo;
884:
1.1.1.2 root 885: PROC *p;
1.1 root 886:
887:
888:
1.1.1.2 root 889: p = curproc;
1.1 root 890:
1.1.1.2 root 891:
892:
1.1.1.6 ! root 893: if ((sr & 0x700) < 0x500) {
1.1.1.2 root 894:
1.1.1.6 ! root 895: /* skip all this if int level is too high */
1.1.1.2 root 896:
1.1.1.6 ! root 897: if ( p->pid != 0 &&
1.1 root 898:
1.1.1.6 ! root 899: ((long)&foo) < (long)p->stack + ISTKSIZE + 512 ) {
1.1 root 900:
1.1.1.6 ! root 901: ALERT("stack underflow");
! 902:
! 903: handle_sig(SIGBUS);
! 904:
! 905: }
1.1 root 906:
1.1.1.2 root 907:
908:
909: /* see if process' time limit has been exceeded */
910:
911:
912:
1.1.1.6 ! root 913: if (p->maxcpu) {
1.1.1.2 root 914:
1.1.1.6 ! root 915: if (p->maxcpu <= p->systime + p->usrtime) {
1.1.1.2 root 916:
1.1.1.6 ! root 917: DEBUG(("cpu limit exceeded"));
1.1.1.2 root 918:
1.1.1.6 ! root 919: raise(SIGXCPU);
1.1.1.2 root 920:
1.1.1.6 ! root 921: }
1.1.1.2 root 922:
1.1.1.6 ! root 923: }
1.1.1.2 root 924:
925:
926:
1.1 root 927: /*
928:
1.1.1.2 root 929: * check for alarms and similar time out stuff (see timeout.c)
1.1 root 930:
931: */
932:
933:
934:
1.1.1.6 ! root 935: checkalarms();
! 936:
! 937: if (p->sigpending)
! 938:
! 939: check_sigs(); /* check for signals */
! 940:
! 941: }
! 942:
! 943:
! 944:
! 945: if (newslice) {
! 946:
! 947: if (p->slices >= 0) {
! 948:
! 949: proc_clock = TIME_SLICE; /* get a fresh time slice */
! 950:
! 951: } else {
1.1 root 952:
1.1.1.6 ! root 953: proc_clock = TIME_SLICE-p->slices; /* slices set by run_next */
1.1 root 954:
1.1.1.6 ! root 955: p->curpri = p->pri;
1.1 root 956:
1.1.1.6 ! root 957: }
1.1 root 958:
1.1.1.6 ! root 959: p->slices = SLICES(p->curpri);
1.1 root 960:
1.1.1.6 ! root 961: }
1.1 root 962:
1.1.1.2 root 963: p->slices = SLICES(p->curpri);
1.1 root 964:
965: }
966:
967:
968:
1.1.1.6 ! root 969: static long sleepcond, iwakecond;
! 970:
! 971:
! 972:
1.1.1.5 root 973: /*
974:
975: * sleep: returns 1 if no signals have happened since our last sleep, 0
976:
977: * if some have
978:
979: */
980:
981:
982:
983: int ARGS_ON_STACK
1.1 root 984:
1.1.1.6 ! root 985: sleep(_que, cond)
1.1 root 986:
1.1.1.6 ! root 987: int _que;
1.1 root 988:
989: long cond;
990:
991: {
992:
993: PROC *p;
994:
1.1.1.6 ! root 995: short sr, que = _que & 0xff;
1.1 root 996:
1.1.1.5 root 997: ulong onsigs = curproc->nsigs;
998:
1.1 root 999: extern short kintr; /* in bios.c */
1000:
1.1.1.6 ! root 1001: int newslice = 1;
! 1002:
1.1.1.4 root 1003: #ifndef MULTITOS
1004:
1.1 root 1005: #ifdef FASTTEXT
1006:
1007: extern int hardscroll; /* in fasttext.c */
1008:
1009: #endif
1010:
1.1.1.4 root 1011: #endif
1012:
1.1 root 1013:
1014:
1.1.1.6 ! root 1015: /* save condition, checkbttys may just wake() it right away...
! 1016:
! 1017: * note this assumes the condition will never be waked from interrupts
! 1018:
! 1019: * or other than thru wake() before we really went to sleep, otherwise
! 1020:
! 1021: * use the 0x100 bit like select
! 1022:
! 1023: */
! 1024:
! 1025: sleepcond = cond;
! 1026:
! 1027:
! 1028:
1.1 root 1029: /*
1030:
1031: * if there have been keyboard interrupts since our last sleep, check for
1032:
1033: * special keys like CTRL-ALT-Fx
1034:
1035: */
1036:
1037:
1038:
1.1.1.6 ! root 1039: sr = spl7();
! 1040:
! 1041: if ((sr & 0x700) < 0x500) {
! 1042:
! 1043: /* can't call checkkeys if sleep was called with interrupts off -nox */
! 1044:
! 1045: spl(sr);
! 1046:
! 1047: (void)checkbttys();
! 1048:
! 1049: if (kintr) {
! 1050:
! 1051: (void)checkkeys();
! 1052:
! 1053: kintr = 0;
! 1054:
! 1055: }
! 1056:
! 1057: sr = spl7();
! 1058:
! 1059: if ((curproc->sigpending & ~(curproc->sigmask)) &&
! 1060:
! 1061: curproc->pid && que != ZOMBIE_Q && que != TSR_Q) {
1.1 root 1062:
1.1.1.6 ! root 1063: spl(sr);
1.1 root 1064:
1.1.1.6 ! root 1065: check_sigs();
! 1066:
! 1067: sr = spl7();
! 1068:
! 1069: sleepcond = 0; /* possibly handled a signal, return */
! 1070:
! 1071: }
1.1 root 1072:
1073: }
1074:
1075:
1076:
1.1.1.6 ! root 1077: /*
! 1078:
! 1079: * kay: If _que & 0x100 != 0 then take curproc->wait_cond != cond as an
! 1080:
! 1081: * indicatation that the wakeup has already happend before we actually
! 1082:
! 1083: * go to sleep and return immediatly.
! 1084:
! 1085: */
! 1086:
! 1087:
! 1088:
! 1089: if ((que == READY_Q && !sys_q[READY_Q]) ||
! 1090:
! 1091: ((sleepcond != cond ||
! 1092:
! 1093: (iwakecond == cond && cond) ||
! 1094:
! 1095: (_que & 0x100 && curproc->wait_cond != cond)) &&
! 1096:
! 1097: (!sys_q[READY_Q] || (newslice = 0, proc_clock)))) {
1.1 root 1098:
1099: /* we're just going to wake up again right away! */
1100:
1.1.1.6 ! root 1101: iwakecond = 0;
! 1102:
! 1103: spl(sr);
! 1104:
! 1105: do_wakeup_things(sr, newslice);
1.1 root 1106:
1.1.1.5 root 1107: return (onsigs != curproc->nsigs);
1.1 root 1108:
1109: }
1110:
1111:
1112:
1.1.1.6 ! root 1113: /*
! 1114:
! 1115: * unless our time slice has expired (proc_clock == 0) and other
! 1116:
! 1117: * processes are ready...
! 1118:
! 1119: */
1.1 root 1120:
1.1.1.6 ! root 1121: iwakecond = 0;
1.1 root 1122:
1.1.1.6 ! root 1123: if (!newslice)
! 1124:
! 1125: que = READY_Q;
! 1126:
! 1127: else
! 1128:
! 1129: curproc->wait_cond = cond;
1.1 root 1130:
1131: add_q(que, curproc);
1132:
1133:
1134:
1.1.1.6 ! root 1135: /* alright curproc is on que now... maybe there's an interrupt pending
! 1136:
! 1137: * that will wakeselect or signal someone
! 1138:
! 1139: */
! 1140:
! 1141: spl(sr);
1.1 root 1142:
1143: if (!sys_q[READY_Q]) {
1144:
1145: /* hmm, no-one is ready to run. might be a deadlock, might not.
1146:
1147: * first, try waking up any napping processes; if that doesn't work,
1148:
1149: * run the root process, just so we have someone to charge time
1150:
1151: * to.
1152:
1153: */
1154:
1.1.1.2 root 1155: wake(SELECT_Q, (long)nap);
1.1 root 1156:
1.1.1.6 ! root 1157: sr = spl7();
! 1158:
1.1 root 1159: if (!sys_q[READY_Q]) {
1160:
1161: p = rootproc; /* pid 0 */
1162:
1163: rm_q(p->wait_q, p);
1164:
1165: add_q(READY_Q, p);
1166:
1167: }
1168:
1.1.1.6 ! root 1169: spl(sr);
! 1170:
1.1 root 1171: }
1172:
1173:
1174:
1175: /*
1176:
1177: * Walk through the ready list, to find what process should run next.
1178:
1179: * Lower priority processes don't get to run every time through this
1180:
1181: * loop; if "p->slices" is positive, it's the number of times that they
1182:
1183: * will have to miss a turn before getting to run again
1184:
1185: */
1186:
1.1.1.3 root 1187:
1188:
1189: /*
1190:
1191: * Loop structure:
1192:
1193: * while (we haven't picked anybody) {
1194:
1195: * for (each process) {
1196:
1197: * if (sleeping off a penalty) {
1198:
1199: * decrement penalty counter
1200:
1201: * }
1202:
1203: * else {
1204:
1205: * pick this one and break out of both loops
1206:
1207: * }
1208:
1209: * }
1210:
1211: * }
1212:
1213: */
1214:
1.1 root 1215: p = 0;
1216:
1217:
1218:
1219: while (!p) {
1220:
1221: for (p = sys_q[READY_Q]; p; p = p->q_next) {
1222:
1223: if (p->slices > 0)
1224:
1225: p->slices--;
1226:
1227: else
1228:
1229: break;
1230:
1231: }
1232:
1233: }
1234:
1.1.1.3 root 1235:
1236:
1237: /* p is our victim */
1238:
1239:
1240:
1.1 root 1241: rm_q(READY_Q, p);
1242:
1243:
1244:
1245: spl(sr);
1246:
1247:
1248:
1249: if (save_context(&(curproc->ctxt[CURRENT]))) {
1250:
1251: /*
1252:
1253: * restore per-process variables here
1254:
1255: */
1256:
1.1.1.4 root 1257: #ifndef MULTITOS
1258:
1.1 root 1259: #ifdef FASTTEXT
1260:
1261: if (!hardscroll)
1262:
1263: *((void **)0x44eL) = curproc->logbase;
1264:
1.1.1.4 root 1265: #endif
1266:
1.1.1.6 ! root 1267: #endif
! 1268:
! 1269: do_wakeup_things(sr, 1);
1.1 root 1270:
1.1.1.5 root 1271: return (onsigs != curproc->nsigs);
1.1 root 1272:
1273: }
1274:
1275: /*
1276:
1277: * save per-process variables here
1278:
1279: */
1280:
1.1.1.4 root 1281: #ifndef MULTITOS
1282:
1.1 root 1283: #ifdef FASTTEXT
1284:
1285: if (!hardscroll)
1286:
1287: curproc->logbase = *((void **)0x44eL);
1288:
1.1.1.4 root 1289: #endif
1290:
1.1.1.6 ! root 1291: #endif
! 1292:
! 1293:
! 1294:
1.1 root 1295: curproc->ctxt[CURRENT].regs[0] = 1;
1296:
1297: curproc = p;
1298:
1299: proc_clock = TIME_SLICE; /* fresh time */
1300:
1301: if ((p->ctxt[CURRENT].sr & 0x2000) == 0) { /* user mode? */
1302:
1303: leave_kernel();
1304:
1305: }
1306:
1307: assert(p->magic == CTXT_MAGIC);
1308:
1.1.1.3 root 1309: change_context(&(p->ctxt[CURRENT]));
1.1 root 1310:
1.1.1.5 root 1311: /* not reached */
1312:
1313: return 0;
1314:
1.1 root 1315: }
1316:
1317:
1318:
1319: /*
1320:
1321: * wake(que, cond): wake up all processes on the given queue that are waiting
1322:
1323: * for the indicated condition
1324:
1325: */
1326:
1327:
1328:
1.1.1.6 ! root 1329: INLINE static void
1.1 root 1330:
1.1.1.6 ! root 1331: do_wake(que, cond)
1.1 root 1332:
1333: int que;
1334:
1335: long cond;
1336:
1337: {
1338:
1339: PROC *p;
1340:
1.1.1.6 ! root 1341: top:
! 1342:
! 1343: for(p = sys_q[que]; p;) {
1.1 root 1344:
1.1.1.6 ! root 1345: short s = spl7();
! 1346:
! 1347: PROC *q;
! 1348:
! 1349:
! 1350:
! 1351: /* check p is still on the right queue, maybe an interrupt just woke it... */
! 1352:
! 1353: if (p->wait_q != que) {
! 1354:
! 1355: spl(s);
! 1356:
! 1357: goto top;
! 1358:
! 1359: }
! 1360:
! 1361: q = p;
! 1362:
! 1363: p = p->q_next;
! 1364:
! 1365: if (q->wait_cond == cond) {
! 1366:
! 1367: rm_q(que, q);
! 1368:
! 1369: add_q(READY_Q, q);
! 1370:
! 1371: }
! 1372:
! 1373: spl(s);
! 1374:
! 1375: }
! 1376:
! 1377: }
! 1378:
! 1379:
! 1380:
! 1381: void ARGS_ON_STACK
! 1382:
! 1383: wake(que, cond)
! 1384:
! 1385: int que;
! 1386:
! 1387: long cond;
! 1388:
! 1389: {
1.1 root 1390:
1391: if (que == READY_Q) {
1392:
1393: ALERT("wake: why wake up ready processes??");
1394:
1395: return;
1396:
1397: }
1398:
1.1.1.6 ! root 1399: if (sleepcond == cond)
1.1 root 1400:
1.1.1.6 ! root 1401: sleepcond = 0;
1.1 root 1402:
1.1.1.6 ! root 1403: do_wake(que, cond);
1.1 root 1404:
1.1.1.6 ! root 1405: }
1.1.1.3 root 1406:
1.1 root 1407:
1.1.1.6 ! root 1408:
! 1409: /*
! 1410:
! 1411: * iwake(que, cond, pid): special version of wake() for IO interrupt
! 1412:
! 1413: * handlers and such. the normal wake() would lose when its
! 1414:
! 1415: * interrupt goes off just before a process is calling sleep() on the
! 1416:
! 1417: * same condition (similar problem like with wakeselect...)
! 1418:
! 1419: *
! 1420:
! 1421: * use like this:
! 1422:
! 1423: * static ipid = -1;
! 1424:
! 1425: * static volatile sleepers = 0; (optional, to save useless calls)
! 1426:
! 1427: * ...
! 1428:
! 1429: * device_read(...)
! 1430:
! 1431: * {
! 1432:
! 1433: * ipid = curproc->pid; (p_getpid() for device drivers...)
! 1434:
! 1435: * while (++sleepers, (not ready for IO...)) {
! 1436:
! 1437: * sleep(IO_Q, cond);
! 1438:
! 1439: * if (--sleepers < 0)
! 1440:
! 1441: * sleepers = 0;
! 1442:
! 1443: * }
! 1444:
! 1445: * if (--sleepers < 0)
! 1446:
! 1447: * sleepers = 0;
! 1448:
! 1449: * ipid = -1;
! 1450:
! 1451: * ...
! 1452:
! 1453: * }
! 1454:
! 1455: *
! 1456:
! 1457: * and in the interrupt handler:
! 1458:
! 1459: * if (sleepers > 0) {
! 1460:
! 1461: * sleepers = 0;
! 1462:
! 1463: * iwake(IO_Q, cond, ipid);
! 1464:
! 1465: * }
! 1466:
! 1467: *
! 1468:
! 1469: * caller is responsible for not trying to wake READY_Q or other nonsense :)
! 1470:
! 1471: * and making sure the passed pid is always -1 when curproc is calling
! 1472:
! 1473: * sleep() for another than the waked que/condition.
! 1474:
! 1475: */
! 1476:
! 1477:
! 1478:
! 1479: void ARGS_ON_STACK
! 1480:
! 1481: iwake(que, cond, pid)
! 1482:
! 1483: int que;
! 1484:
! 1485: long cond;
! 1486:
! 1487: short pid;
! 1488:
! 1489: {
! 1490:
! 1491: if (pid >= 0) {
! 1492:
! 1493: short s = spl7();
! 1494:
! 1495: if (iwakecond == cond) {
1.1 root 1496:
1.1.1.3 root 1497: spl(s);
1498:
1.1.1.6 ! root 1499: return;
1.1 root 1500:
1501: }
1502:
1.1.1.6 ! root 1503: if (curproc->pid == pid && !curproc->wait_q)
! 1504:
! 1505: iwakecond = cond;
! 1506:
! 1507: spl(s);
! 1508:
1.1 root 1509: }
1510:
1.1.1.6 ! root 1511: do_wake(que, cond);
! 1512:
1.1 root 1513: }
1514:
1515:
1516:
1517: /*
1518:
1519: * wakeselect(p): wake process p from a select() system call
1520:
1521: * may be called by an interrupt handler or whatever
1522:
1523: */
1524:
1525:
1526:
1.1.1.2 root 1527: void ARGS_ON_STACK
1.1 root 1528:
1529: wakeselect(param)
1530:
1531: long param;
1532:
1533: {
1534:
1535: PROC *p = (PROC *)param;
1536:
1537: short s;
1538:
1.1.1.6 ! root 1539: extern short select_coll; /* in dosfile.c */
! 1540:
1.1 root 1541:
1542:
1543: s = spl7(); /* block interrupts */
1544:
1.1.1.6 ! root 1545: if(p->wait_cond == (long)wakeselect ||
! 1546:
! 1547: p->wait_cond == (long)&select_coll) {
1.1 root 1548:
1549: p->wait_cond = 0;
1550:
1551: }
1552:
1553: if (p->wait_q == SELECT_Q) {
1554:
1555: rm_q(SELECT_Q, p);
1556:
1557: add_q(READY_Q, p);
1558:
1559: }
1560:
1561: spl(s);
1562:
1563: }
1564:
1565:
1566:
1567: /*
1568:
1569: * dump out information about processes
1570:
1571: */
1572:
1573:
1574:
1575: /*
1576:
1.1.1.3 root 1577: * kludge alert! In order to get the right pid printed by FORCE, we use
1.1 root 1578:
1579: * curproc as the loop variable.
1580:
1.1.1.3 root 1581: *
1582:
1583: * I have changed this function so it is more useful to a user, less to
1584:
1585: * somebody debugging MiNT. I haven't had any stack problems in MiNT
1586:
1587: * at all, so I consider all that stack info wasted space. -- AKP
1588:
1.1 root 1589: */
1590:
1591:
1592:
1.1.1.4 root 1593: #ifdef DEBUG_INFO
1.1.1.3 root 1594:
1595: static const char *qstring[] = {
1596:
1597: "run", "ready", "wait", "iowait", "zombie", "tsr", "stop", "select"
1598:
1599: };
1600:
1601:
1602:
1603: /* UNSAFE macro for qname, evaluates x 1, 2, or 3 times */
1604:
1605: #define qname(x) ((x >= 0 && x < NUM_QUEUES) ? qstring[x] : "unkn")
1606:
1607: #endif
1608:
1609:
1610:
1.1.1.6 ! root 1611: #include "loadave.h"
! 1612:
! 1613:
! 1614:
! 1615: unsigned long uptime = 0;
! 1616:
! 1617: unsigned long avenrun[3] = {0,0,0};
! 1618:
! 1619: short uptimetick = 200;
! 1620:
! 1621: static int number_running;
! 1622:
! 1623: static int one_min_ptr = 0, five_min_ptr = 0, fifteen_min_ptr = 0;
! 1624:
! 1625: static unsigned long sum1 = 0, sum5 = 0, sum15 = 0;
! 1626:
! 1627: static unsigned char one_min[SAMPS_PER_MIN];
! 1628:
! 1629: static unsigned char five_min[SAMPS_PER_5MIN];
! 1630:
! 1631: static unsigned char fifteen_min[SAMPS_PER_15MIN];
! 1632:
! 1633:
! 1634:
1.1 root 1635: void
1636:
1637: DUMPPROC()
1638:
1639: {
1640:
1.1.1.4 root 1641: #ifdef DEBUG_INFO
1.1.1.2 root 1642:
1.1 root 1643: PROC *p = curproc;
1644:
1645:
1646:
1.1.1.6 ! root 1647: FORCE("Uptime: %ld seconds Loads: %ld %ld %ld Processes running: %d",
! 1648:
! 1649: uptime,
! 1650:
! 1651: (avenrun[0]*100)/2048 , (avenrun[1]*100)/2048, (avenrun[2]*100/2048),
! 1652:
! 1653: number_running);
! 1654:
! 1655:
! 1656:
1.1 root 1657: for (curproc = proclist; curproc; curproc = curproc->gl_next) {
1658:
1.1.1.3 root 1659: FORCE("state %s PC: %lx BP: %lx",
1.1 root 1660:
1.1.1.3 root 1661: qname(curproc->wait_q),
1.1 root 1662:
1663: curproc->ctxt[SYSCALL].pc,
1664:
1.1.1.3 root 1665: curproc->base);
1.1 root 1666:
1667: }
1668:
1669: curproc = p; /* restore the real curproc */
1670:
1.1.1.2 root 1671: #endif
1672:
1.1 root 1673: }
1674:
1.1.1.6 ! root 1675:
! 1676:
! 1677: unsigned long
! 1678:
! 1679: gen_average(sum, load_ptr, max_size)
! 1680:
! 1681: unsigned long *sum;
! 1682:
! 1683: unsigned char *load_ptr;
! 1684:
! 1685: int max_size;
! 1686:
! 1687: {
! 1688:
! 1689: int old_load, new_load;
! 1690:
! 1691:
! 1692:
! 1693: old_load = (int)*load_ptr;
! 1694:
! 1695: new_load = number_running;
! 1696:
! 1697: *load_ptr = (char)new_load;
! 1698:
! 1699:
! 1700:
! 1701: *sum += ((long) (new_load - old_load) * LOAD_SCALE);
! 1702:
! 1703:
! 1704:
! 1705: return (*sum / max_size);
! 1706:
! 1707: }
! 1708:
! 1709:
! 1710:
! 1711: void
! 1712:
! 1713: calc_load_average()
! 1714:
! 1715: {
! 1716:
! 1717: PROC *p;
! 1718:
! 1719:
! 1720:
! 1721: uptime++;
! 1722:
! 1723: uptimetick += 200;
! 1724:
! 1725:
! 1726:
! 1727: if (uptime % 5) return;
! 1728:
! 1729:
! 1730:
! 1731: number_running = 0;
! 1732:
! 1733:
! 1734:
! 1735: for (p = proclist; p; p = p->gl_next)
! 1736:
! 1737: if (p != rootproc)
! 1738:
! 1739: if ((p->wait_q == 0) || (p->wait_q == 1))
! 1740:
! 1741: number_running++;
! 1742:
! 1743:
! 1744:
! 1745: avenrun[0] = gen_average(&sum1, &one_min[one_min_ptr++],
! 1746:
! 1747: SAMPS_PER_MIN);
! 1748:
! 1749:
! 1750:
! 1751: if (one_min_ptr == SAMPS_PER_MIN)
! 1752:
! 1753: one_min_ptr = 0;
! 1754:
! 1755:
! 1756:
! 1757: avenrun[1] = gen_average(&sum5, &five_min[five_min_ptr++],
! 1758:
! 1759: SAMPS_PER_5MIN);
! 1760:
! 1761:
! 1762:
! 1763: if (five_min_ptr == SAMPS_PER_5MIN)
! 1764:
! 1765: five_min_ptr = 0;
! 1766:
! 1767:
! 1768:
! 1769: avenrun[2] = gen_average(&sum15, &fifteen_min[fifteen_min_ptr++],
! 1770:
! 1771: SAMPS_PER_15MIN);
! 1772:
! 1773:
! 1774:
! 1775: if (fifteen_min_ptr == SAMPS_PER_15MIN)
! 1776:
! 1777: fifteen_min_ptr = 0;
! 1778:
! 1779:
! 1780:
! 1781: }
! 1782:
! 1783:
! 1784:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.