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