|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.5 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: /*
14:
15: * mem.c:: routines for managing memory regions
16:
17: */
18:
19:
20:
21: #include "mint.h"
22:
1.1.1.3 root 23: #include "fasttext.h" /* for line A stuff */
24:
25:
26:
27: #ifndef VgetSize
28:
1.1.1.6 ! root 29: #if defined(__GNUC__) && defined(trap_14_ww)
! 30:
! 31: #define VgetSize(mode) (long)trap_14_ww((short)91,(short)(mode))
! 32:
! 33: #define Vsetmode(mode) (short)trap_14_ww((short)88,(short)(mode))
! 34:
! 35: #else
! 36:
1.1.1.3 root 37: extern long xbios();
38:
39: #define VgetSize(mode) xbios(91, (short)(mode))
40:
41: #define Vsetmode(mode) xbios(88, (short)(mode))
42:
43: #endif
44:
1.1.1.6 ! root 45: #endif
! 46:
1.1 root 47:
48:
49: static long core_malloc P_((long, int));
50:
1.1.1.3 root 51: static void core_free P_((long));
52:
1.1.1.6 ! root 53: static void terminateme P_((int code));
! 54:
1.1 root 55:
56:
57: /* macro for testing whether a memory region is free */
58:
59: #define ISFREE(m) ((m)->links == 0)
60:
61:
62:
63: /*
64:
1.1.1.2 root 65: * list of shared text regions currently being executed
66:
67: */
68:
69: SHTEXT *text_reg = 0;
70:
71:
72:
73: /*
74:
1.1 root 75: * initialize memory routines
76:
77: */
78:
79:
80:
81: /* initial number of memory regions */
82:
1.1.1.5 root 83: #define NREGIONS ((8*1024)/sizeof(MEMREGION))
1.1 root 84:
85:
86:
87: /* number of new regions to allocate when the initial ones are used up */
88:
1.1.1.5 root 89: #define NEWREGIONS ((8*1024)/sizeof(MEMREGION))
1.1 root 90:
91:
92:
93: static MEMREGION use_regions[NREGIONS+1];
94:
95: MEMREGION *rfreelist;
96:
97:
98:
1.1.1.5 root 99: /* variable for debugging purposes; number of times we've needed
100:
101: * to get new regions
102:
103: */
104:
105: int num_reg_requests = 0;
106:
107:
108:
1.1.1.3 root 109: /* these variables are set in init_core(), and used in
110:
111: * init_mem()
112:
113: */
114:
115: static ulong scrnsize, scrnplace;
116:
117: static SCREEN *vscreen;
118:
119:
120:
1.1 root 121: void
122:
123: init_mem()
124:
125: {
126:
127: int i;
128:
1.1.1.3 root 129: MEMREGION *r;
130:
131: long newbase;
132:
1.1 root 133:
134:
135: use_regions[NREGIONS].next = 0;
136:
137: for (i = 0; i < NREGIONS; i++) {
138:
139: use_regions[i].next = &use_regions[i+1];
140:
141: }
142:
143: rfreelist = use_regions;
144:
145:
146:
147: init_core();
148:
149: init_swap();
150:
1.1.1.3 root 151:
152:
153: init_tables(); /* initialize MMU constants */
154:
155:
156:
157: /* mark all the regions in the core & alt lists as "invalid" */
158:
159: for (r = *core; r; r = r->next) {
160:
161: mark_region(r,PROT_I);
162:
163: }
164:
165: for (r = *alt; r; r = r->next) {
166:
167: mark_region(r,PROT_I);
168:
169: }
170:
171:
172:
173: /* make sure the screen is set up properly */
174:
175: newbase = s_realloc(scrnsize);
176:
177:
178:
179: /* if we did get a new screen, point the new screen
180:
181: * at the right place after copying the data
182:
183: * if possible, save the screen to another buffer,
184:
185: * since if the new screen and old screen overlap
186:
187: * the blit will look very ugly.
188:
189: * Note that if the screen isn't moveable, then we set
190:
191: * scrnsize to a ridiculously large value, and so the
192:
193: * s_realloc above failed.
194:
195: */
196:
197: if (newbase) {
198:
199: /* find a free region for temp storage */
200:
201: for (r = *core; r; r = r->next) {
202:
203: if (ISFREE(r) && r->len >= scrnsize)
204:
205: break;
206:
207: }
208:
209:
210:
211: if (r) {
212:
213: quickmove((char *)r->loc, (char *)scrnplace, scrnsize);
214:
215: Setscreen((void *)r->loc, (void *)r->loc, -1);
216:
217: Vsync();
218:
219: quickmove((char *)newbase, (char *)r->loc, scrnsize);
220:
221: } else {
222:
223: quickmove((char *)newbase, (char *)scrnplace, scrnsize);
224:
225: }
226:
227: Setscreen((void *)newbase, (void *)newbase, -1);
228:
229: /* fix the cursor */
230:
231: Cconws("\r\n");
232:
233: }
234:
1.1 root 235: }
236:
237:
238:
1.1.1.5 root 239: void
240:
241: restr_screen()
242:
243: {
244:
245: long base = (long) Physbase ();
246:
247: MEMREGION *r;
248:
249:
250:
251: if (base != scrnplace)
252:
253: {
254:
255: for (r = *core; r; r = r->next)
256:
257: {
258:
259: if (ISFREE (r) && r->len >= scrnsize)
260:
261: break;
262:
263: }
264:
265: if (r)
266:
267: {
268:
269: quickmove ((char *) r->loc, (char *) base, scrnsize);
270:
271: Setscreen ((void *) r->loc, (void *) r->loc, -1);
272:
273: Vsync ();
274:
275: quickmove ((char *) scrnplace, (char *) r->loc, scrnsize);
276:
277: }
278:
279: else
280:
281: quickmove ((char *) scrnplace, (char *) base, scrnsize);
282:
283: Setscreen ((void *) scrnplace, (void *) scrnplace, -1);
284:
285: Cconws ("\r\n");
286:
287: }
288:
289: }
290:
291:
292:
1.1 root 293: /*
294:
295: * init_core(): initialize the core memory map (normal ST ram) and also
296:
297: * the alternate memory map (fast ram on the TT)
298:
299: */
300:
301:
302:
303: static MEMREGION *_core_regions = 0, *_alt_regions = 0,
304:
305: *_ker_regions = 0;
306:
307:
308:
309: MMAP core = &_core_regions;
310:
311: MMAP alt = &_alt_regions;
312:
313: MMAP ker = &_ker_regions;
314:
315:
316:
317: /* note: add_region must adjust both the size and starting
318:
319: * address of the region being added so that memory is
320:
321: * always properly aligned
322:
323: */
324:
325:
326:
327: int
328:
329: add_region(map, place, size, mflags)
330:
331: MMAP map;
332:
333: ulong place, size;
334:
335: unsigned mflags; /* initial flags for region */
336:
337: {
338:
1.1.1.3 root 339: MEMREGION *m;
1.1 root 340:
1.1.1.3 root 341: ulong trimsize;
1.1 root 342:
343:
344:
1.1.1.3 root 345: TRACELOW(("add_region(map=%lx,place=%lx,size=%lx,flags=%x)",
1.1 root 346:
1.1.1.3 root 347: map,place,size,mflags));
1.1 root 348:
349:
350:
351: m = new_region();
352:
353: if (m == 0)
354:
355: return 0; /* failure */
356:
357: m->links = 0;
358:
359:
360:
1.1.1.3 root 361: if (place & MASKBITS) {
362:
363: /* increase place & shorten size by the amount we're trimming */
364:
365: trimsize = (MASKBITS+1) - (place & MASKBITS);
366:
367: if (size <= trimsize) goto lose;
368:
369: size -= trimsize;
370:
371: place += trimsize;
372:
373: }
374:
375:
376:
377: /* now trim size DOWN to a multiple of pages */
378:
379: if (size & MASKBITS) size &= ~MASKBITS;
380:
381:
382:
383: /* only add if there's anything left */
384:
385: if (size) {
386:
387: m->len = size;
1.1 root 388:
1.1.1.3 root 389: m->loc = place;
390:
391: m->next = *map;
392:
393: m->mflags = mflags;
394:
395: *map = m;
396:
397: }
398:
399: else {
1.1 root 400:
1.1.1.3 root 401: /* succeed but don't do anything; dispose of region */
402:
403: lose: dispose_region(m);
404:
405: }
1.1 root 406:
407: return 1; /* success */
408:
409: }
410:
411:
412:
413: static long
414:
415: core_malloc(amt, mode)
416:
417: long amt;
418:
419: int mode;
420:
421: {
422:
423: static int mxalloc = -1; /* does GEMDOS know about Mxalloc? */
424:
425: long ret;
426:
427:
428:
429: if (mxalloc < 0) {
430:
431: ret = (long)Mxalloc(-1L, 0);
432:
433: if (ret == -32) mxalloc = 0; /* unknown function */
434:
435: else if (ret >= 0) mxalloc = 1;
436:
437: else {
438:
439: ALERT("GEMDOS returned %ld from Mxalloc", ret);
440:
441: mxalloc = 0;
442:
443: }
444:
445: }
446:
447: if (mxalloc)
448:
1.1.1.4 root 449: return (long) Mxalloc(amt, mode);
1.1 root 450:
451: else if (mode == 1)
452:
453: return 0L;
454:
455: else
456:
1.1.1.4 root 457: return (long) Malloc(amt);
1.1 root 458:
459: }
460:
461:
462:
1.1.1.3 root 463: static void
464:
465: core_free(where)
466:
467: long where;
468:
469: {
470:
471: Mfree((void *)where);
472:
473: }
474:
475:
476:
1.1 root 477: void
478:
479: init_core()
480:
481: {
482:
1.1.1.3 root 483: extern int FalconVideo; /* set in main.c */
484:
485: int scrndone = 0;
486:
1.1 root 487: ulong size;
488:
489: ulong place;
490:
1.1.1.3 root 491: ulong temp;
492:
1.1 root 493: void *tossave;
494:
495:
496:
497: tossave = (void *)core_malloc((long)TOS_MEM, 0);
498:
499: if (!tossave) {
500:
501: FATAL("Not enough memory to run MiNT");
502:
503: }
504:
505:
506:
507: /* initialize kernel memory */
508:
509: place = (ulong)core_malloc(KERNEL_MEM, 3);
510:
511: if (place != 0) {
512:
1.1.1.3 root 513: nalloc_arena_add((void *)place,KERNEL_MEM);
514:
515: }
516:
517:
518:
519: /*
520:
521: * find out where the screen is. We want to manage the screen
522:
523: * memory along with all the other memory, so that Srealloc()
524:
525: * can be used by the XBIOS to allocate screens from the
526:
527: * end of memory -- this avoids fragmentation problems when
528:
529: * changing resolutions.
530:
531: */
532:
533: /* Note, however, that some graphics boards (e.g. Matrix)
534:
535: * are unable to change the screen address. We fake out the
536:
537: * rest of our code by pretending to have a really huge
538:
539: * screen that can't be changed.
540:
541: */
542:
543: scrnplace = (long)Physbase();
544:
545:
546:
547: vscreen = (SCREEN *)((char *)lineA0() - 346);
548:
549: if (FalconVideo) {
550:
551: /* the Falcon can tell us the screen size */
552:
553: scrnsize = VgetSize(Vsetmode(-1));
554:
555: } else {
556:
557: /* otherwise, use the line A variables */
558:
559: scrnsize = (vscreen->maxy+1)*(long)vscreen->linelen;
560:
561: }
562:
563:
564:
565: /* check for a graphics card with fixed screen location */
566:
567: #define phys_top_st (*(ulong *)0x42eL)
568:
569:
570:
571: if (scrnplace >= phys_top_st) {
572:
573: /* screen isn't in ST RAM */
574:
575: scrnsize = 0x7fffffffUL;
576:
577: scrndone = 1;
578:
579: } else {
580:
581: temp = (ulong)core_malloc(scrnsize+256L, 0);
582:
583: if (temp) {
584:
585: (void)Setscreen((void *)-1L,
586:
587: (void *)((temp+511)&(0xffffff00L)), -1);
588:
1.1.1.4 root 589: if ((long)Physbase() != ((temp+511)&(0xffffff00L))) {
1.1.1.3 root 590:
591: scrnsize = 0x7fffffffUL;
592:
593: scrndone = 1;
594:
595: }
596:
597: (void)Setscreen((void *)-1L, (void *)scrnplace, -1);
598:
599: core_free(temp);
600:
601: }
1.1 root 602:
603: }
604:
605:
606:
607: /* initialize ST RAM */
608:
609: size = (ulong)core_malloc(-1L, 0);
610:
611: while (size > 0) {
612:
613: place = (ulong)core_malloc(size, 0);
614:
1.1.1.5 root 615: if (!scrndone && (place + size == scrnplace)) {
1.1.1.3 root 616:
617: size += scrnsize;
618:
619: scrndone = 1;
620:
621: }
622:
1.1 root 623: if (!add_region(core, place, size, M_CORE))
624:
625: FATAL("init_mem: unable to add a region");
626:
627: size = (ulong)core_malloc(-1L, 0);
628:
629: }
630:
631:
632:
1.1.1.3 root 633: if (!scrndone) {
634:
635: (void)add_region(core, scrnplace, scrnsize, M_CORE);
636:
637: }
638:
639:
640:
1.1 root 641: /* initialize alternate RAM */
642:
643: size = (ulong)core_malloc(-1L, 1);
644:
645: while (size > 0) {
646:
647: place = (ulong)core_malloc(size, 1);
648:
649: if (!add_region(alt, place, size, M_ALT))
650:
651: FATAL("init_mem: unable to add a region");
652:
653: size = (ulong)core_malloc(-1L, 1);
654:
655: }
656:
657:
658:
659: (void)Mfree(tossave); /* leave some memory for TOS to use */
660:
661: }
662:
663:
664:
665: /*
666:
667: * init_swap(): initialize the swap area; for now, this does nothing
668:
669: */
670:
671:
672:
673: MEMREGION *_swap_regions = 0;
674:
675: MMAP swap = &_swap_regions;
676:
677:
678:
679: void
680:
681: init_swap()
682:
683: {
684:
685: }
686:
687:
688:
689: /*
690:
691: * routines for allocating/deallocating memory regions
692:
693: */
694:
695:
696:
697: /*
698:
699: * new_region returns a new memory region descriptor, or NULL
700:
701: */
702:
703:
704:
705: MEMREGION *
706:
707: new_region()
708:
709: {
710:
711: MEMREGION *m, *newfrees;
712:
713: int i;
714:
715:
716:
717: m = rfreelist;
718:
719: if (!m) {
720:
721: ALERT("new_region: ran out of free regions");
722:
723: return 0;
724:
725: }
726:
727: assert(ISFREE(m));
728:
729: rfreelist = m->next;
730:
731: m->next = 0;
732:
733:
734:
735: /* if we're running low on free regions, allocate some more
736:
737: * we have to do this with at least 1 free region left so that get_region
738:
739: * has a chance of working
740:
741: */
742:
743: if (rfreelist && !rfreelist->next) {
744:
745: MEMREGION *newstuff;
746:
747:
748:
1.1.1.3 root 749: TRACELOW(("get_region: getting new region descriptors"));
1.1 root 750:
1.1.1.3 root 751: newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1 root 752:
753: if (!newstuff)
754:
1.1.1.3 root 755: newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1 root 756:
757: if (!newstuff)
758:
1.1.1.3 root 759: newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1 root 760:
761: newfrees = newstuff ? (MEMREGION *)newstuff->loc : 0;
762:
763: if (newfrees) {
764:
1.1.1.5 root 765: num_reg_requests++;
766:
1.1 root 767: newfrees[NEWREGIONS-1].next = 0;
768:
769: newfrees[NEWREGIONS-1].links = 0;
770:
771: for (i = 0; i < NEWREGIONS-1; i++) {
772:
773: newfrees[i].next = &newfrees[i+1];
774:
775: newfrees[i].links = 0;
776:
777: }
778:
779: rfreelist = newfrees;
780:
781: } else {
782:
1.1.1.2 root 783: DEBUG(("couldn't get new region descriptors!"));
1.1 root 784:
785: }
786:
787: }
788:
789:
790:
791: return m;
792:
793: }
794:
795:
796:
797: /*
798:
799: * dispose_region destroys a memory region descriptor
800:
801: */
802:
803:
804:
805: void
806:
807: dispose_region(m)
808:
809: MEMREGION *m;
810:
811: {
812:
813: m->next = rfreelist;
814:
815: rfreelist = m;
816:
817: }
818:
819:
820:
1.1.1.6 ! root 821: #if 0
! 822:
! 823: /* notused: see dosmem.c */
! 824:
1.1 root 825: /*
826:
1.1.1.3 root 827: * change_prot_status: change the status of a region to 'newmode'. We're
828:
829: * given its starting address, not its region structure pointer, so we have
830:
831: * to find the region pointer; since this is illegal if proc doesn't own
832:
833: * the region, we know we'll find the region struct pointer in proc->mem.
834:
835: *
836:
837: * If the proc doesn't own it, you get EACCDN. There are no other errors.
838:
839: * God help you if newmode isn't legal!
840:
841: */
842:
843:
844:
845: long
846:
847: change_prot_status(proc,start,newmode)
848:
849: PROC *proc;
850:
851: long start;
852:
853: int newmode;
854:
855: {
856:
857: MEMREGION **mr;
858:
859: int i;
860:
861:
862:
863: /* return EACCDN if you don't own the region in question */
864:
865: if (!proc->mem) return EACCDN;
866:
867:
868:
869: for (mr = proc->mem, i = 0; i < proc->num_reg; i++, mr++) {
870:
871: if ((*mr)->loc == start) goto found;
872:
873: }
874:
875: return EACCDN;
876:
877:
878:
879: found:
880:
881: mark_region(*mr,newmode);
882:
883: return E_OK;
884:
885: }
886:
1.1.1.6 ! root 887: #endif
! 888:
1.1.1.3 root 889:
890:
891: /*
892:
1.1 root 893: * virtaddr
894:
895: * attach_region(proc, reg): attach the region to the given process:
896:
897: * returns the address at which it was attached, or NULL if the process
898:
899: * cannot attach more regions. The region link count is incremented if
900:
901: * the attachment is successful.
902:
903: */
904:
905:
906:
907: virtaddr
908:
909: attach_region(proc, reg)
910:
911: PROC *proc;
912:
913: MEMREGION *reg;
914:
915: {
916:
917: int i;
918:
919: MEMREGION **newmem;
920:
921: virtaddr *newaddr;
922:
923:
924:
1.1.1.3 root 925: TRACELOW(("attach_region %lx len %lx to pid %d",
926:
927: reg->loc, reg->len, proc->pid));
928:
929:
930:
1.1 root 931: if (!reg || !reg->loc) {
932:
933: ALERT("attach_region: attaching a null region??");
934:
935: return 0;
936:
937: }
938:
1.1.1.3 root 939:
940:
941: again:
942:
1.1 root 943: for (i = 0; i < proc->num_reg; i++) {
944:
945: if (!proc->mem[i]) {
946:
947: assert(proc->addr[i] == 0);
948:
949: reg->links++;
950:
951: proc->mem[i] = reg;
952:
953: proc->addr[i] = (virtaddr) reg->loc;
954:
1.1.1.5 root 955: mark_proc_region(proc,reg,PROT_P);
1.1.1.3 root 956:
1.1 root 957: return proc->addr[i];
958:
959: }
960:
961: }
962:
963:
964:
965: /* Hmmm, OK, we have to expand the process' memory table */
966:
1.1.1.3 root 967: TRACELOW(("Expanding process memory table"));
1.1 root 968:
969: i = proc->num_reg + NUM_REGIONS;
970:
971:
972:
973: newmem = kmalloc(i * SIZEOF(MEMREGION *));
974:
975: newaddr = kmalloc(i * SIZEOF(virtaddr));
976:
977:
978:
979: if (newmem && newaddr) {
980:
1.1.1.3 root 981: /*
982:
983: * We have to use temps while allocating and freeing mem
984:
985: * and addr so the memory protection code won't walk this
986:
987: * process' memory list in the middle.
988:
989: */
990:
991: void *pmem, *paddr;
992:
993:
994:
1.1 root 995: /* copy over the old address mapping */
996:
997: for (i = 0; i < proc->num_reg; i++) {
998:
999: newmem[i] = proc->mem[i];
1000:
1001: newaddr[i] = proc->addr[i];
1002:
1003: if (newmem[i] == 0)
1004:
1005: assert(newaddr[i] == 0);
1006:
1007: }
1008:
1009: /* initialize the rest of the tables */
1010:
1011: for(; i < proc->num_reg + NUM_REGIONS; i++) {
1012:
1013: newmem[i] = 0;
1014:
1015: newaddr[i] = 0;
1016:
1017: }
1018:
1.1.1.3 root 1019: /* free the old tables (carefully! for memory protection) */
1020:
1021: pmem = proc->mem;
1.1 root 1022:
1.1.1.3 root 1023: paddr = proc->addr;
1024:
1025: proc->mem = NULL;
1026:
1027: proc->addr = NULL;
1028:
1029: kfree(pmem); kfree(paddr);
1.1 root 1030:
1031: proc->mem = newmem;
1032:
1033: proc->addr = newaddr;
1034:
1035: proc->num_reg += NUM_REGIONS;
1036:
1.1.1.3 root 1037: /* this time we will succeed */
1.1 root 1038:
1.1.1.3 root 1039: goto again;
1.1 root 1040:
1.1.1.3 root 1041: } else {
1.1 root 1042:
1.1.1.3 root 1043: if (newmem) kfree(newmem);
1.1 root 1044:
1.1.1.3 root 1045: if (newaddr) kfree(newaddr);
1.1 root 1046:
1.1.1.3 root 1047: DEBUG(("attach_region: failed"));
1.1 root 1048:
1.1.1.3 root 1049: return 0;
1.1 root 1050:
1.1.1.3 root 1051: }
1.1 root 1052:
1053: }
1054:
1055:
1056:
1057: /*
1058:
1059: * detach_region(proc, reg): remove region from the procedure's address
1060:
1061: * space. If no more processes reference the region, return it to the
1062:
1063: * system. Note that we search backwards, so that the most recent
1064:
1065: * attachment of memory gets detached!
1066:
1067: */
1068:
1069:
1070:
1071: void
1072:
1073: detach_region(proc, reg)
1074:
1075: PROC *proc;
1076:
1077: MEMREGION *reg;
1078:
1079: {
1080:
1081: int i;
1082:
1083:
1084:
1085: if (!reg) return;
1086:
1.1.1.3 root 1087:
1088:
1089: TRACELOW(("detach_region %lx len %lx from pid %d",
1090:
1091: reg->loc, reg->len, proc->pid));
1092:
1093:
1094:
1.1 root 1095: for (i = proc->num_reg - 1; i >= 0; i--) {
1096:
1097: if (proc->mem[i] == reg) {
1098:
1099: reg->links--;
1100:
1101: proc->mem[i] = 0; proc->addr[i] = 0;
1102:
1103: if (reg->links == 0) {
1104:
1105: free_region(reg);
1106:
1107: }
1108:
1.1.1.3 root 1109: else {
1110:
1111: /* cause curproc's table to be updated */
1112:
1.1.1.5 root 1113: mark_proc_region(proc,reg,PROT_I);
1.1.1.3 root 1114:
1115: }
1116:
1.1 root 1117: return;
1118:
1119: }
1120:
1121: }
1122:
1.1.1.2 root 1123: DEBUG(("detach_region: region not attached"));
1.1 root 1124:
1125: }
1126:
1127:
1128:
1129: /*
1130:
1.1.1.3 root 1131: * get_region(MMAP map, ulong size, int mode) -- allocate a new region of the
1.1 root 1132:
1133: * given size in the given memory map. if no region big enough is available,
1134:
1135: * return NULL, otherwise return a pointer to the region.
1136:
1.1.1.3 root 1137: * "mode" tells us about memory protection modes
1138:
1139: *
1140:
1.1 root 1141: * the "links" field in the region is set to 1
1142:
1143: *
1144:
1145: * BEWARE: new_region may call get_region (indirectly), so we have to be
1146:
1147: * _very_ careful with re-entrancy in this function
1148:
1149: */
1150:
1151:
1152:
1153: MEMREGION *
1154:
1.1.1.3 root 1155: get_region(map, size, mode)
1.1 root 1156:
1157: MMAP map;
1158:
1159: ulong size;
1160:
1.1.1.3 root 1161: int mode;
1162:
1.1 root 1163: {
1164:
1.1.1.6 ! root 1165: MEMREGION *m, *n, *nlast, *nfirstp, *s;
1.1 root 1166:
1167:
1168:
1.1.1.3 root 1169: TRACELOW(("get_region(%s,%lx,%x)",
1170:
1171: (map == ker ? "ker" : (map == core ? "core" : "alt")),
1172:
1173: size, mode));
1174:
1175:
1176:
1.1 root 1177: /* precautionary measures */
1178:
1179: if (size == 0) {
1180:
1.1.1.2 root 1181: DEBUG(("request for 0 bytes??"));
1.1 root 1182:
1183: size = 1;
1184:
1185: }
1186:
1187:
1188:
1189: size = ROUND(size);
1190:
1191:
1192:
1193: sanity_check(map);
1194:
1195: /* exact matches are likely to be rare, so we pre-allocate a new
1196:
1197: * region here; this helps us to avoid re-entrancy problems
1198:
1199: * when new_region calls get_region
1200:
1201: */
1202:
1203: m = new_region();
1204:
1205:
1206:
1.1.1.6 ! root 1207: /* We come back and try again if we found and freed any unattached shared
! 1208:
! 1209: * text regions.
! 1210:
! 1211: */
! 1212:
! 1213: nfirstp = NULL;
! 1214:
! 1215: #if 0
! 1216:
! 1217: retry:
! 1218:
! 1219: #endif
! 1220:
! 1221: n = *map;
! 1222:
! 1223: retry2:
! 1224:
! 1225: s = nlast = NULL;
! 1226:
! 1227:
! 1228:
1.1 root 1229: while (n) {
1230:
1231: if (ISFREE(n)) {
1232:
1233: if (n->len == size) {
1234:
1235: if (m) dispose_region(m);
1236:
1237: n->links++;
1238:
1.1.1.3 root 1239: goto win;
1.1 root 1240:
1241: }
1242:
1243: else if (n->len > size) {
1244:
1245: /* split a new region, 'm', which will contain the free bytes after n */
1246:
1247: if (m) {
1248:
1249: m->next = n->next;
1250:
1251: n->next = m;
1252:
1253: m->mflags = n->mflags & M_MAP;
1254:
1255: m->loc = n->loc + size;
1256:
1257: m->len = n->len - size;
1258:
1259: n->len = size;
1260:
1261: n->links++;
1262:
1.1.1.3 root 1263: goto win;
1.1 root 1264:
1265: } else {
1266:
1.1.1.2 root 1267: DEBUG(("get_region: no regions left"));
1.1 root 1268:
1269: return 0;
1270:
1271: }
1272:
1273: }
1274:
1.1.1.6 ! root 1275: nlast = n;
! 1276:
! 1277: /* If this is an unattached shared text region, leave it as a last resort */
! 1278:
! 1279: } else if (n->links == 0xffff && (n->mflags & M_SHTEXT)) {
! 1280:
! 1281: if (!s) {
! 1282:
! 1283: s = n;
! 1284:
! 1285: nfirstp = nlast;
! 1286:
! 1287: }
! 1288:
1.1 root 1289: }
1290:
1291: n = n->next;
1292:
1293: }
1294:
1295:
1296:
1.1.1.6 ! root 1297: /* Looks like we're out of free memory. Try freeing an unattached shared text
! 1298:
! 1299: * region, and then try again to fill this request.
! 1300:
! 1301: */
! 1302:
! 1303: #if 1
! 1304:
! 1305: if (s && s->len < size) {
! 1306:
! 1307: long lastsize = 0, end = 0;
! 1308:
! 1309:
! 1310:
! 1311: n = nlast = nfirstp;
! 1312:
! 1313: if (!n || n->next != s)
! 1314:
! 1315: n = s;
! 1316:
! 1317: for (; n; n = n->next) {
! 1318:
! 1319: if (ISFREE(n)) {
! 1320:
! 1321: if (end == n->loc) {
! 1322:
! 1323: lastsize += n->len;
! 1324:
! 1325: } else {
! 1326:
! 1327: s = NULL;
! 1328:
! 1329: nfirstp = nlast;
! 1330:
! 1331: lastsize = n->len;
! 1332:
! 1333: }
! 1334:
! 1335: nlast = n;
! 1336:
! 1337: end = n->loc + n->len;
! 1338:
! 1339: if (lastsize >= size) {
! 1340:
! 1341: break;
! 1342:
! 1343: }
! 1344:
! 1345: } else if (n->links == 0xffff && (n->mflags & M_SHTEXT)) {
! 1346:
! 1347: if (end == n->loc) {
! 1348:
! 1349: if (!s)
! 1350:
! 1351: s = n;
! 1352:
! 1353: lastsize += n->len;
! 1354:
! 1355: } else {
! 1356:
! 1357: s = n;
! 1358:
! 1359: nfirstp = nlast;
! 1360:
! 1361: lastsize = n->len;
! 1362:
! 1363: }
! 1364:
! 1365: end = n->loc + n->len;
! 1366:
! 1367: if (lastsize >= size) {
! 1368:
! 1369: break;
! 1370:
! 1371: }
! 1372:
! 1373: }
! 1374:
! 1375: }
! 1376:
! 1377: if (!n)
! 1378:
! 1379: s = NULL;
! 1380:
! 1381: }
! 1382:
! 1383: if (s) {
! 1384:
! 1385: s->links = 0;
! 1386:
! 1387: free_region(s);
! 1388:
! 1389: if (NULL == (n = nfirstp))
! 1390:
! 1391: n = *map;
! 1392:
! 1393: goto retry2;
! 1394:
! 1395: }
! 1396:
! 1397: #else
! 1398:
! 1399: if (s) {
! 1400:
! 1401: s->links = 0;
! 1402:
! 1403: free_region(s);
! 1404:
! 1405: goto retry;
! 1406:
! 1407: }
! 1408:
! 1409: #endif
! 1410:
! 1411:
! 1412:
1.1 root 1413: if (m)
1414:
1415: dispose_region(m);
1416:
1.1.1.3 root 1417:
1418:
1419: TRACELOW(("get_region: no memory left in this map"));
1420:
1.1 root 1421: return NULL;
1422:
1.1.1.3 root 1423:
1424:
1425: win:
1426:
1427: mark_region(n, mode & PROT_PROTMODE);
1428:
1429: if (mode & M_KEEP) n->mflags |= M_KEEP;
1430:
1431:
1432:
1433: return n;
1434:
1.1 root 1435: }
1436:
1437:
1438:
1439: /*
1440:
1441: * free_region(MEMREGION *reg): free the indicated region. The map
1442:
1443: * in which the region is contained is given by reg->mflags.
1444:
1445: * the caller is responsible for making sure that the region
1446:
1447: * really should be freed, i.e. that reg->links == 0.
1448:
1.1.1.2 root 1449: *
1450:
1451: * special things to do:
1452:
1453: * if the region is a shared text region, we must close the
1454:
1455: * associated file descriptor
1456:
1.1 root 1457: */
1458:
1459:
1460:
1461: void
1462:
1463: free_region(reg)
1464:
1465: MEMREGION *reg;
1466:
1467: {
1468:
1469: MMAP map;
1470:
1471: MEMREGION *m;
1472:
1.1.1.2 root 1473: SHTEXT *s, **old;
1474:
1.1 root 1475:
1476:
1477: if (!reg) return;
1478:
1479:
1480:
1481: assert(ISFREE(reg));
1482:
1483:
1484:
1.1.1.2 root 1485: if (reg->mflags & M_SHTEXT) {
1486:
1487: TRACE(("freeing shared text region"));
1488:
1489: old = &text_reg;
1490:
1491: for(;;) {
1492:
1493: s = *old;
1494:
1495: if (!s) break;
1496:
1497: if (s->text == reg) {
1498:
1.1.1.3 root 1499: if (s->f)
1500:
1501: do_close(s->f);
1.1.1.2 root 1502:
1503: *old = s->next;
1504:
1505: kfree(s);
1506:
1507: break;
1508:
1509: }
1510:
1511: old = &s->next;
1512:
1513: }
1514:
1515: if (!s) {
1516:
1517: DEBUG(("No shared text entry for M_SHTEXT region??"));
1518:
1519: }
1520:
1521: }
1522:
1523:
1524:
1.1 root 1525: if (reg->mflags & M_CORE)
1526:
1527: map = core;
1528:
1529: else if (reg->mflags & M_ALT)
1530:
1531: map = alt;
1532:
1533: else if (reg->mflags & M_KER)
1534:
1535: map = ker;
1536:
1537: else {
1538:
1539: FATAL("free_region: region flags not valid (%x)", reg->mflags);
1540:
1541: }
1542:
1543: reg->mflags &= M_MAP;
1544:
1545:
1546:
1.1.1.3 root 1547: /* unhook any vectors pointing into this region */
1548:
1549: unlink_vectors(reg->loc, reg->loc + reg->len);
1.1 root 1550:
1551:
1.1.1.3 root 1552:
1553: /* BUG(?): should invalidate caches entries - a copyback cache could stuff
1.1.1.2 root 1554:
1555: * things into freed memory.
1556:
1.1.1.3 root 1557: * cinv(reg->loc, reg->len);
1.1.1.2 root 1558:
1559: */
1560:
1.1.1.3 root 1561: m = *map;
1562:
1563: assert(m);
1564:
1565:
1566:
1567: /* MEMPROT: invalidate */
1568:
1569: if (map == core || map == alt)
1570:
1571: mark_region(reg,PROT_I);
1572:
1573:
1574:
1.1 root 1575: if (m == reg) goto merge_after;
1576:
1577:
1578:
1579: /* merge previous region if it's free and contiguous with 'reg' */
1580:
1581:
1582:
1583: /* first, we find the region */
1584:
1585: while (m && m->next != reg)
1586:
1587: m = m->next;
1588:
1589:
1590:
1.1.1.2 root 1591: if (m == NULL) {
1592:
1593: FATAL("couldn't find region %lx: loc: %lx len: %ld",
1594:
1595: reg, reg->loc, reg->len);
1596:
1597: }
1.1 root 1598:
1599:
1600:
1601: if (ISFREE(m) && (m->loc + m->len == reg->loc)) {
1602:
1603: m->len += reg->len;
1604:
1605: assert(m->next == reg);
1606:
1607: m->next = reg->next;
1608:
1609: reg->next = 0;
1610:
1611: dispose_region(reg);
1612:
1613: reg = m;
1614:
1615: }
1616:
1617:
1618:
1619: /* merge next region if it's free and contiguous with 'reg' */
1620:
1621: merge_after:
1622:
1623: m = reg->next;
1624:
1625: if (m && ISFREE(m) && reg->loc + reg->len == m->loc) {
1626:
1627: reg->len += m->len;
1628:
1629: reg->next = m->next;
1630:
1631: m->next = 0;
1632:
1633: dispose_region(m);
1634:
1635: }
1636:
1637:
1638:
1639: sanity_check(map);
1640:
1641: }
1642:
1643:
1644:
1645: /*
1646:
1647: * shrink_region(MEMREGION *reg, ulong newsize):
1648:
1649: * shrink region 'reg', so that it is now 'newsize' bytes long.
1650:
1651: * if 'newsize' is bigger than the region's current size, return EGSBF;
1652:
1653: * otherwise return 0.
1654:
1655: */
1656:
1657:
1658:
1659: long
1660:
1661: shrink_region(reg, newsize)
1662:
1663: MEMREGION *reg;
1664:
1665: ulong newsize;
1666:
1667: {
1668:
1669: MEMREGION *n;
1670:
1671: ulong diff;
1672:
1673:
1674:
1675:
1676:
1677: newsize = ROUND(newsize);
1678:
1679:
1680:
1681: assert(reg->links > 0);
1682:
1683:
1684:
1.1.1.2 root 1685: if (!(reg->mflags & (M_CORE | M_ALT | M_KER))) {
1.1 root 1686:
1687: FATAL("shrink_region: bad region flags (%x)", reg->mflags);
1688:
1689: }
1690:
1691:
1692:
1693: /* shrinking to 0 is the same as freeing */
1694:
1695: if (newsize == 0) {
1696:
1697: detach_region(curproc, reg);
1698:
1699: return 0;
1700:
1701: }
1702:
1703:
1704:
1705: /* if new size is the same as old size, don't do anything */
1706:
1707: if (newsize == reg->len) {
1708:
1709: return 0; /* nothing to do */
1710:
1711: }
1712:
1713:
1714:
1715: if (newsize > reg->len) {
1716:
1.1.1.2 root 1717: DEBUG(("shrink_region: request to make region bigger"));
1.1 root 1718:
1719: return EGSBF; /* growth failure */
1720:
1721: }
1722:
1723:
1724:
1725: /* OK, we're going to free (reg->len - newsize) bytes at the end of
1726:
1727: this block. If the block after us is already free, simply add the
1728:
1729: space to that block.
1730:
1731: */
1732:
1733: n = reg->next;
1734:
1735: diff = reg->len - newsize;
1736:
1737:
1738:
1739: if (n && ISFREE(n) && reg->loc + reg->len == n->loc) {
1740:
1741: reg->len = newsize;
1742:
1743: n->loc -= diff;
1744:
1745: n->len += diff;
1746:
1.1.1.3 root 1747: /* MEMPROT: invalidate the second half */
1748:
1749: /* (part of it is already invalid; that's OK) */
1750:
1751: mark_region(n,PROT_I);
1752:
1753:
1754:
1.1 root 1755: return 0;
1756:
1757: }
1758:
1759: else {
1760:
1761: n = new_region();
1762:
1763: if (!n) {
1764:
1.1.1.2 root 1765: DEBUG(("shrink_region: new_region failed"));
1.1 root 1766:
1767: return EINTRN;
1768:
1769: }
1770:
1771: reg->len = newsize;
1772:
1773: n->loc = reg->loc + newsize;
1774:
1775: n->len = diff;
1776:
1777: n->mflags = reg->mflags & M_MAP;
1778:
1779: n->next = reg->next;
1780:
1781: reg->next = n;
1782:
1.1.1.3 root 1783: /* MEMPROT: invalidate the new, free region */
1784:
1785: mark_region(n,PROT_I);
1786:
1.1 root 1787: }
1788:
1789: return 0;
1790:
1791: }
1792:
1793:
1794:
1795: /*
1796:
1.1.1.6 ! root 1797: * max_rsize(map, deeded): return the length of the biggest free region
1.1 root 1798:
1799: * in the given memory map, or 0 if no regions remain.
1800:
1.1.1.6 ! root 1801: * needed is minimun amount needed, if != 0 try to keep unattached
! 1802:
! 1803: * shared text regions, else count them all as free.
! 1804:
1.1 root 1805: */
1806:
1807:
1808:
1809: long
1810:
1.1.1.6 ! root 1811: max_rsize(map, needed)
1.1 root 1812:
1813: MMAP map;
1814:
1.1.1.6 ! root 1815: long needed;
! 1816:
1.1 root 1817: {
1818:
1.1.1.2 root 1819: MEMREGION *m;
1.1 root 1820:
1.1.1.6 ! root 1821: long size = 0, lastsize = 0, end = 0;
! 1822:
! 1823:
! 1824:
! 1825: if (needed) {
! 1826:
! 1827: for (m = *map; m; m = m->next) {
! 1828:
! 1829: if (ISFREE(m) ||
! 1830:
! 1831: (m->links == 0xfffe && !(m->mflags & M_SHTEXT))) {
! 1832:
! 1833: if (end == m->loc) {
! 1834:
! 1835: lastsize += m->len;
! 1836:
! 1837: } else {
! 1838:
! 1839: lastsize = m->len;
! 1840:
! 1841: }
! 1842:
! 1843: end = m->loc + m->len;
! 1844:
! 1845: if (lastsize > size) {
! 1846:
! 1847: size = lastsize;
! 1848:
! 1849: }
! 1850:
! 1851: }
! 1852:
! 1853: }
! 1854:
! 1855: if (size >= needed)
! 1856:
! 1857: return size;
1.1 root 1858:
1859:
1860:
1.1.1.6 ! root 1861: lastsize = end = 0;
! 1862:
! 1863: }
! 1864:
1.1 root 1865: for (m = *map; m; m = m->next) {
1866:
1.1.1.6 ! root 1867: if (ISFREE(m) || m->links == 0xfffe ||
! 1868:
! 1869: (m->links == 0xffff && (m->mflags & M_SHTEXT))) {
1.1 root 1870:
1.1.1.6 ! root 1871: if (end == m->loc) {
1.1 root 1872:
1.1.1.6 ! root 1873: lastsize += m->len;
! 1874:
! 1875: } else {
! 1876:
! 1877: lastsize = m->len;
! 1878:
! 1879: }
! 1880:
! 1881: end = m->loc + m->len;
! 1882:
! 1883: if (lastsize > size) {
! 1884:
! 1885: if (needed && lastsize >= needed)
! 1886:
! 1887: return lastsize;
! 1888:
! 1889: size = lastsize;
1.1 root 1890:
1891: }
1892:
1893: }
1894:
1895: }
1896:
1897: return size;
1898:
1899: }
1900:
1901:
1902:
1903: /*
1904:
1905: * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
1906:
1907: * the given memory map; if flag == 0, return only the number of free
1908:
1909: * bytes
1910:
1911: */
1912:
1913:
1914:
1915: long
1916:
1917: tot_rsize(map, flag)
1918:
1919: MMAP map;
1920:
1921: int flag;
1922:
1923: {
1924:
1925: MEMREGION *m;
1926:
1927: long size = 0;
1928:
1929:
1930:
1931: for (m = *map; m; m = m->next) {
1932:
1.1.1.6 ! root 1933: if (flag || ISFREE(m) ||
! 1934:
! 1935: (m->links == 0xffff && (m->mflags & M_SHTEXT))) {
1.1 root 1936:
1937: size += m->len;
1938:
1939: }
1940:
1941: }
1942:
1943: return size;
1944:
1945: }
1946:
1947:
1948:
1949: /*
1950:
1.1.1.3 root 1951: * alloc_region(MMAP map, ulong size, int mode): allocate a new region and
1.1 root 1952:
1.1.1.3 root 1953: * attach it to the current process; returns the address at which the region
1.1 root 1954:
1.1.1.3 root 1955: * was attached, or NULL. The mode argument is the memory protection mode to
1.1 root 1956:
1.1.1.3 root 1957: * give to get_region, and in turn to mark_region.
1.1 root 1958:
1959: */
1960:
1961:
1962:
1963: virtaddr
1964:
1.1.1.3 root 1965: alloc_region(map, size, mode)
1.1 root 1966:
1967: MMAP map;
1968:
1969: ulong size;
1970:
1.1.1.3 root 1971: int mode;
1972:
1.1 root 1973: {
1974:
1975: MEMREGION *m;
1976:
1977: PROC *proc = curproc;
1978:
1979: virtaddr v;
1980:
1981:
1982:
1.1.1.3 root 1983: TRACELOW(("alloc_region(map,size: %lx,mode: %x)",size,mode));
1984:
1985: if (!size) {
1986:
1987: DEBUG(("alloc_region of zero bytes?!"));
1988:
1989: return 0;
1990:
1991: }
1992:
1993:
1994:
1995: m = get_region(map, size, mode);
1.1 root 1996:
1997: if (!m) {
1998:
1.1.1.3 root 1999: TRACELOW(("alloc_region: get_region failed"));
2000:
1.1 root 2001: return 0;
2002:
2003: }
2004:
2005:
2006:
1.1.1.2 root 2007: /* sanity check: even addresses only, please */
2008:
2009: assert((m->loc & MASKBITS) == 0);
2010:
2011:
2012:
1.1 root 2013: v = attach_region(proc, m);
2014:
2015: /* NOTE: get_region returns a region with link count 1; since attach_region
2016:
2017: * increments the link count, we restore it after calling attach_region
2018:
2019: */
2020:
2021: m->links = 1;
2022:
2023: if (!v) {
2024:
2025: m->links = 0;
2026:
2027: free_region(m);
2028:
1.1.1.3 root 2029: TRACE(("alloc_region: attach_region failed"));
2030:
1.1 root 2031: return 0;
2032:
2033: }
2034:
2035: return v;
2036:
2037: }
2038:
2039:
2040:
2041: /*
2042:
2043: * routines for creating a copy of an environment, and a new basepage.
2044:
2045: * note that the memory regions created should immediately be attached to
2046:
2047: * a process! Also note that create_env always operates in ST RAM, but
2048:
2049: * create_base might not.
2050:
2051: */
2052:
2053:
2054:
2055: MEMREGION *
2056:
1.1.1.4 root 2057: create_env(env, flags)
1.1 root 2058:
2059: const char *env;
2060:
1.1.1.4 root 2061: ulong flags;
2062:
1.1 root 2063: {
2064:
2065: long size;
2066:
2067: MEMREGION *m;
2068:
2069: virtaddr v;
2070:
2071: const char *old;
2072:
2073: char *new;
2074:
1.1.1.4 root 2075: short protmode;
2076:
1.1.1.3 root 2077:
1.1 root 2078:
2079: if (!env) {
2080:
2081: env = ((BASEPAGE *)curproc->base)->p_env;
2082:
2083: /* duplicate parent's environment */
2084:
2085: }
2086:
2087: size = 2;
2088:
2089: old = env;
2090:
2091: while (*env || *(env+1))
2092:
2093: env++,size++;
2094:
1.1.1.3 root 2095:
2096:
1.1.1.4 root 2097: protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
2098:
2099:
2100:
2101: v = alloc_region(core, size, protmode);
1.1.1.3 root 2102:
2103: /* if core fails, try alt */
2104:
2105: if (!v)
2106:
1.1.1.4 root 2107: v = alloc_region(alt, size, protmode);
1.1.1.3 root 2108:
2109:
1.1 root 2110:
2111: if (!v) {
2112:
1.1.1.2 root 2113: DEBUG(("create_env: alloc_region failed"));
1.1 root 2114:
2115: return (MEMREGION *)0;
2116:
2117: }
2118:
2119: m = addr2mem(v);
2120:
2121:
2122:
2123: /* copy the old environment into the new */
2124:
2125: new = (char *) m->loc;
2126:
1.1.1.3 root 2127: TRACE(("copying environment: from %lx to %lx", old, new));
2128:
1.1 root 2129: while (size > 0) {
2130:
2131: *new++ = *old++;
2132:
2133: --size;
2134:
2135: }
2136:
1.1.1.3 root 2137: TRACE(("finished copying environment"));
2138:
2139:
2140:
1.1 root 2141: return m;
2142:
2143: }
2144:
2145:
2146:
1.1.1.6 ! root 2147: static void terminateme(code)
! 2148:
! 2149: int code;
! 2150:
! 2151: {
! 2152:
! 2153: Pterm (code);
! 2154:
! 2155: }
! 2156:
! 2157:
! 2158:
1.1 root 2159: MEMREGION *
2160:
1.1.1.6 ! root 2161: create_base(cmd, env, flags, prgsize, execproc, s, f, fh, xp)
1.1 root 2162:
2163: const char *cmd;
2164:
2165: MEMREGION *env;
2166:
2167: ulong flags, prgsize;
2168:
1.1.1.6 ! root 2169: PROC *execproc;
1.1 root 2170:
1.1.1.6 ! root 2171: SHTEXT *s;
1.1 root 2172:
1.1.1.6 ! root 2173: FILEPTR *f;
1.1 root 2174:
1.1.1.6 ! root 2175: FILEHEAD *fh;
1.1 root 2176:
1.1.1.6 ! root 2177: XATTR *xp;
1.1.1.3 root 2178:
1.1.1.6 ! root 2179: {
1.1 root 2180:
1.1.1.6 ! root 2181: long len = 0, minalt = 0, coresize, altsize;
1.1 root 2182:
1.1.1.6 ! root 2183: MMAP map;
1.1 root 2184:
1.1.1.6 ! root 2185: MEMREGION *m, *savemem = 0;
1.1 root 2186:
1.1.1.6 ! root 2187: BASEPAGE *b, *bparent = 0;
1.1 root 2188:
1.1.1.6 ! root 2189: PROC *parent = 0;
1.1 root 2190:
1.1.1.6 ! root 2191: short protmode;
1.1 root 2192:
1.1.1.6 ! root 2193: int i, ismax = 1;
1.1 root 2194:
2195:
2196:
1.1.1.6 ! root 2197: /* if we're about to do an exec tell max_rsize which of the exec'ing
1.1 root 2198:
1.1.1.6 ! root 2199: process regions will be freed, but don't free them yet so the process
1.1 root 2200:
1.1.1.6 ! root 2201: can still get an ENOMEM...
1.1 root 2202:
1.1.1.6 ! root 2203: */
1.1 root 2204:
1.1.1.6 ! root 2205: if (execproc) {
1.1 root 2206:
1.1.1.6 ! root 2207: for (i = 0; i < execproc->num_reg; i++) {
1.1 root 2208:
1.1.1.6 ! root 2209: m = execproc->mem[i];
1.1 root 2210:
1.1.1.6 ! root 2211: if (m && m->links == 1)
1.1 root 2212:
1.1.1.6 ! root 2213: m->links = 0xfffe;
1.1 root 2214:
2215: }
2216:
2217:
2218:
1.1.1.6 ! root 2219: /* if parents mem saved because of a blocking fork that can be restored too
1.1 root 2220:
1.1.1.6 ! root 2221: */
1.1 root 2222:
1.1.1.6 ! root 2223: if (NULL != (parent = pid2proc(execproc->ppid)) &&
1.1 root 2224:
1.1.1.6 ! root 2225: parent->wait_q == WAIT_Q &&
1.1 root 2226:
1.1.1.6 ! root 2227: parent->wait_cond == (long)execproc) {
1.1.1.5 root 2228:
1.1.1.6 ! root 2229: for (i = 0; i < parent->num_reg; i++) {
1.1.1.5 root 2230:
1.1.1.6 ! root 2231: m = parent->mem[i];
1.1.1.5 root 2232:
1.1.1.6 ! root 2233: if (m && (m->mflags & M_FSAVED)) {
1.1.1.5 root 2234:
1.1.1.6 ! root 2235: m->links = 0xfffe;
1.1.1.5 root 2236:
1.1.1.6 ! root 2237: savemem = m;
1.1.1.3 root 2238:
1.1.1.6 ! root 2239: break;
1.1.1.3 root 2240:
1.1.1.6 ! root 2241: }
1.1.1.3 root 2242:
1.1.1.6 ! root 2243: }
! 2244:
! 2245: }
1.1.1.3 root 2246:
2247: }
2248:
1.1 root 2249:
2250:
1.1.1.6 ! root 2251: /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
1.1 root 2252:
1.1.1.6 ! root 2253: RAM if enough is available. "enough" is: if more alt ram than ST ram,
1.1 root 2254:
1.1.1.6 ! root 2255: load there; otherwise, if more than (minalt+1)*128K alt ram available
1.1 root 2256:
1.1.1.6 ! root 2257: for heap space, load in alt ram ("minalt" is the high byte of flags)
1.1 root 2258:
1.1.1.6 ! root 2259: */
1.1.1.3 root 2260:
1.1.1.6 ! root 2261: again2:
1.1.1.3 root 2262:
1.1.1.6 ! root 2263: if (flags & (F_ALTLOAD|F_SHTEXT)) {
1.1.1.3 root 2264:
1.1.1.6 ! root 2265: minalt = (flags & F_MINALT) >> 28L;
1.1.1.3 root 2266:
1.1.1.6 ! root 2267: minalt = len = (minalt+1)*128*1024L + prgsize + 256;
1.1.1.3 root 2268:
1.1.1.6 ! root 2269: if ((flags & F_MINALT) == F_MINALT)
1.1 root 2270:
1.1.1.6 ! root 2271: len = 0;
1.1 root 2272:
1.1.1.6 ! root 2273: else
1.1 root 2274:
1.1.1.6 ! root 2275: ismax = 0;
1.1 root 2276:
2277: }
2278:
1.1.1.6 ! root 2279: again1:
1.1 root 2280:
1.1.1.6 ! root 2281: if (flags & F_ALTLOAD) {
1.1 root 2282:
1.1.1.6 ! root 2283: coresize = max_rsize(core, len);
1.1 root 2284:
1.1.1.6 ! root 2285: altsize = max_rsize(alt, len);
1.1 root 2286:
1.1.1.6 ! root 2287: if (altsize >= coresize) {
1.1 root 2288:
1.1.1.6 ! root 2289: map = alt;
1.1 root 2290:
1.1.1.6 ! root 2291: len = altsize;
1.1 root 2292:
1.1.1.6 ! root 2293: } else {
1.1 root 2294:
1.1.1.6 ! root 2295: if (altsize >= minalt) {
1.1 root 2296:
1.1.1.6 ! root 2297: map = alt;
1.1 root 2298:
1.1.1.6 ! root 2299: len = altsize;
1.1 root 2300:
1.1.1.6 ! root 2301: } else {
1.1 root 2302:
1.1.1.6 ! root 2303: map = core;
1.1 root 2304:
1.1.1.6 ! root 2305: len = coresize;
1.1 root 2306:
1.1.1.6 ! root 2307: }
1.1 root 2308:
1.1.1.6 ! root 2309: }
1.1 root 2310:
1.1.1.6 ! root 2311: }
1.1 root 2312:
1.1.1.6 ! root 2313: else
1.1 root 2314:
1.1.1.6 ! root 2315: len = max_rsize((map = core), len);
1.1 root 2316:
2317:
2318:
1.1.1.6 ! root 2319: if (savemem)
1.1.1.3 root 2320:
1.1.1.6 ! root 2321: savemem->links = 1;
1.1 root 2322:
2323:
2324:
1.1.1.6 ! root 2325: if (curproc->maxmem && len > curproc->maxmem) {
1.1 root 2326:
1.1.1.6 ! root 2327: if (ismax >= 0)
1.1 root 2328:
1.1.1.6 ! root 2329: len = curproc->maxmem;
1.1 root 2330:
1.1.1.6 ! root 2331: else if (len > curproc->maxmem+fh->ftext)
1.1 root 2332:
1.1.1.6 ! root 2333: len = curproc->maxmem+fh->ftext;
1.1 root 2334:
1.1.1.6 ! root 2335: }
1.1 root 2336:
2337:
2338:
1.1.1.6 ! root 2339: /* make sure that a little bit of memory is left over */
1.1 root 2340:
1.1.1.6 ! root 2341: if (len > 2*KEEP_MEM) {
1.1 root 2342:
1.1.1.6 ! root 2343: len -= KEEP_MEM;
1.1.1.2 root 2344:
1.1.1.6 ! root 2345: }
1.1.1.2 root 2346:
1.1.1.6 ! root 2347:
! 2348:
! 2349: if (s && !s->text &&
! 2350:
! 2351: (!(flags & F_ALTLOAD) || map == alt || altsize < fh->ftext)) {
! 2352:
! 2353: if (len > fh->ftext + KERNEL_MEM)
! 2354:
! 2355: len -= fh->ftext + KERNEL_MEM;
! 2356:
! 2357: else
! 2358:
! 2359: len = 0;
! 2360:
! 2361: #if 1
! 2362:
! 2363: if (prgsize && len < prgsize + 0x400) {
! 2364:
! 2365: if (!ismax) {
! 2366:
! 2367: len = minalt + fh->ftext;
! 2368:
! 2369: ismax = -1;
! 2370:
! 2371: goto again1;
! 2372:
! 2373: }
! 2374:
! 2375: if ((s->text = addr2mem(alloc_region(map, fh->ftext, PROT_P)))) {
! 2376:
! 2377: goto again2;
! 2378:
! 2379: }
! 2380:
! 2381: }
! 2382:
! 2383: #endif
! 2384:
! 2385: }
! 2386:
! 2387:
! 2388:
! 2389: if (prgsize && len < prgsize + 0x400) {
! 2390:
! 2391: /* can't possibly load this file in its eligible regions */
! 2392:
! 2393: DEBUG(("create_base: max_rsize smaller than prgsize"));
! 2394:
! 2395:
! 2396:
! 2397: if (execproc) {
! 2398:
! 2399: /* error, undo the above */
! 2400:
! 2401: for (i = 0; i < execproc->num_reg; i++) {
! 2402:
! 2403: m = execproc->mem[i];
! 2404:
! 2405: if (m && m->links == 0xfffe)
! 2406:
! 2407: m->links = 1;
! 2408:
! 2409: }
! 2410:
! 2411: }
! 2412:
! 2413: if (s && !s->text) {
! 2414:
! 2415: kfree (s);
! 2416:
! 2417: }
! 2418:
! 2419: mint_errno = ENSMEM;
! 2420:
! 2421: return 0;
! 2422:
! 2423: }
! 2424:
! 2425: if (execproc) {
! 2426:
! 2427: /* free exec'ing process memory... if the exec returns after this make it
! 2428:
! 2429: _exit (SIGKILL << 8);
! 2430:
! 2431: */
! 2432:
! 2433: *((short *) (execproc->stack + ISTKSIZE + sizeof (void (*)()))) =
! 2434:
! 2435: (SIGKILL << 8);
! 2436:
! 2437: execproc->ctxt[SYSCALL].term_vec = (long)rts;
! 2438:
! 2439: execproc->ctxt[SYSCALL].pc = (long)terminateme;
! 2440:
! 2441: execproc->ctxt[SYSCALL].sr |= 0x2000;
! 2442:
! 2443: execproc->ctxt[SYSCALL].ssp = (long)(execproc->stack + ISTKSIZE);
! 2444:
! 2445:
! 2446:
! 2447: /* save basepage p_parent */
! 2448:
! 2449: bparent = execproc->base->p_parent;
! 2450:
! 2451: if (parent) {
! 2452:
! 2453: if (savemem)
! 2454:
! 2455: fork_restore(parent, savemem);
! 2456:
! 2457: /* blocking forks keep the same basepage for parent and child,
! 2458:
! 2459: so this p_parent actually was our grandparents... */
! 2460:
! 2461: bparent = parent->base;
! 2462:
! 2463: }
! 2464:
! 2465: for (i = 0; i < execproc->num_reg; i++) {
! 2466:
! 2467: m = execproc->mem[i];
! 2468:
! 2469: if (m && m->links == 0xfffe) {
! 2470:
! 2471: execproc->mem[i] = 0;
! 2472:
! 2473: execproc->addr[i] = 0;
! 2474:
! 2475: if (m->mflags & M_SHTEXT_T) {
! 2476:
! 2477: TRACE (("create_base: keeping sticky text segment (%lx, len %lx)",
! 2478:
! 2479: m->loc, m->len));
! 2480:
! 2481: m->links = 0xffff;
! 2482:
! 2483: } else {
! 2484:
! 2485: m->links = 0;
! 2486:
! 2487: free_region(m);
! 2488:
! 2489: }
! 2490:
! 2491: }
! 2492:
! 2493: }
! 2494:
! 2495: }
! 2496:
! 2497: protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
! 2498:
! 2499:
! 2500:
! 2501: m = 0;
! 2502:
! 2503: if (s && !s->f) {
! 2504:
! 2505: if (!s->text) {
! 2506:
! 2507: m = addr2mem(alloc_region(map, len + fh->ftext + KERNEL_MEM, protmode));
! 2508:
! 2509: if (!m ||
! 2510:
! 2511: (((len > minalt &&
! 2512:
! 2513: ((flags & F_MINALT) < F_MINALT) &&
! 2514:
! 2515: max_rsize (map, -1) < fh->ftext) ||
! 2516:
! 2517: 0 == (s->text = addr2mem(alloc_region(map, fh->ftext, PROT_P))) ||
! 2518:
! 2519: (m->next == s->text &&
! 2520:
! 2521: !(detach_region (curproc, s->text), s->text = 0))) &&
! 2522:
! 2523: shrink_region(m, fh->ftext))) {
! 2524:
! 2525: if (m)
! 2526:
! 2527: detach_region(curproc, m);
! 2528:
! 2529: kfree (s);
! 2530:
! 2531: mint_errno = ENSMEM;
! 2532:
! 2533: return 0;
! 2534:
! 2535: }
! 2536:
! 2537: if (!s->text) {
! 2538:
! 2539: s->text = m;
! 2540:
! 2541: if (protmode != PROT_P)
! 2542:
! 2543: mark_region(m, PROT_P);
! 2544:
! 2545: m = 0;
! 2546:
! 2547: }
! 2548:
! 2549: }
! 2550:
! 2551: s = get_text_seg(f, fh, xp, s, 0);
! 2552:
! 2553: if (!s) {
! 2554:
! 2555: if (m)
! 2556:
! 2557: detach_region(curproc, m);
! 2558:
! 2559: DEBUG(("create_base: unable to load shared text segment"));
! 2560:
! 2561: /* mint_errno set in get_text_seg */
! 2562:
! 2563: return 0;
! 2564:
! 2565: }
! 2566:
! 2567: }
! 2568:
! 2569:
! 2570:
! 2571: if (!m) {
! 2572:
! 2573: m = addr2mem(alloc_region(map, len, protmode));
! 2574:
! 2575: }
! 2576:
! 2577: if (!m) {
! 2578:
! 2579: DEBUG(("create_base: alloc_region failed"));
! 2580:
! 2581: mint_errno = ENSMEM;
! 2582:
! 2583: return 0;
! 2584:
! 2585: }
! 2586:
! 2587: b = (BASEPAGE *)(m->loc);
! 2588:
! 2589:
! 2590:
! 2591: zero((char *)b, (long)sizeof(BASEPAGE));
! 2592:
! 2593: b->p_lowtpa = (long)b;
! 2594:
! 2595: b->p_hitpa = m->loc + m->len;
! 2596:
! 2597: b->p_env = (char *)env->loc;
! 2598:
! 2599: b->p_flags = flags;
! 2600:
! 2601:
! 2602:
! 2603: if (execproc) {
! 2604:
! 2605: execproc->base = b;
! 2606:
! 2607: b->p_parent = bparent;
! 2608:
! 2609: }
! 2610:
! 2611:
! 2612:
! 2613: if (cmd)
! 2614:
! 2615: strncpy(b->p_cmdlin, cmd, 126);
! 2616:
! 2617: return m;
! 2618:
! 2619: }
! 2620:
! 2621:
! 2622:
! 2623: /*
! 2624:
! 2625: * load_region(): loads the program with the given file name
! 2626:
! 2627: * into a new region, and returns a pointer to that region. On
! 2628:
! 2629: * an error, returns 0 and leaves the error number in mint_errno.
! 2630:
! 2631: * "env" points to an already set up environment region, as returned
! 2632:
! 2633: * by create_env. On success, "xp" points to the file attributes, which
! 2634:
! 2635: * Pexec has already determined, and "fp" points to the programs
! 2636:
! 2637: * prgflags. "text" is a pointer to a MEMREGION
! 2638:
! 2639: * pointer, which will be set to the region occupied by the shared
! 2640:
! 2641: * text segment of this program (if applicable).
! 2642:
! 2643: */
! 2644:
! 2645:
! 2646:
! 2647: MEMREGION *
! 2648:
! 2649: load_region(filename, env, cmdlin, xp, text, fp, isexec)
! 2650:
! 2651: const char *filename;
! 2652:
! 2653: MEMREGION *env;
! 2654:
! 2655: const char *cmdlin;
! 2656:
! 2657: XATTR *xp; /* attributes for the file just loaded */
! 2658:
! 2659: MEMREGION **text; /* set to point to shared text region,
! 2660:
! 2661: if any */
! 2662:
! 2663: long *fp; /* prgflags for this file */
! 2664:
! 2665: int isexec; /* this is an exec*() (overlay) */
1.1.1.3 root 2666:
1.1 root 2667: {
2668:
2669: FILEPTR *f;
2670:
2671: DEVDRV *dev;
2672:
1.1.1.2 root 2673: MEMREGION *reg, *shtext;
1.1 root 2674:
2675: BASEPAGE *b;
2676:
1.1.1.2 root 2677: long size, start;
1.1 root 2678:
1.1.1.2 root 2679: FILEHEAD fh;
1.1 root 2680:
1.1.1.6 ! root 2681: SHTEXT *s;
! 2682:
1.1 root 2683:
2684:
1.1.1.2 root 2685: /* bug: this should be O_DENYW mode, not O_DENYNONE */
1.1 root 2686:
1.1.1.2 root 2687: /* we must use O_DENYNONE because of the desktop and because of the
1.1 root 2688:
1.1.1.2 root 2689: * TOS file system brain-damage
1.1 root 2690:
1.1.1.2 root 2691: */
1.1 root 2692:
2693: f = do_open(filename, O_DENYNONE | O_EXEC, 0, xp);
2694:
2695: if (!f) {
2696:
2697: return 0; /* mint_errno set by do_open */
2698:
2699: }
2700:
2701:
2702:
1.1.1.2 root 2703: dev = f->dev;
1.1 root 2704:
1.1.1.2 root 2705: size = (*dev->read)(f, (void *)&fh, (long)sizeof(fh));
1.1 root 2706:
1.1.1.2 root 2707: if (fh.fmagic != GEMDOS_MAGIC || size != (long)sizeof(fh)) {
1.1 root 2708:
1.1.1.2 root 2709: DEBUG(("load_region: file not executable"));
1.1 root 2710:
2711: mint_errno = ENOEXEC;
2712:
2713: failed:
2714:
2715: do_close(f);
2716:
2717: return 0;
2718:
2719: }
2720:
2721:
2722:
1.1.1.5 root 2723: if (((fh.flag & F_PROTMODE) >> F_PROTSHIFT) > PROT_MAX_MODE) {
2724:
2725: DEBUG (("load_region: invalid protection mode changed to private"));
2726:
2727: fh.flag = (fh.flag & ~F_PROTMODE) | F_PROT_P;
2728:
2729: }
2730:
1.1.1.3 root 2731: *fp = fh.flag;
2732:
2733:
2734:
1.1.1.2 root 2735: if (fh.flag & F_SHTEXT) {
2736:
2737: TRACE(("loading shared text segment"));
2738:
1.1.1.6 ! root 2739: s = get_text_seg(f, &fh, xp, 0L, isexec);
1.1.1.2 root 2740:
1.1.1.6 ! root 2741: if (!s) {
1.1.1.2 root 2742:
2743: DEBUG(("load_region: unable to get shared text segment"));
2744:
2745: /* mint_errno set in get_text_seg */
2746:
2747: goto failed;
2748:
2749: }
2750:
2751: size = fh.fdata + fh.fbss;
2752:
1.1.1.6 ! root 2753: shtext = s->text;
! 2754:
1.1.1.2 root 2755: } else {
2756:
2757: size = fh.ftext + fh.fdata + fh.fbss;
2758:
2759: shtext = 0;
2760:
1.1.1.6 ! root 2761: s = 0;
! 2762:
1.1.1.2 root 2763: }
2764:
2765:
1.1 root 2766:
1.1.1.6 ! root 2767: env->links++;
! 2768:
! 2769: if (s && !shtext) {
! 2770:
! 2771: reg = create_base(cmdlin, env, fh.flag, size,
! 2772:
! 2773: isexec ? curproc : 0L, s, f, &fh, xp);
! 2774:
! 2775: shtext = s->text;
! 2776:
! 2777: } else {
! 2778:
! 2779: if (shtext)
! 2780:
! 2781: shtext->links++;
! 2782:
! 2783: reg = create_base(cmdlin, env, fh.flag, size,
! 2784:
! 2785: isexec ? curproc : 0L, 0L, 0L, 0L, 0L);
! 2786:
! 2787: if (shtext) {
! 2788:
! 2789: shtext->links--;
! 2790:
! 2791: #if 1
! 2792:
! 2793: /* if create_base failed maybe the (sticky) text segment itself is
! 2794:
! 2795: * fragmenting memory... force it reloaded and have a second try
! 2796:
! 2797: */
! 2798:
! 2799: if (!reg && shtext->links == 1 && isexec) {
! 2800:
! 2801: s->f = 0;
! 2802:
! 2803: f->links--;
! 2804:
! 2805: detach_region(curproc, shtext);
! 2806:
! 2807: s = get_text_seg(f, &fh, xp, 0L, isexec);
! 2808:
! 2809: if (!s) {
! 2810:
! 2811: DEBUG(("load_region: unable to get shared text segment"));
! 2812:
! 2813: goto failed;
! 2814:
! 2815: }
! 2816:
! 2817: reg = create_base(cmdlin, env, fh.flag, size,
! 2818:
! 2819: curproc, s, f, &fh, xp);
! 2820:
! 2821: shtext = s->text;
! 2822:
! 2823: }
! 2824:
! 2825: #endif
! 2826:
! 2827: }
! 2828:
! 2829: }
! 2830:
! 2831: env->links--;
1.1 root 2832:
1.1.1.3 root 2833: if (reg && size+1024L > reg->len) {
1.1 root 2834:
1.1.1.3 root 2835: DEBUG(("load_region: insufficient memory to load"));
1.1 root 2836:
1.1.1.3 root 2837: detach_region(curproc, reg);
1.1 root 2838:
1.1.1.3 root 2839: reg = 0;
1.1 root 2840:
1.1.1.6 ! root 2841: mint_errno = ENSMEM;
! 2842:
1.1 root 2843: }
2844:
2845:
2846:
2847: if (reg == 0) {
2848:
1.1.1.2 root 2849: if (shtext) {
2850:
2851: detach_region(curproc, shtext);
2852:
2853: }
2854:
1.1 root 2855: goto failed;
2856:
2857: }
2858:
2859:
2860:
2861: b = (BASEPAGE *)reg->loc;
2862:
2863: b->p_flags = fh.flag;
2864:
1.1.1.2 root 2865: if (shtext) {
2866:
2867: b->p_tbase = shtext->loc;
1.1 root 2868:
1.1.1.2 root 2869: b->p_tlen = 0;
1.1 root 2870:
1.1.1.2 root 2871: b->p_dbase = b->p_lowtpa + 256;
2872:
2873: } else {
2874:
2875: b->p_tbase = b->p_lowtpa + 256;
2876:
2877: b->p_tlen = fh.ftext;
2878:
2879: b->p_dbase = b->p_tbase + b->p_tlen;
2880:
2881: }
1.1 root 2882:
2883: b->p_dlen = fh.fdata;
2884:
2885: b->p_bbase = b->p_dbase + b->p_dlen;
2886:
1.1.1.2 root 2887: b->p_blen = fh.fbss;
1.1 root 2888:
2889:
2890:
1.1.1.2 root 2891: /* if shared text, then we start loading at the end of the
1.1 root 2892:
1.1.1.2 root 2893: * text region, since that is already set up
2894:
2895: */
2896:
2897: if (shtext) {
2898:
2899: /* skip over text info */
2900:
2901: size = fh.fdata;
2902:
2903: start = fh.ftext;
2904:
2905: } else {
2906:
2907: size = fh.ftext + fh.fdata;
2908:
2909: start = 0;
2910:
2911: }
2912:
2913:
2914:
2915: mint_errno = (int)load_and_reloc(f, &fh, (char *)b+256, start,
2916:
2917: size, b);
2918:
2919:
2920:
2921: if (mint_errno) {
1.1 root 2922:
2923: detach_region(curproc, reg);
2924:
1.1.1.2 root 2925: if (shtext) detach_region(curproc, shtext);
2926:
1.1 root 2927: goto failed;
2928:
2929: }
2930:
2931:
2932:
2933: if (fh.flag & F_FASTLOAD) /* fastload bit */
2934:
2935: size = b->p_blen;
2936:
2937: else
2938:
2939: size = b->p_hitpa - b->p_bbase;
2940:
1.1.1.5 root 2941: if (size > 0) {
2942:
2943: start = b->p_bbase;
2944:
2945: if (start & 1) {
2946:
2947: *(char *)start = 0;
2948:
2949: start++;
2950:
2951: --size;
2952:
2953: }
2954:
2955: zero((char *)start, size);
2956:
2957: }
1.1 root 2958:
2959:
2960:
1.1.1.2 root 2961: do_close(f);
1.1 root 2962:
1.1.1.2 root 2963: *text = shtext;
1.1 root 2964:
1.1.1.2 root 2965: return reg;
1.1 root 2966:
1.1.1.2 root 2967: }
2968:
2969:
2970:
2971: /*
2972:
2973: * load_and_reloc(f, fh, where, start, nbytes): load and relocate from
2974:
2975: * the open GEMDOS executable file f "nbytes" bytes starting at offset
2976:
2977: * "start" (relative to the end of the file header, i.e. from the first
2978:
2979: * byte of the actual program image in the file). "where" is the address
2980:
2981: * in (physical) memory into which the loaded image must be placed; it is
2982:
2983: * assumed that "where" is big enough to hold "nbytes" bytes!
1.1 root 2984:
2985: */
2986:
2987:
2988:
1.1.1.2 root 2989: long
2990:
2991: load_and_reloc(f, fh, where, start, nbytes, base)
2992:
2993: FILEPTR *f;
2994:
2995: FILEHEAD *fh;
2996:
2997: char *where;
2998:
2999: long start;
3000:
3001: long nbytes;
3002:
3003: BASEPAGE *base;
3004:
3005: {
3006:
3007: unsigned char c, *next;
3008:
3009: long r;
3010:
3011: DEVDRV *dev;
3012:
3013: #define LRBUFSIZ 8196
3014:
3015: static unsigned char buffer[LRBUFSIZ];
3016:
3017: long fixup, size, bytes_read;
3018:
3019: long reloc;
3020:
3021:
3022:
3023:
3024:
3025: TRACE(("load_and_reloc: %ld to %ld at %lx", start, nbytes+start, where));
3026:
3027: dev = f->dev;
3028:
3029:
3030:
3031: r = (*dev->lseek)(f, start+sizeof(FILEHEAD), SEEK_SET);
3032:
3033: if (r < 0) return r;
3034:
3035: r = (*dev->read)(f, where, nbytes);
3036:
3037: if (r != nbytes) {
3038:
3039: DEBUG(("load_region: unexpected EOF"));
3040:
3041: return ENOEXEC;
3042:
3043: }
3044:
3045:
3046:
3047: /* now do the relocation */
3048:
3049: /* skip over symbol table, etc. */
3050:
3051: r = (*dev->lseek)(f, sizeof(FILEHEAD) + fh->ftext + fh->fdata +
3052:
3053: fh->fsym, SEEK_SET);
3054:
3055: if (r < 0) return ENOEXEC;
3056:
3057:
3058:
3059: if (fh->reloc != 0 || (*dev->read)(f, (char *)&fixup, 4L) != 4L
3060:
3061: || fixup == 0) {
3062:
3063: return 0; /* no relocation to be performed */
3064:
3065: }
3066:
3067:
3068:
3069: size = LRBUFSIZ;
3070:
3071: bytes_read = 0;
3072:
3073: next = buffer;
3074:
1.1 root 3075:
3076:
1.1.1.2 root 3077: do {
3078:
3079: if (fixup >= nbytes + start) {
3080:
3081: TRACE(("load_region: end of relocation at %ld", fixup));
3082:
3083: break;
3084:
3085: }
3086:
3087: else if (fixup >= start) {
1.1 root 3088:
1.1.1.2 root 3089: reloc = *((long *)(where + fixup - start));
3090:
3091: if (reloc < fh->ftext) {
3092:
3093: reloc += base->p_tbase;
3094:
3095: } else if (reloc < fh->ftext + fh->fdata && base->p_dbase) {
3096:
3097: reloc += base->p_dbase - fh->ftext;
3098:
3099: } else if (reloc < fh->ftext + fh->fdata + fh->fbss && base->p_bbase) {
3100:
3101: reloc += base->p_bbase - (fh->ftext + fh->fdata);
3102:
3103: } else {
3104:
3105: DEBUG(("load_region: bad relocation: %ld", reloc));
3106:
3107: if (base->p_dbase)
3108:
3109: reloc += base->p_dbase - fh->ftext; /* assume data reloc */
3110:
3111: else if (base->p_bbase)
3112:
3113: reloc += base->p_bbase - (fh->ftext + fh->fdata);
3114:
3115: else
3116:
3117: return ENOEXEC;
3118:
3119: }
3120:
3121: *((long *)(where + fixup - start)) = reloc;
3122:
3123: }
1.1 root 3124:
3125: do {
3126:
1.1.1.2 root 3127: if (!bytes_read) {
1.1 root 3128:
1.1.1.2 root 3129: bytes_read =
1.1 root 3130:
1.1.1.2 root 3131: (*dev->read)(f,(char *)buffer,size);
3132:
3133: next = buffer;
1.1 root 3134:
3135: }
3136:
1.1.1.2 root 3137: if (bytes_read < 0) {
1.1 root 3138:
1.1.1.2 root 3139: DEBUG(("load_region: EOF in relocation"));
1.1 root 3140:
1.1.1.2 root 3141: return ENOEXEC;
1.1 root 3142:
1.1.1.2 root 3143: }
1.1 root 3144:
1.1.1.2 root 3145: else if (bytes_read == 0)
1.1 root 3146:
1.1.1.2 root 3147: c = 0;
1.1 root 3148:
1.1.1.2 root 3149: else {
1.1 root 3150:
1.1.1.2 root 3151: c = *next++; bytes_read--;
1.1 root 3152:
1.1.1.2 root 3153: }
1.1 root 3154:
1.1.1.2 root 3155: if (c == 1) fixup += 254;
1.1 root 3156:
1.1.1.2 root 3157: } while (c == 1);
1.1 root 3158:
1.1.1.2 root 3159: fixup += ( (unsigned) c) & 0xff;
1.1 root 3160:
1.1.1.2 root 3161: } while (c);
1.1 root 3162:
3163:
3164:
1.1.1.2 root 3165: return 0;
1.1 root 3166:
1.1.1.2 root 3167: }
3168:
3169:
3170:
3171: /*
3172:
3173: * function to check for existence of a shared text region
3174:
3175: * corresponding to file "f", and if none is found, to create one
3176:
3177: * the memory region being returned is attached to the current
3178:
3179: * process
3180:
3181: */
3182:
3183:
3184:
1.1.1.6 ! root 3185: SHTEXT *
1.1.1.2 root 3186:
1.1.1.6 ! root 3187: get_text_seg(f, fh, xp, s, noalloc)
1.1.1.2 root 3188:
3189: FILEPTR *f;
3190:
3191: FILEHEAD *fh;
3192:
3193: XATTR *xp;
3194:
3195: SHTEXT *s;
1.1 root 3196:
1.1.1.6 ! root 3197: int noalloc;
! 3198:
! 3199: {
! 3200:
1.1.1.2 root 3201: MEMREGION *m;
3202:
3203: long r;
3204:
3205: BASEPAGE b;
3206:
3207:
3208:
1.1.1.6 ! root 3209: if (s) {
! 3210:
! 3211: m = s->text;
! 3212:
! 3213: } else {
! 3214:
! 3215: s = text_reg;
! 3216:
! 3217:
1.1.1.2 root 3218:
1.1.1.6 ! root 3219: while(s) {
1.1.1.2 root 3220:
1.1.1.6 ! root 3221: if (s->f && samefile(&f->fc, &s->f->fc) &&
1.1.1.2 root 3222:
1.1.1.6 ! root 3223: xp->mtime == s->mtime &&
1.1.1.2 root 3224:
1.1.1.6 ! root 3225: xp->mdate == s->mdate)
1.1.1.2 root 3226:
1.1.1.6 ! root 3227: {
1.1.1.2 root 3228:
1.1.1.6 ! root 3229: m = s->text;
1.1.1.2 root 3230:
1.1.1.6 ! root 3231: /* Kludge for unattached shared region */
1.1 root 3232:
1.1.1.6 ! root 3233: if (m->links == 0xffff)
1.1 root 3234:
1.1.1.6 ! root 3235: m->links = 0;
! 3236:
! 3237: if (attach_region(curproc, m)) {
1.1 root 3238:
1.1.1.2 root 3239: TRACE(("re-using shared text region %lx", m));
3240:
1.1.1.6 ! root 3241: return s;
1.1.1.2 root 3242:
1.1.1.6 ! root 3243: }
1.1.1.2 root 3244:
1.1.1.6 ! root 3245: else {
1.1.1.2 root 3246:
1.1.1.6 ! root 3247: mint_errno = ENSMEM;
1.1.1.2 root 3248:
1.1.1.6 ! root 3249: return 0;
! 3250:
! 3251: }
1.1.1.2 root 3252:
3253: }
3254:
1.1.1.6 ! root 3255: s = s->next;
! 3256:
1.1.1.2 root 3257: }
3258:
1.1 root 3259:
3260:
1.1.1.6 ! root 3261: /* hmmm, not found; OK, we'll have to create a new text region */
1.1 root 3262:
3263:
1.1.1.2 root 3264:
1.1.1.6 ! root 3265: s = kmalloc(SIZEOF(SHTEXT));
1.1.1.2 root 3266:
1.1.1.6 ! root 3267: if (!s) {
1.1.1.2 root 3268:
1.1.1.6 ! root 3269: mint_errno = ENSMEM;
1.1.1.2 root 3270:
1.1.1.6 ! root 3271: return 0;
1.1.1.2 root 3272:
1.1.1.6 ! root 3273: }
1.1.1.2 root 3274:
1.1.1.6 ! root 3275: if (noalloc) {
! 3276:
! 3277: s->f = 0;
! 3278:
! 3279: s->text = 0;
! 3280:
! 3281: return s;
! 3282:
! 3283: }
! 3284:
! 3285: m = 0;
1.1.1.2 root 3286:
3287: }
3288:
1.1.1.6 ! root 3289:
! 3290:
! 3291: if (!m) {
1.1.1.2 root 3292:
3293: /* actually, I can't see why loading in TT RAM is ever undesireable,
3294:
3295: * since shared text programs should be very clean (and since only
3296:
3297: * the text segment is going in there). But better safe than sorry.
3298:
3299: */
3300:
1.1.1.6 ! root 3301: if (fh->flag & F_ALTLOAD) {
1.1.1.2 root 3302:
1.1.1.6 ! root 3303: m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
1.1.1.2 root 3304:
1.1.1.6 ! root 3305: }
1.1.1.2 root 3306:
1.1.1.6 ! root 3307: if (!m)
1.1.1.2 root 3308:
1.1.1.6 ! root 3309: m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
! 3310:
! 3311: }
1.1.1.2 root 3312:
3313:
3314:
3315: if (!m) {
3316:
3317: kfree(s);
3318:
3319: mint_errno = ENSMEM;
3320:
3321: return 0;
3322:
3323: }
3324:
3325:
3326:
3327: /* set up a fake "basepage" for load_and_reloc
3328:
3329: * note: the 0 values should make load_and_reloc
3330:
3331: * barf on any attempts at data relocation, since we have
3332:
3333: * no data segment
3334:
3335: */
3336:
3337: TRACE(("attempting to create shared text region"));
3338:
3339:
3340:
3341: b.p_tbase = m->loc;
3342:
3343: b.p_tlen = fh->ftext;
3344:
3345: b.p_dbase = 0;
3346:
3347: b.p_dlen = 0;
3348:
3349: b.p_bbase = b.p_blen = 0;
3350:
1.1 root 3351:
1.1.1.2 root 3352:
3353: r = load_and_reloc(f, fh, (char *)m->loc, 0, fh->ftext, &b);
3354:
3355: if (r) {
3356:
3357: detach_region(curproc, m);
3358:
3359: kfree(s);
3360:
3361: return 0;
3362:
3363: }
3364:
3365:
3366:
3367: /* region has valid shared text data */
3368:
3369: m->mflags |= M_SHTEXT;
3370:
1.1.1.6 ! root 3371: #if 1
! 3372:
! 3373: if (xp->mode & 01000)
! 3374:
! 3375: #endif
! 3376:
! 3377: /* make it sticky (this should depend on the files mode!?) */
! 3378:
! 3379: m->mflags |= M_SHTEXT_T;
! 3380:
1.1.1.2 root 3381:
3382:
3383: /*
3384:
3385: * KLUDGE: to make sure we always have up to date shared text
3386:
3387: * info, even across a network, we leave the file passed
3388:
3389: * to us open with DENYWRITE mode, so that nobody will
3390:
3391: * modify it.
3392:
3393: */
3394:
3395: f->links++; /* keep the file open longer */
3396:
3397:
3398:
3399: /* BUG: what if someone already has the file open for
3400:
3401: * writing? Then we could get screwed...
3402:
3403: */
3404:
3405: f->flags = (f->flags & ~O_SHMODE) | O_DENYW;
3406:
3407: s->f = f;
3408:
3409: s->text = m;
3410:
3411: s->next = text_reg;
3412:
3413: s->mtime = xp->mtime;
3414:
3415: s->mdate = xp->mdate;
3416:
3417: text_reg = s;
3418:
3419: TRACE(("shared text region %lx created", m));
3420:
1.1.1.6 ! root 3421: return s;
! 3422:
! 3423: }
! 3424:
! 3425:
! 3426:
! 3427: /*
! 3428:
! 3429: * function to just check for existence of a shared text region
! 3430:
! 3431: * corresponding to file "f"
! 3432:
! 3433: */
! 3434:
! 3435:
! 3436:
! 3437: MEMREGION *
! 3438:
! 3439: find_text_seg(f)
! 3440:
! 3441: FILEPTR *f;
! 3442:
! 3443: {
! 3444:
! 3445: SHTEXT *s;
! 3446:
! 3447:
! 3448:
! 3449: for (s = text_reg; s; s = s->next) {
! 3450:
! 3451: if (s->f && samefile(&f->fc, &s->f->fc))
! 3452:
! 3453: return s->text;
! 3454:
! 3455: }
! 3456:
! 3457: return 0;
1.1 root 3458:
3459: }
3460:
3461:
3462:
3463: /*
3464:
3465: * exec_region(p, mem, thread): create a child process out of a mem region
3466:
3467: * "p" is the process structure set up by the parent; it may be "curproc",
3468:
3469: * if we're overlaying. "mem" is the loaded memory region returned by
3470:
3471: * "load region". Any open files (other than the standard handles) owned
3472:
3473: * by "p" are closed, and if thread !=0 all memory is released; the caller
3474:
3475: * must explicitly attach the environment and base region. The caller must
3476:
3477: * also put "p" on the appropriate queue (most likely READY_Q).
3478:
3479: */
3480:
3481:
3482:
3483: extern long mint_dos(), mint_bios();
3484:
3485:
3486:
3487: void rts() {} /* dummy termination routine */
3488:
3489:
3490:
3491: PROC *
3492:
3493: exec_region(p, mem, thread)
3494:
3495: PROC *p;
3496:
3497: MEMREGION *mem;
3498:
3499: int thread;
3500:
3501: {
3502:
3503: BASEPAGE *b;
3504:
3505: FILEPTR *f;
3506:
3507: int i;
3508:
3509: MEMREGION *m;
3510:
3511:
3512:
1.1.1.2 root 3513: TRACE(("exec_region"));
1.1 root 3514:
3515:
3516:
3517: b = (BASEPAGE *) mem->loc;
3518:
3519:
3520:
1.1.1.2 root 3521: cpush((void *)b->p_tbase, b->p_tlen); /* flush cached versions of the text */
3522:
3523:
3524:
1.1 root 3525: /* set some (undocumented) variables in the basepage */
3526:
3527: b->p_defdrv = p->curdrv;
3528:
3529: for (i = 0; i < 6; i++)
3530:
3531: b->p_devx[i] = i;
3532:
3533:
3534:
3535: p->dta = (DTABUF *)(b->p_dta = &b->p_cmdlin[0]);
3536:
3537: p->base = b;
3538:
3539:
3540:
3541: /* close extra open files */
3542:
3543: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
3544:
1.1.1.2 root 3545: if ( (f = p->handle[i]) != 0 && (p->fdflags[i] & FD_CLOEXEC) ) {
1.1 root 3546:
3547: do_pclose(p, f);
3548:
3549: p->handle[i] = 0;
3550:
3551: }
3552:
3553: }
3554:
3555:
3556:
3557: /* initialize memory */
3558:
3559: recalc_maxmem(p);
3560:
3561: if (p->maxmem) {
3562:
3563: shrink_region(mem, p->maxmem);
3564:
3565: b->p_hitpa = b->p_lowtpa + mem->len;
3566:
3567: }
3568:
3569:
3570:
3571: p->memflags = b->p_flags;
3572:
3573:
3574:
3575: if (!thread) {
3576:
3577: for (i = 0; i < p->num_reg; i++) {
3578:
3579: m = p->mem[i];
3580:
3581: if (m) {
3582:
3583: m->links--;
3584:
1.1.1.6 ! root 3585: #if 1
! 3586:
! 3587: if (m->links <= 0) {
! 3588:
! 3589: if (!m->links) {
! 3590:
! 3591: if (m->mflags & M_SHTEXT_T) {
! 3592:
! 3593: TRACE (("exec_region: keeping sticky text segment (%lx, len %lx)",
! 3594:
! 3595: m->loc, m->len));
! 3596:
! 3597: m->links = 0xffff;
! 3598:
! 3599: } else
! 3600:
! 3601: free_region(m);
! 3602:
! 3603: } else
! 3604:
! 3605: ALERT ("exec_region: region %lx bogus link count %d, not freed (len %lx)",
! 3606:
! 3607: m->loc, m->links, m->len);
! 3608:
! 3609: }
! 3610:
! 3611: #else
! 3612:
1.1 root 3613: if (m->links <= 0)
3614:
3615: free_region(m);
3616:
1.1.1.6 ! root 3617: #endif
! 3618:
1.1 root 3619: }
3620:
3621: }
3622:
3623: if (p->num_reg > NUM_REGIONS) {
3624:
1.1.1.3 root 3625: /*
3626:
3627: * If the proc struct has a larger mem array than
3628:
3629: * the default, then free it and allocate a
3630:
3631: * default-sized one.
3632:
3633: */
1.1 root 3634:
3635:
3636:
1.1.1.3 root 3637: /*
1.1 root 3638:
1.1.1.3 root 3639: * hoo ha! Memory protection problem here. Use
3640:
3641: * temps and pre-clear p->mem so memprot doesn't try
3642:
3643: * to walk these structures as we're freeing and
3644:
3645: * reallocating them! (Calling kmalloc can cause
3646:
3647: * a table walk if the alloc results in calling
3648:
3649: * get_region.)
3650:
3651: */
3652:
3653: void *pmem, *paddr;
3654:
3655:
3656:
3657: pmem = p->mem;
3658:
3659: paddr = p->addr;
3660:
3661: p->mem = NULL; p->addr = NULL;
3662:
3663: kfree(pmem); kfree(paddr);
3664:
3665:
3666:
3667: pmem = kmalloc(NUM_REGIONS * SIZEOF(MEMREGION *));
3668:
3669: paddr = kmalloc(NUM_REGIONS * SIZEOF(virtaddr));
3670:
3671: assert(pmem && paddr);
3672:
3673: p->mem = pmem;
3674:
3675: p->addr = paddr;
1.1 root 3676:
3677: p->num_reg = NUM_REGIONS;
3678:
3679: }
3680:
3681: zero((char *)p->mem, (p->num_reg)*SIZEOF(MEMREGION *));
3682:
3683: zero((char *)p->addr, (p->num_reg)*SIZEOF(virtaddr));
3684:
3685: }
3686:
3687:
3688:
3689: /* initialize signals */
3690:
3691: p->sigmask = 0;
3692:
3693: for (i = 0; i < NSIG; i++) {
3694:
3695: if (p->sighandle[i] != SIG_IGN) {
3696:
3697: p->sighandle[i] = SIG_DFL;
3698:
3699: p->sigflags[i] = 0;
3700:
3701: p->sigextra[i] = 0;
3702:
3703: }
3704:
3705: }
3706:
3707:
3708:
3709: /* zero the user registers, and set the FPU in a "clear" state */
3710:
3711: for (i = 0; i < 15; i++)
3712:
3713: p->ctxt[CURRENT].regs[i] = 0;
3714:
3715: p->ctxt[CURRENT].sr = 0;
3716:
3717: p->ctxt[CURRENT].fstate[0] = 0;
3718:
3719:
3720:
3721: /* set PC, stack registers, etc. appropriately */
3722:
3723: p->ctxt[CURRENT].pc = b->p_tbase;
3724:
3725:
3726:
3727: /* The "-0x20" is to make sure that syscall.s won't run past the end of
3728:
3729: * memory when the user makes a system call and doesn't push very many
3730:
3731: * parameters -- syscall always tries to copy the maximum possible number
3732:
3733: * of parms.
3734:
3735: *
3736:
3737: * NOTE: there's a sanity check here in case programs Mshrink a basepage
3738:
3739: * without fixing the p_hitpa field in the basepage; this is to ensure
3740:
3741: * compatibility with older versions of MiNT, which ignore p_hitpa.
3742:
3743: */
3744:
3745: if (valid_address(b->p_hitpa - 0x20))
3746:
3747: p->ctxt[CURRENT].usp = b->p_hitpa - 0x20;
3748:
3749: else
3750:
3751: p->ctxt[CURRENT].usp = mem->loc + mem->len - 0x20;
3752:
3753:
3754:
3755: p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
3756:
3757: p->ctxt[CURRENT].term_vec = (long)rts;
3758:
3759:
3760:
3761: /* set up stack for process */
3762:
3763: *((long *)(p->ctxt[CURRENT].usp + 4)) = (long) b;
3764:
3765:
3766:
3767: /* check for a valid text region. some compilers (e.g. Lattice 3) just throw
3768:
3769: everything into the text region, including data; fork() must be careful
3770:
3771: to save the whole region, then. We assume that if the compiler (or
3772:
3773: assembler, or whatever) goes to the trouble of making separate text, data,
3774:
3775: and bss regions, then the text region is code and isn't modified and
3776:
3777: fork doesn't have to save it.
3778:
3779: */
3780:
1.1.1.2 root 3781: if (b->p_blen != 0 || b->p_dlen != 0)
1.1 root 3782:
3783: p->txtsize = b->p_tlen;
3784:
3785: else
3786:
3787: p->txtsize = 0;
3788:
3789:
3790:
3791: /*
3792:
3793: * An ugly hack: dLibs tries to poke around in the parent's address space
3794:
3795: * to find stuff. For now, we'll allow this by faking a pointer into
3796:
3797: * the parent's address space in the place in the basepage where dLibs is
3798:
3799: * expecting it. This ugly hack only works correctly if the Pexec'ing
3800:
3801: * program (i.e. curproc) is in user mode.
3802:
3803: */
3804:
1.1.1.2 root 3805: if (curproc != rootproc)
3806:
3807: curproc->base->p_usp = curproc->ctxt[SYSCALL].usp - 0x32;
1.1 root 3808:
3809:
3810:
3811: return p;
3812:
3813: }
3814:
3815:
3816:
3817: /*
3818:
3819: * misc. utility routines
3820:
3821: */
3822:
3823:
3824:
3825: /*
3826:
3827: * long memused(p): return total memory allocated to process p
3828:
3829: */
3830:
3831:
3832:
3833: long
3834:
3835: memused(p)
3836:
3837: PROC *p;
3838:
3839: {
3840:
3841: int i;
3842:
3843: long size;
3844:
3845:
3846:
1.1.1.3 root 3847: /* a ZOMBIE owns no memory and its mem array ptr is zero */
3848:
3849: if (p->mem == NULL) return 0;
3850:
3851:
3852:
1.1 root 3853: size = 0;
3854:
3855: for (i = 0; i < p->num_reg; i++) {
3856:
1.1.1.6 ! root 3857: if (p->mem[i]) {
! 3858:
! 3859: if (p->mem[i]->mflags & (M_SEEN|M_FSAVED))
! 3860:
! 3861: continue; /* count links only once */
! 3862:
! 3863: p->mem[i]->mflags |= M_SEEN;
1.1 root 3864:
3865: size += p->mem[i]->len;
3866:
1.1.1.6 ! root 3867: }
! 3868:
! 3869: }
! 3870:
! 3871: for (i = 0; i < p->num_reg; i++) {
! 3872:
! 3873: if (p->mem[i])
! 3874:
! 3875: p->mem[i]->mflags &= ~M_SEEN;
! 3876:
1.1 root 3877: }
3878:
3879: return size;
3880:
3881: }
3882:
3883:
3884:
3885: /*
3886:
3887: * recalculate the maximum memory limit on a process; this limit depends
3888:
3889: * on the max. allocated memory and max. total memory limits set by
3890:
3891: * p_setlimit (see dos.c), and (perhaps) on the size of the program
3892:
3893: * that the process is executing. whenever any of these things
3894:
3895: * change (through p_exec or p_setlimit) this routine must be called
3896:
3897: */
3898:
3899:
3900:
3901: void
3902:
3903: recalc_maxmem(p)
3904:
3905: PROC *p;
3906:
3907: {
3908:
3909: BASEPAGE *b;
3910:
3911: long siz;
3912:
3913:
3914:
3915: b = (BASEPAGE *)p->base;
3916:
3917: if (b)
3918:
3919: siz = b->p_tlen + b->p_dlen + b->p_blen;
3920:
3921: else
3922:
3923: siz = 0;
3924:
3925: p->maxmem = 0;
3926:
3927: if (p->maxdata) {
3928:
3929: p->maxmem = p->maxdata + siz;
3930:
3931: }
3932:
3933:
3934:
3935: if (p->maxcore) {
3936:
3937: if (p->maxmem == 0 || p->maxmem > p->maxcore)
3938:
3939: p->maxmem = p->maxcore;
3940:
3941: }
3942:
3943: if (p->maxmem && p->maxmem < siz)
3944:
3945: p->maxmem = siz;
3946:
3947: }
3948:
3949:
3950:
3951: /*
3952:
3953: * valid_address: checks to see if the indicated address falls within
3954:
3955: * memory attached to the current process
3956:
3957: */
3958:
3959:
3960:
3961: int
3962:
3963: valid_address(addr)
3964:
3965: long addr;
3966:
3967: {
3968:
3969: int i;
3970:
3971: MEMREGION *m;
3972:
3973:
3974:
3975: for (i = 0; i < curproc->num_reg; i++) {
3976:
3977: if ((m = curproc->mem[i]) != 0) {
3978:
3979: if (addr >= m->loc && addr <= m->loc + m->len)
3980:
3981: return 1;
3982:
3983: }
3984:
3985: }
3986:
3987: return 0;
3988:
3989: }
3990:
3991:
3992:
3993: /*
3994:
1.1.1.3 root 3995: * convert an address to a memory region; this works only in
3996:
3997: * the ST RAM and TT RAM maps, and will fail for memory that
3998:
3999: * MiNT doesn't own or which is virtualized
4000:
4001: */
4002:
4003:
4004:
4005: MEMREGION *
4006:
4007: addr2region(addr)
4008:
4009: long addr;
4010:
4011: {
4012:
4013: unsigned long ua = (unsigned long) addr;
4014:
4015:
4016:
4017: extern ulong mint_top_st, mint_top_tt;
4018:
4019: MEMREGION *r;
4020:
4021: MMAP map;
4022:
4023:
4024:
4025: if (ua < mint_top_st) {
4026:
4027: map = core;
4028:
4029: } else if (ua < mint_top_tt) {
4030:
4031: map = alt;
4032:
4033: } else {
4034:
4035: return 0;
4036:
4037: }
4038:
4039:
4040:
4041: for (r = *map; r; r = r->next) {
4042:
4043: if (addr >= r->loc && addr < r->loc + r->len)
4044:
4045: return r;
4046:
4047: }
4048:
4049: return 0;
4050:
4051: }
4052:
4053:
4054:
4055: /*
4056:
1.1 root 4057: * some debugging stuff
4058:
4059: */
4060:
4061:
4062:
4063: void
4064:
1.1.1.3 root 4065: DUMP_ALL_MEM()
4066:
4067: {
4068:
1.1.1.5 root 4069: #ifdef DEBUG_INFO
4070:
1.1.1.3 root 4071: DUMPMEM(ker);
4072:
4073: DUMPMEM(core);
4074:
4075: DUMPMEM(alt);
4076:
1.1.1.5 root 4077: FORCE("new memory region descriptor pages: %d", num_reg_requests);
4078:
4079: #endif
4080:
1.1.1.3 root 4081: }
4082:
4083:
4084:
4085: void
4086:
1.1 root 4087: DUMPMEM(map)
4088:
4089: MMAP map;
4090:
4091: {
4092:
1.1.1.4 root 4093: #ifdef DEBUG_INFO
1.1.1.2 root 4094:
1.1 root 4095: MEMREGION *m;
4096:
4097:
4098:
4099: m = *map;
4100:
1.1.1.3 root 4101: FORCE("%s memory dump: starting at region %lx",
4102:
4103: (map == ker ? "ker" : (map == core ? "core" : "alt")), m);
1.1 root 4104:
4105: while (m) {
4106:
1.1.1.6 ! root 4107: FORCE("%ld bytes at %lx (%d links, mflags %x); next %lx", m->len, m->loc,
1.1 root 4108:
1.1.1.6 ! root 4109: m->links, m->mflags, m->next);
1.1 root 4110:
1.1.1.3 root 4111: m = m->next;
1.1 root 4112:
4113: }
4114:
1.1.1.4 root 4115: #else
4116:
4117: UNUSED(map);
4118:
1.1.1.2 root 4119: #endif
4120:
1.1 root 4121: }
4122:
4123:
4124:
4125: void
4126:
4127: sanity_check(map)
4128:
4129: MMAP map;
4130:
4131: {
4132:
4133: #ifdef SANITY_CHECK
4134:
4135: MEMREGION *m, *nxt;
4136:
4137: long end;
4138:
4139:
4140:
4141: m = *map;
4142:
4143: while (m) {
4144:
4145: nxt = m->next;
4146:
4147: if (nxt) {
4148:
4149: end = m->loc + m->len;
4150:
4151: if (m->loc < nxt->loc && end > nxt->loc) {
4152:
4153: FATAL("MEMORY CHAIN CORRUPTED");
4154:
4155: }
4156:
4157: else if (end == nxt->loc && ISFREE(m) && ISFREE(nxt)) {
4158:
4159: ALERT("Continguous memory regions not merged!");
4160:
4161: }
4162:
4163: }
4164:
4165: m = nxt;
4166:
4167: }
4168:
1.1.1.2 root 4169: #else
4170:
4171: UNUSED(map);
4172:
1.1 root 4173: #endif
4174:
4175: }
4176:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.