|
|
1.1 root 1: /*
2:
3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /*
10:
11: * mem.c:: routines for managing memory regions
12:
13: */
14:
15:
16:
17: #include "mint.h"
18:
19:
20:
21: static long core_malloc P_((long, int));
22:
23:
24:
25: /* macro for testing whether a memory region is free */
26:
27: #define ISFREE(m) ((m)->links == 0)
28:
29:
30:
31: /*
32:
1.1.1.2 ! root 33: * list of shared text regions currently being executed
! 34:
! 35: */
! 36:
! 37: SHTEXT *text_reg = 0;
! 38:
! 39:
! 40:
! 41: /*
! 42:
1.1 root 43: * initialize memory routines
44:
45: */
46:
47:
48:
49: /* initial number of memory regions */
50:
51: #define NREGIONS 512
52:
53:
54:
55: /* number of new regions to allocate when the initial ones are used up */
56:
57: #define NEWREGIONS 256
58:
59:
60:
61: static MEMREGION use_regions[NREGIONS+1];
62:
63: MEMREGION *rfreelist;
64:
65:
66:
67: void
68:
69: init_mem()
70:
71: {
72:
73: int i;
74:
75:
76:
77: use_regions[NREGIONS].next = 0;
78:
79: for (i = 0; i < NREGIONS; i++) {
80:
81: use_regions[i].next = &use_regions[i+1];
82:
83: }
84:
85: rfreelist = use_regions;
86:
87:
88:
89: init_core();
90:
91: init_swap();
92:
93: }
94:
95:
96:
97: /*
98:
99: * init_core(): initialize the core memory map (normal ST ram) and also
100:
101: * the alternate memory map (fast ram on the TT)
102:
103: */
104:
105:
106:
107: static MEMREGION *_core_regions = 0, *_alt_regions = 0,
108:
109: *_ker_regions = 0;
110:
111:
112:
113: MMAP core = &_core_regions;
114:
115: MMAP alt = &_alt_regions;
116:
117: MMAP ker = &_ker_regions;
118:
119:
120:
121: /* note: add_region must adjust both the size and starting
122:
123: * address of the region being added so that memory is
124:
125: * always properly aligned
126:
127: */
128:
129:
130:
131: int
132:
133: add_region(map, place, size, mflags)
134:
135: MMAP map;
136:
137: ulong place, size;
138:
139: unsigned mflags; /* initial flags for region */
140:
141: {
142:
143: MEMREGION *m;
144:
145: ulong newplace;
146:
147:
148:
149: newplace = ROUND(place);
150:
151: size = (place + size) - newplace;
152:
153: size &= ~MASKBITS;
154:
1.1.1.2 ! root 155: if ((long)size <= 0L) /* region too small to use */
1.1 root 156:
157: return 1;
158:
159:
160:
161: m = new_region();
162:
163: if (m == 0)
164:
165: return 0; /* failure */
166:
167: m->links = 0;
168:
169: m->len = size;
170:
171: m->loc = newplace;
172:
173: m->next = *map;
174:
175: m->mflags = mflags;
176:
177: *map = m;
178:
179: return 1; /* success */
180:
181: }
182:
183:
184:
185: static long
186:
187: core_malloc(amt, mode)
188:
189: long amt;
190:
191: int mode;
192:
193: {
194:
195: static int mxalloc = -1; /* does GEMDOS know about Mxalloc? */
196:
197: long ret;
198:
199:
200:
201: if (mxalloc < 0) {
202:
203: ret = (long)Mxalloc(-1L, 0);
204:
205: if (ret == -32) mxalloc = 0; /* unknown function */
206:
207: else if (ret >= 0) mxalloc = 1;
208:
209: else {
210:
211: ALERT("GEMDOS returned %ld from Mxalloc", ret);
212:
213: mxalloc = 0;
214:
215: }
216:
217: }
218:
219: if (mxalloc)
220:
221: return Mxalloc(amt, mode);
222:
223: else if (mode == 1)
224:
225: return 0L;
226:
227: else
228:
229: return Malloc(amt);
230:
231: }
232:
233:
234:
235: void
236:
237: init_core()
238:
239: {
240:
241: ulong size;
242:
243: ulong place;
244:
245: void *tossave;
246:
247:
248:
249: tossave = (void *)core_malloc((long)TOS_MEM, 0);
250:
251: if (!tossave) {
252:
253: FATAL("Not enough memory to run MiNT");
254:
255: }
256:
257:
258:
259: /* initialize kernel memory */
260:
261: place = (ulong)core_malloc(KERNEL_MEM, 3);
262:
263: if (place != 0) {
264:
265: (void)add_region(ker, place, KERNEL_MEM, M_KER);
266:
267: }
268:
269:
270:
271: /* initialize ST RAM */
272:
273: size = (ulong)core_malloc(-1L, 0);
274:
275: while (size > 0) {
276:
277: place = (ulong)core_malloc(size, 0);
278:
279: if (!add_region(core, place, size, M_CORE))
280:
281: FATAL("init_mem: unable to add a region");
282:
283: size = (ulong)core_malloc(-1L, 0);
284:
285: }
286:
287:
288:
289: /* initialize alternate RAM */
290:
291: size = (ulong)core_malloc(-1L, 1);
292:
293: while (size > 0) {
294:
295: place = (ulong)core_malloc(size, 1);
296:
297: if (!add_region(alt, place, size, M_ALT))
298:
299: FATAL("init_mem: unable to add a region");
300:
301: size = (ulong)core_malloc(-1L, 1);
302:
303: }
304:
305:
306:
307: (void)Mfree(tossave); /* leave some memory for TOS to use */
308:
309: }
310:
311:
312:
313: /*
314:
315: * init_swap(): initialize the swap area; for now, this does nothing
316:
317: */
318:
319:
320:
321: MEMREGION *_swap_regions = 0;
322:
323: MMAP swap = &_swap_regions;
324:
325:
326:
327: void
328:
329: init_swap()
330:
331: {
332:
333: }
334:
335:
336:
337: /*
338:
339: * routines for allocating/deallocating memory regions
340:
341: */
342:
343:
344:
345: /*
346:
347: * new_region returns a new memory region descriptor, or NULL
348:
349: */
350:
351:
352:
353: MEMREGION *
354:
355: new_region()
356:
357: {
358:
359: MEMREGION *m, *newfrees;
360:
361: int i;
362:
363:
364:
365: m = rfreelist;
366:
367: if (!m) {
368:
369: ALERT("new_region: ran out of free regions");
370:
371: return 0;
372:
373: }
374:
375: assert(ISFREE(m));
376:
377: rfreelist = m->next;
378:
379: m->next = 0;
380:
381:
382:
383: /* if we're running low on free regions, allocate some more
384:
385: * we have to do this with at least 1 free region left so that get_region
386:
387: * has a chance of working
388:
389: */
390:
391: if (rfreelist && !rfreelist->next) {
392:
393: MEMREGION *newstuff;
394:
395:
396:
1.1.1.2 ! root 397: TRACE(("get_region: getting new region descriptors"));
1.1 root 398:
399: newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION));
400:
401: if (!newstuff)
402:
403: newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION));
404:
405: if (!newstuff)
406:
407: newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION));
408:
409: newfrees = newstuff ? (MEMREGION *)newstuff->loc : 0;
410:
411: if (newfrees) {
412:
413: newfrees[NEWREGIONS-1].next = 0;
414:
415: newfrees[NEWREGIONS-1].links = 0;
416:
417: for (i = 0; i < NEWREGIONS-1; i++) {
418:
419: newfrees[i].next = &newfrees[i+1];
420:
421: newfrees[i].links = 0;
422:
423: }
424:
425: rfreelist = newfrees;
426:
427: } else {
428:
1.1.1.2 ! root 429: DEBUG(("couldn't get new region descriptors!"));
1.1 root 430:
431: }
432:
433: }
434:
435:
436:
437: return m;
438:
439: }
440:
441:
442:
443: /*
444:
445: * dispose_region destroys a memory region descriptor
446:
447: */
448:
449:
450:
451: void
452:
453: dispose_region(m)
454:
455: MEMREGION *m;
456:
457: {
458:
459: m->next = rfreelist;
460:
461: rfreelist = m;
462:
463: }
464:
465:
466:
467: /*
468:
469: * virtaddr
470:
471: * attach_region(proc, reg): attach the region to the given process:
472:
473: * returns the address at which it was attached, or NULL if the process
474:
475: * cannot attach more regions. The region link count is incremented if
476:
477: * the attachment is successful.
478:
479: */
480:
481:
482:
483: virtaddr
484:
485: attach_region(proc, reg)
486:
487: PROC *proc;
488:
489: MEMREGION *reg;
490:
491: {
492:
493: int i;
494:
495: MEMREGION **newmem;
496:
497: virtaddr *newaddr;
498:
499:
500:
501: if (!reg || !reg->loc) {
502:
503: ALERT("attach_region: attaching a null region??");
504:
505: return 0;
506:
507: }
508:
509: for (i = 0; i < proc->num_reg; i++) {
510:
511: if (!proc->mem[i]) {
512:
513: assert(proc->addr[i] == 0);
514:
515: reg->links++;
516:
517: proc->mem[i] = reg;
518:
519: proc->addr[i] = (virtaddr) reg->loc;
520:
521: return proc->addr[i];
522:
523: }
524:
525: }
526:
527:
528:
529: /* Hmmm, OK, we have to expand the process' memory table */
530:
1.1.1.2 ! root 531: TRACE(("Expanding process memory table"));
1.1 root 532:
533: i = proc->num_reg + NUM_REGIONS;
534:
535:
536:
537: newmem = kmalloc(i * SIZEOF(MEMREGION *));
538:
539: newaddr = kmalloc(i * SIZEOF(virtaddr));
540:
541:
542:
543: if (newmem && newaddr) {
544:
545: /* copy over the old address mapping */
546:
547: for (i = 0; i < proc->num_reg; i++) {
548:
549: newmem[i] = proc->mem[i];
550:
551: newaddr[i] = proc->addr[i];
552:
553: if (newmem[i] == 0)
554:
555: assert(newaddr[i] == 0);
556:
557: }
558:
559: /* initialize the rest of the tables */
560:
561: for(; i < proc->num_reg + NUM_REGIONS; i++) {
562:
563: newmem[i] = 0;
564:
565: newaddr[i] = 0;
566:
567: }
568:
569: /* free the old tables */
570:
571: kfree(proc->mem); kfree(proc->addr);
572:
573: proc->mem = newmem;
574:
575: proc->addr = newaddr;
576:
577: proc->num_reg += NUM_REGIONS;
578:
579: /* this call will succeed */
580:
1.1.1.2 ! root 581: TRACE(("recursively calling attach_region"));
1.1 root 582:
583: return attach_region(proc, reg);
584:
585: }
586:
587:
588:
1.1.1.2 ! root 589: DEBUG(("attach_region: failed"));
1.1 root 590:
591: return 0;
592:
593: }
594:
595:
596:
597: /*
598:
599: * detach_region(proc, reg): remove region from the procedure's address
600:
601: * space. If no more processes reference the region, return it to the
602:
603: * system. Note that we search backwards, so that the most recent
604:
605: * attachment of memory gets detached!
606:
607: */
608:
609:
610:
611: void
612:
613: detach_region(proc, reg)
614:
615: PROC *proc;
616:
617: MEMREGION *reg;
618:
619: {
620:
621: int i;
622:
623:
624:
625: if (!reg) return;
626:
627: for (i = proc->num_reg - 1; i >= 0; i--) {
628:
629: if (proc->mem[i] == reg) {
630:
631: reg->links--;
632:
633: proc->mem[i] = 0; proc->addr[i] = 0;
634:
635: if (reg->links == 0) {
636:
637: free_region(reg);
638:
639: }
640:
641: return;
642:
643: }
644:
645: }
646:
1.1.1.2 ! root 647: DEBUG(("detach_region: region not attached"));
1.1 root 648:
649: }
650:
651:
652:
653: /*
654:
655: * get_region(MMAP map, ulong size) -- allocate a new region of the
656:
657: * given size in the given memory map. if no region big enough is available,
658:
659: * return NULL, otherwise return a pointer to the region.
660:
661: * the "links" field in the region is set to 1
662:
663: *
664:
665: * BEWARE: new_region may call get_region (indirectly), so we have to be
666:
667: * _very_ careful with re-entrancy in this function
668:
669: */
670:
671:
672:
673: MEMREGION *
674:
675: get_region(map, size)
676:
677: MMAP map;
678:
679: ulong size;
680:
681: {
682:
683: MEMREGION *m, *n;
684:
685:
686:
687: /* precautionary measures */
688:
689: if (size == 0) {
690:
1.1.1.2 ! root 691: DEBUG(("request for 0 bytes??"));
1.1 root 692:
693: size = 1;
694:
695: }
696:
697:
698:
699: size = ROUND(size);
700:
701:
702:
703: n = *map;
704:
705:
706:
707: sanity_check(map);
708:
709: /* exact matches are likely to be rare, so we pre-allocate a new
710:
711: * region here; this helps us to avoid re-entrancy problems
712:
713: * when new_region calls get_region
714:
715: */
716:
717: m = new_region();
718:
719:
720:
721: while (n) {
722:
723: if (ISFREE(n)) {
724:
725: if (n->len == size) {
726:
727: if (m) dispose_region(m);
728:
729: n->links++;
730:
731: return n;
732:
733: }
734:
735: else if (n->len > size) {
736:
737: /* split a new region, 'm', which will contain the free bytes after n */
738:
739: if (m) {
740:
741: m->next = n->next;
742:
743: n->next = m;
744:
745: m->mflags = n->mflags & M_MAP;
746:
747: m->loc = n->loc + size;
748:
749: m->len = n->len - size;
750:
751: n->len = size;
752:
753: n->links++;
754:
755: return n;
756:
757: } else {
758:
1.1.1.2 ! root 759: DEBUG(("get_region: no regions left"));
1.1 root 760:
761: return 0;
762:
763: }
764:
765: }
766:
767: }
768:
769: n = n->next;
770:
771: }
772:
773:
774:
775: if (m)
776:
777: dispose_region(m);
778:
779: return NULL;
780:
781: }
782:
783:
784:
785: /*
786:
787: * free_region(MEMREGION *reg): free the indicated region. The map
788:
789: * in which the region is contained is given by reg->mflags.
790:
791: * the caller is responsible for making sure that the region
792:
793: * really should be freed, i.e. that reg->links == 0.
794:
1.1.1.2 ! root 795: *
! 796:
! 797: * special things to do:
! 798:
! 799: * if the region is a shared text region, we must close the
! 800:
! 801: * associated file descriptor
! 802:
1.1 root 803: */
804:
805:
806:
807: void
808:
809: free_region(reg)
810:
811: MEMREGION *reg;
812:
813: {
814:
815: MMAP map;
816:
817: MEMREGION *m;
818:
1.1.1.2 ! root 819: SHTEXT *s, **old;
! 820:
1.1 root 821:
822:
823: if (!reg) return;
824:
825:
826:
827: assert(ISFREE(reg));
828:
829:
830:
1.1.1.2 ! root 831: if (reg->mflags & M_SHTEXT) {
! 832:
! 833: TRACE(("freeing shared text region"));
! 834:
! 835: old = &text_reg;
! 836:
! 837: for(;;) {
! 838:
! 839: s = *old;
! 840:
! 841: if (!s) break;
! 842:
! 843: if (s->text == reg) {
! 844:
! 845: do_close(s->f);
! 846:
! 847: *old = s->next;
! 848:
! 849: kfree(s);
! 850:
! 851: break;
! 852:
! 853: }
! 854:
! 855: old = &s->next;
! 856:
! 857: }
! 858:
! 859: if (!s) {
! 860:
! 861: DEBUG(("No shared text entry for M_SHTEXT region??"));
! 862:
! 863: }
! 864:
! 865: }
! 866:
! 867:
! 868:
1.1 root 869: if (reg->mflags & M_CORE)
870:
871: map = core;
872:
873: else if (reg->mflags & M_ALT)
874:
875: map = alt;
876:
877: else if (reg->mflags & M_KER)
878:
879: map = ker;
880:
881: else {
882:
883: FATAL("free_region: region flags not valid (%x)", reg->mflags);
884:
885: }
886:
887: reg->mflags &= M_MAP;
888:
889: m = *map;
890:
891: assert(m);
892:
893:
894:
1.1.1.2 ! root 895: /* BUG: should invalidate caches entries - a copyback cache could stuff
! 896:
! 897: * things into freed memory.
! 898:
! 899: * cinv(m->loc, m->len);
! 900:
! 901: */
! 902:
1.1 root 903: if (m == reg) goto merge_after;
904:
905:
906:
907: /* merge previous region if it's free and contiguous with 'reg' */
908:
909:
910:
911: /* first, we find the region */
912:
913: while (m && m->next != reg)
914:
915: m = m->next;
916:
917:
918:
1.1.1.2 ! root 919: if (m == NULL) {
! 920:
! 921: FATAL("couldn't find region %lx: loc: %lx len: %ld",
! 922:
! 923: reg, reg->loc, reg->len);
! 924:
! 925: }
1.1 root 926:
927:
928:
929: if (ISFREE(m) && (m->loc + m->len == reg->loc)) {
930:
931: m->len += reg->len;
932:
933: assert(m->next == reg);
934:
935: m->next = reg->next;
936:
937: reg->next = 0;
938:
939: dispose_region(reg);
940:
941: reg = m;
942:
943: }
944:
945:
946:
947: /* merge next region if it's free and contiguous with 'reg' */
948:
949: merge_after:
950:
951: m = reg->next;
952:
953: if (m && ISFREE(m) && reg->loc + reg->len == m->loc) {
954:
955: reg->len += m->len;
956:
957: reg->next = m->next;
958:
959: m->next = 0;
960:
961: dispose_region(m);
962:
963: }
964:
965:
966:
967: sanity_check(map);
968:
969: }
970:
971:
972:
973: /*
974:
975: * shrink_region(MEMREGION *reg, ulong newsize):
976:
977: * shrink region 'reg', so that it is now 'newsize' bytes long.
978:
979: * if 'newsize' is bigger than the region's current size, return EGSBF;
980:
981: * otherwise return 0.
982:
983: */
984:
985:
986:
987: long
988:
989: shrink_region(reg, newsize)
990:
991: MEMREGION *reg;
992:
993: ulong newsize;
994:
995: {
996:
997: MEMREGION *n;
998:
999: ulong diff;
1000:
1001:
1002:
1003:
1004:
1005: newsize = ROUND(newsize);
1006:
1007:
1008:
1009: assert(reg->links > 0);
1010:
1011:
1012:
1.1.1.2 ! root 1013: if (!(reg->mflags & (M_CORE | M_ALT | M_KER))) {
1.1 root 1014:
1015: FATAL("shrink_region: bad region flags (%x)", reg->mflags);
1016:
1017: }
1018:
1019:
1020:
1021: /* shrinking to 0 is the same as freeing */
1022:
1023: if (newsize == 0) {
1024:
1025: detach_region(curproc, reg);
1026:
1027: return 0;
1028:
1029: }
1030:
1031:
1032:
1033: /* if new size is the same as old size, don't do anything */
1034:
1035: if (newsize == reg->len) {
1036:
1037: return 0; /* nothing to do */
1038:
1039: }
1040:
1041:
1042:
1043: if (newsize > reg->len) {
1044:
1.1.1.2 ! root 1045: DEBUG(("shrink_region: request to make region bigger"));
1.1 root 1046:
1047: return EGSBF; /* growth failure */
1048:
1049: }
1050:
1051:
1052:
1053: /* OK, we're going to free (reg->len - newsize) bytes at the end of
1054:
1055: this block. If the block after us is already free, simply add the
1056:
1057: space to that block.
1058:
1059: */
1060:
1061: n = reg->next;
1062:
1063: diff = reg->len - newsize;
1064:
1065:
1066:
1067: if (n && ISFREE(n) && reg->loc + reg->len == n->loc) {
1068:
1069: reg->len = newsize;
1070:
1071: n->loc -= diff;
1072:
1073: n->len += diff;
1074:
1075: return 0;
1076:
1077: }
1078:
1079: else {
1080:
1081: n = new_region();
1082:
1083: if (!n) {
1084:
1.1.1.2 ! root 1085: DEBUG(("shrink_region: new_region failed"));
1.1 root 1086:
1087: return EINTRN;
1088:
1089: }
1090:
1091: reg->len = newsize;
1092:
1093: n->loc = reg->loc + newsize;
1094:
1095: n->len = diff;
1096:
1097: n->mflags = reg->mflags & M_MAP;
1098:
1099: n->next = reg->next;
1100:
1101: reg->next = n;
1102:
1103: }
1104:
1105: return 0;
1106:
1107: }
1108:
1109:
1110:
1111: /*
1112:
1113: * max_rsize(map): return the length of the biggest free region
1114:
1115: * in the given memory map, or 0 if no regions remain.
1116:
1117: */
1118:
1119:
1120:
1121: long
1122:
1123: max_rsize(map)
1124:
1125: MMAP map;
1126:
1127: {
1128:
1.1.1.2 ! root 1129: MEMREGION *m;
1.1 root 1130:
1131: long size = 0;
1132:
1133:
1134:
1135: for (m = *map; m; m = m->next) {
1136:
1137: if (ISFREE(m)) {
1138:
1139: if (m->len > size) {
1140:
1141: size = m->len;
1142:
1143: }
1144:
1145: }
1146:
1147: }
1148:
1149: return size;
1150:
1151: }
1152:
1153:
1154:
1155: /*
1156:
1157: * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
1158:
1159: * the given memory map; if flag == 0, return only the number of free
1160:
1161: * bytes
1162:
1163: */
1164:
1165:
1166:
1167: long
1168:
1169: tot_rsize(map, flag)
1170:
1171: MMAP map;
1172:
1173: int flag;
1174:
1175: {
1176:
1177: MEMREGION *m;
1178:
1179: long size = 0;
1180:
1181:
1182:
1183: for (m = *map; m; m = m->next) {
1184:
1185: if (flag || ISFREE(m)) {
1186:
1187: size += m->len;
1188:
1189: }
1190:
1191: }
1192:
1193: return size;
1194:
1195: }
1196:
1197:
1198:
1199: /*
1200:
1201: * alloc_region(MMAP map, ulong size): allocate a new region and attach
1202:
1203: * it to the current process; returns the address at which the region
1204:
1205: * was attached, or NULL. If not enough memory is found, wait a bit
1206:
1207: * and try again before giving up (maybe someone else will free some
1208:
1209: * memory)
1210:
1211: */
1212:
1213:
1214:
1215: virtaddr
1216:
1217: alloc_region(map, size)
1218:
1219: MMAP map;
1220:
1221: ulong size;
1222:
1223: {
1224:
1225: MEMREGION *m;
1226:
1227: PROC *proc = curproc;
1228:
1229: virtaddr v;
1230:
1231:
1232:
1233: m = get_region(map, size);
1234:
1235: if (!m) {
1236:
1237: return 0;
1238:
1239: }
1240:
1241:
1242:
1.1.1.2 ! root 1243: /* sanity check: even addresses only, please */
! 1244:
! 1245: assert((m->loc & MASKBITS) == 0);
! 1246:
! 1247:
! 1248:
1.1 root 1249: v = attach_region(proc, m);
1250:
1251: /* NOTE: get_region returns a region with link count 1; since attach_region
1252:
1253: * increments the link count, we restore it after calling attach_region
1254:
1255: */
1256:
1257: m->links = 1;
1258:
1259: if (!v) {
1260:
1261: m->links = 0;
1262:
1263: free_region(m);
1264:
1265: return 0;
1266:
1267: }
1268:
1269: return v;
1270:
1271: }
1272:
1273:
1274:
1275: /*
1276:
1277: * routines for creating a copy of an environment, and a new basepage.
1278:
1279: * note that the memory regions created should immediately be attached to
1280:
1281: * a process! Also note that create_env always operates in ST RAM, but
1282:
1283: * create_base might not.
1284:
1285: */
1286:
1287:
1288:
1289: MEMREGION *
1290:
1291: create_env(env)
1292:
1293: const char *env;
1294:
1295: {
1296:
1297: long size;
1298:
1299: MEMREGION *m;
1300:
1301: virtaddr v;
1302:
1303: const char *old;
1304:
1305: char *new;
1306:
1307:
1308:
1309: if (!env) {
1310:
1311: env = ((BASEPAGE *)curproc->base)->p_env;
1312:
1313: /* duplicate parent's environment */
1314:
1315: }
1316:
1317: size = 2;
1318:
1319: old = env;
1320:
1321: while (*env || *(env+1))
1322:
1323: env++,size++;
1324:
1325: v = alloc_region(core, size);
1326:
1327: if (!v) {
1328:
1.1.1.2 ! root 1329: DEBUG(("create_env: alloc_region failed"));
1.1 root 1330:
1331: return (MEMREGION *)0;
1332:
1333: }
1334:
1335: m = addr2mem(v);
1336:
1337:
1338:
1339: /* copy the old environment into the new */
1340:
1341: new = (char *) m->loc;
1342:
1343: while (size > 0) {
1344:
1345: *new++ = *old++;
1346:
1347: --size;
1348:
1349: }
1350:
1351: return m;
1352:
1353: }
1354:
1355:
1356:
1357: MEMREGION *
1358:
1359: create_base(cmd, env, flags, prgsize)
1360:
1361: const char *cmd;
1362:
1363: MEMREGION *env;
1364:
1365: ulong flags, prgsize;
1366:
1367: {
1368:
1369: long len, coresize, altsize;
1370:
1371: MMAP map;
1372:
1373: MEMREGION *m;
1374:
1375: BASEPAGE *b;
1376:
1377:
1378:
1379: /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
1380:
1381: RAM if enough is available. "enough" is: if more alt ram than ST ram,
1382:
1383: load there; otherwise, if more than (minalt+1)*128K alt ram available
1384:
1385: for heap space, load in alt ram ("minalt" is the high byte of flags)
1386:
1387: */
1388:
1389: if (flags & F_ALTLOAD) {
1390:
1391: coresize = max_rsize(core);
1392:
1393: altsize = max_rsize(alt);
1394:
1395: if (altsize >= coresize)
1396:
1397: map = alt;
1398:
1399: else {
1400:
1.1.1.2 ! root 1401: len = (flags & F_MINALT) >> 28L;
1.1 root 1402:
1403: len = (len+1)*128*1024L + prgsize + 256;
1404:
1405: if (altsize >= len)
1406:
1407: map = alt;
1408:
1409: else
1410:
1411: map = core;
1412:
1413: }
1414:
1415: }
1416:
1417: else
1418:
1419: map = core;
1420:
1421:
1422:
1423: len = max_rsize(map);
1424:
1425:
1426:
1427: /* make sure that a little bit of memory is left over */
1428:
1429: if (len > 2*KEEP_MEM) {
1430:
1431: len -= KEEP_MEM;
1432:
1433: }
1434:
1435: m = addr2mem(alloc_region(map, len));
1436:
1437: if (!m) {
1438:
1.1.1.2 ! root 1439: DEBUG(("create_base: alloc_region failed"));
1.1 root 1440:
1441: return 0;
1442:
1443: }
1444:
1445: b = (BASEPAGE *)(m->loc);
1446:
1447:
1448:
1449: zero((char *)b, (long)sizeof(BASEPAGE));
1450:
1451: b->p_lowtpa = (long)b;
1452:
1453: b->p_hitpa = m->loc + m->len;
1454:
1455: b->p_env = (char *)env->loc;
1456:
1457: b->p_flags = flags;
1458:
1459:
1460:
1461: if (cmd)
1462:
1463: strncpy(b->p_cmdlin, cmd, 126);
1464:
1465: return m;
1466:
1467: }
1468:
1469:
1470:
1471: /*
1472:
1.1.1.2 ! root 1473: * load_region(): loads the program with the given file name
1.1 root 1474:
1.1.1.2 ! root 1475: * into a new region, and returns a pointer to that region. On
1.1 root 1476:
1.1.1.2 ! root 1477: * an error, returns 0 and leaves the error number in mint_errno.
1.1 root 1478:
1.1.1.2 ! root 1479: * "env" points to an already set up environment region, as returned
1.1 root 1480:
1.1.1.2 ! root 1481: * by create_env. "xp" points to the file attributes, which
1.1 root 1482:
1.1.1.2 ! root 1483: * Pexec has already determined. "text" is a pointer to a MEMREGION
1.1 root 1484:
1.1.1.2 ! root 1485: * pointer, which will be set to the region occupied by the shared
1.1 root 1486:
1.1.1.2 ! root 1487: * text segment of this program (if applicable).
1.1 root 1488:
1.1.1.2 ! root 1489: */
1.1 root 1490:
1491:
1492:
1493: MEMREGION *
1494:
1.1.1.2 ! root 1495: load_region(filename, env, cmdlin, xp, text)
1.1 root 1496:
1497: const char *filename;
1498:
1499: MEMREGION *env;
1500:
1501: const char *cmdlin;
1502:
1503: XATTR *xp; /* attributes for the file just loaded */
1504:
1.1.1.2 ! root 1505: MEMREGION **text; /* set to point to shared text region,
! 1506:
! 1507: if any */
! 1508:
1.1 root 1509: {
1510:
1511: FILEPTR *f;
1512:
1513: DEVDRV *dev;
1514:
1.1.1.2 ! root 1515: MEMREGION *reg, *shtext;
1.1 root 1516:
1517: BASEPAGE *b;
1518:
1.1.1.2 ! root 1519: long size, start;
1.1 root 1520:
1.1.1.2 ! root 1521: FILEHEAD fh;
1.1 root 1522:
1.1.1.2 ! root 1523: int trycount;
1.1 root 1524:
1525:
1526:
1.1.1.2 ! root 1527: /* bug: this should be O_DENYW mode, not O_DENYNONE */
1.1 root 1528:
1.1.1.2 ! root 1529: /* we must use O_DENYNONE because of the desktop and because of the
1.1 root 1530:
1.1.1.2 ! root 1531: * TOS file system brain-damage
1.1 root 1532:
1.1.1.2 ! root 1533: */
1.1 root 1534:
1535: f = do_open(filename, O_DENYNONE | O_EXEC, 0, xp);
1536:
1537: if (!f) {
1538:
1539: return 0; /* mint_errno set by do_open */
1540:
1541: }
1542:
1543:
1544:
1.1.1.2 ! root 1545: dev = f->dev;
1.1 root 1546:
1.1.1.2 ! root 1547: size = (*dev->read)(f, (void *)&fh, (long)sizeof(fh));
1.1 root 1548:
1.1.1.2 ! root 1549: if (fh.fmagic != GEMDOS_MAGIC || size != (long)sizeof(fh)) {
1.1 root 1550:
1.1.1.2 ! root 1551: DEBUG(("load_region: file not executable"));
1.1 root 1552:
1553: mint_errno = ENOEXEC;
1554:
1555: failed:
1556:
1557: do_close(f);
1558:
1559: return 0;
1560:
1561: }
1562:
1563:
1564:
1.1.1.2 ! root 1565: if (fh.flag & F_SHTEXT) {
! 1566:
! 1567: TRACE(("loading shared text segment"));
! 1568:
! 1569: shtext = get_text_seg(f, &fh, xp);
! 1570:
! 1571: if (!shtext) {
! 1572:
! 1573: DEBUG(("load_region: unable to get shared text segment"));
! 1574:
! 1575: /* mint_errno set in get_text_seg */
! 1576:
! 1577: goto failed;
! 1578:
! 1579: }
! 1580:
! 1581: size = fh.fdata + fh.fbss;
! 1582:
! 1583: } else {
! 1584:
! 1585: size = fh.ftext + fh.fdata + fh.fbss;
! 1586:
! 1587: shtext = 0;
! 1588:
! 1589: }
! 1590:
! 1591:
1.1 root 1592:
1593: reg = 0;
1594:
1595: for (trycount = 0; (trycount < 1) && (reg == 0); trycount++) {
1596:
1597: reg = create_base(cmdlin, env, fh.flag, size);
1598:
1599: if (size+1024L > reg->len) {
1600:
1.1.1.2 ! root 1601: DEBUG(("load_region: insufficient memory to load"));
1.1 root 1602:
1603: detach_region(curproc, reg);
1604:
1605: reg = 0;
1606:
1607: }
1608:
1609: if (!reg) {
1610:
1611: /* maybe the memory shortage is short-term; sleep a bit to see */
1612:
1613: nap(10);
1614:
1615: }
1616:
1617: }
1618:
1619:
1620:
1621: if (reg == 0) {
1622:
1.1.1.2 ! root 1623: if (shtext) {
! 1624:
! 1625: detach_region(curproc, shtext);
! 1626:
! 1627: }
! 1628:
1.1 root 1629: mint_errno = ENSMEM;
1630:
1631: goto failed;
1632:
1633: }
1634:
1635:
1636:
1637: b = (BASEPAGE *)reg->loc;
1638:
1639: b->p_flags = fh.flag;
1640:
1.1.1.2 ! root 1641: if (shtext) {
! 1642:
! 1643: b->p_tbase = shtext->loc;
1.1 root 1644:
1.1.1.2 ! root 1645: b->p_tlen = 0;
1.1 root 1646:
1.1.1.2 ! root 1647: b->p_dbase = b->p_lowtpa + 256;
! 1648:
! 1649: } else {
! 1650:
! 1651: b->p_tbase = b->p_lowtpa + 256;
! 1652:
! 1653: b->p_tlen = fh.ftext;
! 1654:
! 1655: b->p_dbase = b->p_tbase + b->p_tlen;
! 1656:
! 1657: }
1.1 root 1658:
1659: b->p_dlen = fh.fdata;
1660:
1661: b->p_bbase = b->p_dbase + b->p_dlen;
1662:
1.1.1.2 ! root 1663: b->p_blen = fh.fbss;
1.1 root 1664:
1665:
1666:
1.1.1.2 ! root 1667: /* if shared text, then we start loading at the end of the
1.1 root 1668:
1.1.1.2 ! root 1669: * text region, since that is already set up
! 1670:
! 1671: */
! 1672:
! 1673: if (shtext) {
! 1674:
! 1675: /* skip over text info */
! 1676:
! 1677: size = fh.fdata;
! 1678:
! 1679: start = fh.ftext;
! 1680:
! 1681: } else {
! 1682:
! 1683: size = fh.ftext + fh.fdata;
! 1684:
! 1685: start = 0;
! 1686:
! 1687: }
! 1688:
! 1689:
! 1690:
! 1691: mint_errno = (int)load_and_reloc(f, &fh, (char *)b+256, start,
! 1692:
! 1693: size, b);
! 1694:
! 1695:
! 1696:
! 1697: if (mint_errno) {
1.1 root 1698:
1699: detach_region(curproc, reg);
1700:
1.1.1.2 ! root 1701: if (shtext) detach_region(curproc, shtext);
! 1702:
1.1 root 1703: goto failed;
1704:
1705: }
1706:
1707:
1708:
1709: if (fh.flag & F_FASTLOAD) /* fastload bit */
1710:
1711: size = b->p_blen;
1712:
1713: else
1714:
1715: size = b->p_hitpa - b->p_bbase;
1716:
1717: zero((char *)b->p_bbase, size);
1718:
1719:
1720:
1.1.1.2 ! root 1721: do_close(f);
1.1 root 1722:
1.1.1.2 ! root 1723: *text = shtext;
1.1 root 1724:
1.1.1.2 ! root 1725: return reg;
1.1 root 1726:
1.1.1.2 ! root 1727: }
! 1728:
! 1729:
! 1730:
! 1731: /*
! 1732:
! 1733: * load_and_reloc(f, fh, where, start, nbytes): load and relocate from
! 1734:
! 1735: * the open GEMDOS executable file f "nbytes" bytes starting at offset
! 1736:
! 1737: * "start" (relative to the end of the file header, i.e. from the first
! 1738:
! 1739: * byte of the actual program image in the file). "where" is the address
! 1740:
! 1741: * in (physical) memory into which the loaded image must be placed; it is
! 1742:
! 1743: * assumed that "where" is big enough to hold "nbytes" bytes!
1.1 root 1744:
1745: */
1746:
1747:
1748:
1.1.1.2 ! root 1749: long
! 1750:
! 1751: load_and_reloc(f, fh, where, start, nbytes, base)
! 1752:
! 1753: FILEPTR *f;
! 1754:
! 1755: FILEHEAD *fh;
! 1756:
! 1757: char *where;
! 1758:
! 1759: long start;
! 1760:
! 1761: long nbytes;
! 1762:
! 1763: BASEPAGE *base;
! 1764:
! 1765: {
! 1766:
! 1767: unsigned char c, *next;
! 1768:
! 1769: long r;
! 1770:
! 1771: DEVDRV *dev;
! 1772:
! 1773: #define LRBUFSIZ 8196
! 1774:
! 1775: static unsigned char buffer[LRBUFSIZ];
! 1776:
! 1777: long fixup, size, bytes_read;
! 1778:
! 1779: long reloc;
! 1780:
! 1781:
! 1782:
! 1783:
! 1784:
! 1785: TRACE(("load_and_reloc: %ld to %ld at %lx", start, nbytes+start, where));
! 1786:
! 1787: dev = f->dev;
! 1788:
! 1789:
! 1790:
! 1791: r = (*dev->lseek)(f, start+sizeof(FILEHEAD), SEEK_SET);
! 1792:
! 1793: if (r < 0) return r;
! 1794:
! 1795: r = (*dev->read)(f, where, nbytes);
! 1796:
! 1797: if (r != nbytes) {
! 1798:
! 1799: DEBUG(("load_region: unexpected EOF"));
! 1800:
! 1801: return ENOEXEC;
! 1802:
! 1803: }
! 1804:
! 1805:
! 1806:
! 1807: /* now do the relocation */
! 1808:
! 1809: /* skip over symbol table, etc. */
! 1810:
! 1811: r = (*dev->lseek)(f, sizeof(FILEHEAD) + fh->ftext + fh->fdata +
! 1812:
! 1813: fh->fsym, SEEK_SET);
! 1814:
! 1815: if (r < 0) return ENOEXEC;
! 1816:
! 1817:
! 1818:
! 1819: if (fh->reloc != 0 || (*dev->read)(f, (char *)&fixup, 4L) != 4L
! 1820:
! 1821: || fixup == 0) {
! 1822:
! 1823: return 0; /* no relocation to be performed */
! 1824:
! 1825: }
! 1826:
! 1827:
! 1828:
! 1829: size = LRBUFSIZ;
! 1830:
! 1831: bytes_read = 0;
! 1832:
! 1833: next = buffer;
! 1834:
1.1 root 1835:
1836:
1.1.1.2 ! root 1837: do {
! 1838:
! 1839: if (fixup >= nbytes + start) {
! 1840:
! 1841: TRACE(("load_region: end of relocation at %ld", fixup));
! 1842:
! 1843: break;
! 1844:
! 1845: }
! 1846:
! 1847: else if (fixup >= start) {
1.1 root 1848:
1.1.1.2 ! root 1849: reloc = *((long *)(where + fixup - start));
! 1850:
! 1851: if (reloc < fh->ftext) {
! 1852:
! 1853: reloc += base->p_tbase;
! 1854:
! 1855: } else if (reloc < fh->ftext + fh->fdata && base->p_dbase) {
! 1856:
! 1857: reloc += base->p_dbase - fh->ftext;
! 1858:
! 1859: } else if (reloc < fh->ftext + fh->fdata + fh->fbss && base->p_bbase) {
! 1860:
! 1861: reloc += base->p_bbase - (fh->ftext + fh->fdata);
! 1862:
! 1863: } else {
! 1864:
! 1865: DEBUG(("load_region: bad relocation: %ld", reloc));
! 1866:
! 1867: if (base->p_dbase)
! 1868:
! 1869: reloc += base->p_dbase - fh->ftext; /* assume data reloc */
! 1870:
! 1871: else if (base->p_bbase)
! 1872:
! 1873: reloc += base->p_bbase - (fh->ftext + fh->fdata);
! 1874:
! 1875: else
! 1876:
! 1877: return ENOEXEC;
! 1878:
! 1879: }
! 1880:
! 1881: *((long *)(where + fixup - start)) = reloc;
! 1882:
! 1883: }
1.1 root 1884:
1885: do {
1886:
1.1.1.2 ! root 1887: if (!bytes_read) {
1.1 root 1888:
1.1.1.2 ! root 1889: bytes_read =
1.1 root 1890:
1.1.1.2 ! root 1891: (*dev->read)(f,(char *)buffer,size);
! 1892:
! 1893: next = buffer;
1.1 root 1894:
1895: }
1896:
1.1.1.2 ! root 1897: if (bytes_read < 0) {
1.1 root 1898:
1.1.1.2 ! root 1899: DEBUG(("load_region: EOF in relocation"));
1.1 root 1900:
1.1.1.2 ! root 1901: return ENOEXEC;
1.1 root 1902:
1.1.1.2 ! root 1903: }
1.1 root 1904:
1.1.1.2 ! root 1905: else if (bytes_read == 0)
1.1 root 1906:
1.1.1.2 ! root 1907: c = 0;
1.1 root 1908:
1.1.1.2 ! root 1909: else {
1.1 root 1910:
1.1.1.2 ! root 1911: c = *next++; bytes_read--;
1.1 root 1912:
1.1.1.2 ! root 1913: }
1.1 root 1914:
1.1.1.2 ! root 1915: if (c == 1) fixup += 254;
1.1 root 1916:
1.1.1.2 ! root 1917: } while (c == 1);
1.1 root 1918:
1.1.1.2 ! root 1919: fixup += ( (unsigned) c) & 0xff;
1.1 root 1920:
1.1.1.2 ! root 1921: } while (c);
1.1 root 1922:
1923:
1924:
1.1.1.2 ! root 1925: return 0;
1.1 root 1926:
1.1.1.2 ! root 1927: }
! 1928:
! 1929:
! 1930:
! 1931: /*
! 1932:
! 1933: * function to check for existence of a shared text region
! 1934:
! 1935: * corresponding to file "f", and if none is found, to create one
! 1936:
! 1937: * the memory region being returned is attached to the current
! 1938:
! 1939: * process
! 1940:
! 1941: */
! 1942:
! 1943:
! 1944:
! 1945: MEMREGION *
! 1946:
! 1947: get_text_seg(f, fh, xp)
! 1948:
! 1949: FILEPTR *f;
! 1950:
! 1951: FILEHEAD *fh;
! 1952:
! 1953: XATTR *xp;
! 1954:
! 1955: {
! 1956:
! 1957: SHTEXT *s;
1.1 root 1958:
1.1.1.2 ! root 1959: MEMREGION *m;
! 1960:
! 1961: long r;
! 1962:
! 1963: BASEPAGE b;
! 1964:
! 1965:
! 1966:
! 1967: s = text_reg;
! 1968:
! 1969:
! 1970:
! 1971: while(s) {
! 1972:
! 1973: if (samefile(&f->fc, &s->f->fc) &&
! 1974:
! 1975: xp->mtime == s->mtime &&
! 1976:
! 1977: xp->mdate == s->mdate)
! 1978:
! 1979: {
1.1 root 1980:
1.1.1.2 ! root 1981: m = s->text;
1.1 root 1982:
1.1.1.2 ! root 1983: if (attach_region(curproc, m)) {
1.1 root 1984:
1.1.1.2 ! root 1985: TRACE(("re-using shared text region %lx", m));
! 1986:
! 1987: return m;
! 1988:
! 1989: }
! 1990:
! 1991: else {
! 1992:
! 1993: mint_errno = ENSMEM;
! 1994:
! 1995: return 0;
! 1996:
! 1997: }
! 1998:
! 1999: }
! 2000:
! 2001: s = s->next;
1.1 root 2002:
2003: }
2004:
2005:
2006:
1.1.1.2 ! root 2007: /* hmmm, not found; OK, we'll have to create a new text region */
! 2008:
! 2009:
! 2010:
! 2011: s = kmalloc(SIZEOF(SHTEXT));
! 2012:
! 2013: if (!s) {
! 2014:
! 2015: mint_errno = ENSMEM;
! 2016:
! 2017: return 0;
! 2018:
! 2019: }
! 2020:
! 2021: m = 0;
! 2022:
! 2023: /* actually, I can't see why loading in TT RAM is ever undesireable,
! 2024:
! 2025: * since shared text programs should be very clean (and since only
! 2026:
! 2027: * the text segment is going in there). But better safe than sorry.
! 2028:
! 2029: */
! 2030:
! 2031: if (fh->flag & F_ALTLOAD) {
! 2032:
! 2033: m = addr2mem(alloc_region(alt, fh->ftext));
! 2034:
! 2035: }
! 2036:
! 2037: if (!m)
! 2038:
! 2039: m = addr2mem(alloc_region(core, fh->ftext));
! 2040:
! 2041:
! 2042:
! 2043: if (!m) {
! 2044:
! 2045: kfree(s);
! 2046:
! 2047: mint_errno = ENSMEM;
! 2048:
! 2049: return 0;
! 2050:
! 2051: }
! 2052:
! 2053:
! 2054:
! 2055: /* set up a fake "basepage" for load_and_reloc
! 2056:
! 2057: * note: the 0 values should make load_and_reloc
! 2058:
! 2059: * barf on any attempts at data relocation, since we have
! 2060:
! 2061: * no data segment
! 2062:
! 2063: */
! 2064:
! 2065: TRACE(("attempting to create shared text region"));
! 2066:
! 2067:
! 2068:
! 2069: b.p_tbase = m->loc;
! 2070:
! 2071: b.p_tlen = fh->ftext;
! 2072:
! 2073: b.p_dbase = 0;
! 2074:
! 2075: b.p_dlen = 0;
! 2076:
! 2077: b.p_bbase = b.p_blen = 0;
! 2078:
1.1 root 2079:
1.1.1.2 ! root 2080:
! 2081: r = load_and_reloc(f, fh, (char *)m->loc, 0, fh->ftext, &b);
! 2082:
! 2083: if (r) {
! 2084:
! 2085: m->links = 0;
! 2086:
! 2087: detach_region(curproc, m);
! 2088:
! 2089: kfree(s);
! 2090:
! 2091: return 0;
! 2092:
! 2093: }
! 2094:
! 2095:
! 2096:
! 2097: /* region has valid shared text data */
! 2098:
! 2099: m->mflags |= M_SHTEXT;
! 2100:
! 2101:
! 2102:
! 2103: /*
! 2104:
! 2105: * KLUDGE: to make sure we always have up to date shared text
! 2106:
! 2107: * info, even across a network, we leave the file passed
! 2108:
! 2109: * to us open with DENYWRITE mode, so that nobody will
! 2110:
! 2111: * modify it.
! 2112:
! 2113: */
! 2114:
! 2115: f->links++; /* keep the file open longer */
! 2116:
! 2117:
! 2118:
! 2119: /* BUG: what if someone already has the file open for
! 2120:
! 2121: * writing? Then we could get screwed...
! 2122:
! 2123: */
! 2124:
! 2125: f->flags = (f->flags & ~O_SHMODE) | O_DENYW;
! 2126:
! 2127: s->f = f;
! 2128:
! 2129: s->text = m;
! 2130:
! 2131: s->next = text_reg;
! 2132:
! 2133: s->mtime = xp->mtime;
! 2134:
! 2135: s->mdate = xp->mdate;
! 2136:
! 2137: text_reg = s;
! 2138:
! 2139: TRACE(("shared text region %lx created", m));
! 2140:
! 2141: return m;
1.1 root 2142:
2143: }
2144:
2145:
2146:
2147: /*
2148:
2149: * exec_region(p, mem, thread): create a child process out of a mem region
2150:
2151: * "p" is the process structure set up by the parent; it may be "curproc",
2152:
2153: * if we're overlaying. "mem" is the loaded memory region returned by
2154:
2155: * "load region". Any open files (other than the standard handles) owned
2156:
2157: * by "p" are closed, and if thread !=0 all memory is released; the caller
2158:
2159: * must explicitly attach the environment and base region. The caller must
2160:
2161: * also put "p" on the appropriate queue (most likely READY_Q).
2162:
2163: */
2164:
2165:
2166:
2167: extern long mint_dos(), mint_bios();
2168:
2169:
2170:
2171: void rts() {} /* dummy termination routine */
2172:
2173:
2174:
2175: PROC *
2176:
2177: exec_region(p, mem, thread)
2178:
2179: PROC *p;
2180:
2181: MEMREGION *mem;
2182:
2183: int thread;
2184:
2185: {
2186:
2187: BASEPAGE *b;
2188:
2189: FILEPTR *f;
2190:
2191: int i;
2192:
2193: MEMREGION *m;
2194:
2195:
2196:
1.1.1.2 ! root 2197: TRACE(("exec_region"));
1.1 root 2198:
2199:
2200:
2201: b = (BASEPAGE *) mem->loc;
2202:
2203:
2204:
1.1.1.2 ! root 2205: cpush((void *)b->p_tbase, b->p_tlen); /* flush cached versions of the text */
! 2206:
! 2207:
! 2208:
1.1 root 2209: /* set some (undocumented) variables in the basepage */
2210:
2211: b->p_defdrv = p->curdrv;
2212:
2213: for (i = 0; i < 6; i++)
2214:
2215: b->p_devx[i] = i;
2216:
2217:
2218:
2219: p->dta = (DTABUF *)(b->p_dta = &b->p_cmdlin[0]);
2220:
2221: p->base = b;
2222:
2223:
2224:
2225: /* close extra open files */
2226:
2227: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
2228:
1.1.1.2 ! root 2229: if ( (f = p->handle[i]) != 0 && (p->fdflags[i] & FD_CLOEXEC) ) {
1.1 root 2230:
2231: do_pclose(p, f);
2232:
2233: p->handle[i] = 0;
2234:
2235: }
2236:
2237: }
2238:
2239:
2240:
2241: /* initialize memory */
2242:
2243: recalc_maxmem(p);
2244:
2245: if (p->maxmem) {
2246:
2247: shrink_region(mem, p->maxmem);
2248:
2249: b->p_hitpa = b->p_lowtpa + mem->len;
2250:
2251: }
2252:
2253:
2254:
2255: p->memflags = b->p_flags;
2256:
2257:
2258:
2259: if (!thread) {
2260:
2261: for (i = 0; i < p->num_reg; i++) {
2262:
2263: m = p->mem[i];
2264:
2265: if (m) {
2266:
2267: m->links--;
2268:
2269: if (m->links <= 0)
2270:
2271: free_region(m);
2272:
2273: }
2274:
2275: }
2276:
2277: if (p->num_reg > NUM_REGIONS) {
2278:
2279: kfree(p->mem); kfree(p->addr);
2280:
2281: p->mem = kmalloc(NUM_REGIONS * SIZEOF(MEMREGION *));
2282:
2283: p->addr = kmalloc(NUM_REGIONS * SIZEOF(virtaddr));
2284:
2285: /* note: the mallocs have succeeded, since we just freed bigger areas */
2286:
2287: assert(p->mem && p->addr);
2288:
2289: p->num_reg = NUM_REGIONS;
2290:
2291: }
2292:
2293: zero((char *)p->mem, (p->num_reg)*SIZEOF(MEMREGION *));
2294:
2295: zero((char *)p->addr, (p->num_reg)*SIZEOF(virtaddr));
2296:
2297: }
2298:
2299:
2300:
2301: /* initialize signals */
2302:
2303: p->sigmask = 0;
2304:
2305: for (i = 0; i < NSIG; i++) {
2306:
2307: if (p->sighandle[i] != SIG_IGN) {
2308:
2309: p->sighandle[i] = SIG_DFL;
2310:
2311: p->sigflags[i] = 0;
2312:
2313: p->sigextra[i] = 0;
2314:
2315: }
2316:
2317: }
2318:
2319:
2320:
2321: /* zero the user registers, and set the FPU in a "clear" state */
2322:
2323: for (i = 0; i < 15; i++)
2324:
2325: p->ctxt[CURRENT].regs[i] = 0;
2326:
2327: p->ctxt[CURRENT].sr = 0;
2328:
2329: p->ctxt[CURRENT].fstate[0] = 0;
2330:
2331:
2332:
2333: /* set PC, stack registers, etc. appropriately */
2334:
2335: p->ctxt[CURRENT].pc = b->p_tbase;
2336:
2337:
2338:
2339: /* The "-0x20" is to make sure that syscall.s won't run past the end of
2340:
2341: * memory when the user makes a system call and doesn't push very many
2342:
2343: * parameters -- syscall always tries to copy the maximum possible number
2344:
2345: * of parms.
2346:
2347: *
2348:
2349: * NOTE: there's a sanity check here in case programs Mshrink a basepage
2350:
2351: * without fixing the p_hitpa field in the basepage; this is to ensure
2352:
2353: * compatibility with older versions of MiNT, which ignore p_hitpa.
2354:
2355: */
2356:
2357: if (valid_address(b->p_hitpa - 0x20))
2358:
2359: p->ctxt[CURRENT].usp = b->p_hitpa - 0x20;
2360:
2361: else
2362:
2363: p->ctxt[CURRENT].usp = mem->loc + mem->len - 0x20;
2364:
2365:
2366:
2367: p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
2368:
2369: p->ctxt[CURRENT].term_vec = (long)rts;
2370:
2371:
2372:
2373: /* set up stack for process */
2374:
2375: *((long *)(p->ctxt[CURRENT].usp + 4)) = (long) b;
2376:
2377:
2378:
2379: /* check for a valid text region. some compilers (e.g. Lattice 3) just throw
2380:
2381: everything into the text region, including data; fork() must be careful
2382:
2383: to save the whole region, then. We assume that if the compiler (or
2384:
2385: assembler, or whatever) goes to the trouble of making separate text, data,
2386:
2387: and bss regions, then the text region is code and isn't modified and
2388:
2389: fork doesn't have to save it.
2390:
2391: */
2392:
1.1.1.2 ! root 2393: if (b->p_blen != 0 || b->p_dlen != 0)
1.1 root 2394:
2395: p->txtsize = b->p_tlen;
2396:
2397: else
2398:
2399: p->txtsize = 0;
2400:
2401:
2402:
2403: /*
2404:
2405: * An ugly hack: dLibs tries to poke around in the parent's address space
2406:
2407: * to find stuff. For now, we'll allow this by faking a pointer into
2408:
2409: * the parent's address space in the place in the basepage where dLibs is
2410:
2411: * expecting it. This ugly hack only works correctly if the Pexec'ing
2412:
2413: * program (i.e. curproc) is in user mode.
2414:
2415: */
2416:
1.1.1.2 ! root 2417: if (curproc != rootproc)
! 2418:
! 2419: curproc->base->p_usp = curproc->ctxt[SYSCALL].usp - 0x32;
1.1 root 2420:
2421:
2422:
2423: return p;
2424:
2425: }
2426:
2427:
2428:
2429: /*
2430:
2431: * misc. utility routines
2432:
2433: */
2434:
2435:
2436:
2437: /*
2438:
2439: * long memused(p): return total memory allocated to process p
2440:
2441: */
2442:
2443:
2444:
2445: long
2446:
2447: memused(p)
2448:
2449: PROC *p;
2450:
2451: {
2452:
2453: int i;
2454:
2455: long size;
2456:
2457:
2458:
2459: size = 0;
2460:
2461: for (i = 0; i < p->num_reg; i++) {
2462:
2463: if (p->mem[i])
2464:
2465: size += p->mem[i]->len;
2466:
2467: }
2468:
2469: return size;
2470:
2471: }
2472:
2473:
2474:
2475: /*
2476:
2477: * recalculate the maximum memory limit on a process; this limit depends
2478:
2479: * on the max. allocated memory and max. total memory limits set by
2480:
2481: * p_setlimit (see dos.c), and (perhaps) on the size of the program
2482:
2483: * that the process is executing. whenever any of these things
2484:
2485: * change (through p_exec or p_setlimit) this routine must be called
2486:
2487: */
2488:
2489:
2490:
2491: void
2492:
2493: recalc_maxmem(p)
2494:
2495: PROC *p;
2496:
2497: {
2498:
2499: BASEPAGE *b;
2500:
2501: long siz;
2502:
2503:
2504:
2505: b = (BASEPAGE *)p->base;
2506:
2507: if (b)
2508:
2509: siz = b->p_tlen + b->p_dlen + b->p_blen;
2510:
2511: else
2512:
2513: siz = 0;
2514:
2515: p->maxmem = 0;
2516:
2517: if (p->maxdata) {
2518:
2519: p->maxmem = p->maxdata + siz;
2520:
2521: }
2522:
2523:
2524:
2525: if (p->maxcore) {
2526:
2527: if (p->maxmem == 0 || p->maxmem > p->maxcore)
2528:
2529: p->maxmem = p->maxcore;
2530:
2531: }
2532:
2533: if (p->maxmem && p->maxmem < siz)
2534:
2535: p->maxmem = siz;
2536:
2537: }
2538:
2539:
2540:
2541: /*
2542:
2543: * valid_address: checks to see if the indicated address falls within
2544:
2545: * memory attached to the current process
2546:
2547: */
2548:
2549:
2550:
2551: int
2552:
2553: valid_address(addr)
2554:
2555: long addr;
2556:
2557: {
2558:
2559: int i;
2560:
2561: MEMREGION *m;
2562:
2563:
2564:
2565: for (i = 0; i < curproc->num_reg; i++) {
2566:
2567: if ((m = curproc->mem[i]) != 0) {
2568:
2569: if (addr >= m->loc && addr <= m->loc + m->len)
2570:
2571: return 1;
2572:
2573: }
2574:
2575: }
2576:
2577: return 0;
2578:
2579: }
2580:
2581:
2582:
2583: /*
2584:
2585: * some debugging stuff
2586:
2587: */
2588:
2589:
2590:
2591: void
2592:
2593: DUMPMEM(map)
2594:
2595: MMAP map;
2596:
2597: {
2598:
1.1.1.2 ! root 2599: #ifndef NO_DEBUG_INFO
! 2600:
1.1 root 2601: MEMREGION *m;
2602:
2603:
2604:
2605: m = *map;
2606:
2607: ALERT("memory dump: starting at region %lx", m);
2608:
2609: while (m) {
2610:
2611: ALERT("%ld bytes at %lx (%d links); next region %lx", m->len, m->loc,
2612:
2613: m->links, m->next);
2614:
2615: m = m->next;
2616:
2617: }
2618:
1.1.1.2 ! root 2619: #endif
! 2620:
1.1 root 2621: }
2622:
2623:
2624:
2625: void
2626:
2627: sanity_check(map)
2628:
2629: MMAP map;
2630:
2631: {
2632:
2633: #ifdef SANITY_CHECK
2634:
2635: MEMREGION *m, *nxt;
2636:
2637: long end;
2638:
2639:
2640:
2641: m = *map;
2642:
2643: while (m) {
2644:
2645: nxt = m->next;
2646:
2647: if (nxt) {
2648:
2649: end = m->loc + m->len;
2650:
2651: if (m->loc < nxt->loc && end > nxt->loc) {
2652:
2653: FATAL("MEMORY CHAIN CORRUPTED");
2654:
2655: }
2656:
2657: else if (end == nxt->loc && ISFREE(m) && ISFREE(nxt)) {
2658:
2659: ALERT("Continguous memory regions not merged!");
2660:
2661: }
2662:
2663: }
2664:
2665: m = nxt;
2666:
2667: }
2668:
1.1.1.2 ! root 2669: #else
! 2670:
! 2671: UNUSED(map);
! 2672:
1.1 root 2673: #endif
2674:
2675: }
2676:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.