|
|
1.1 ! root 1: /* $Header: /newbits/286_KERNEL/USRSRC/coh/RCS/seg.c,v 1.1 92/01/09 13:29:05 bin Exp Locker: bin $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * Segment manipulation. ! 18: * ! 19: * $Log: seg.c,v $ ! 20: * Revision 1.1 92/01/09 13:29:05 bin ! 21: * Initial revision ! 22: * ! 23: * Revision 1.1 88/03/24 16:14:20 src ! 24: * Initial revision ! 25: * ! 26: * 88/02/26 Allan Cornish /usr/src/sys/coh/seg.c ! 27: * swapio() now avoids 64 Kbyte page [dma] straddles. ! 28: * ! 29: * 88/01/22 Allan Cornish /usr/src/sys/coh/seg.c ! 30: * salloc() now invokes krunch(1000) if initial allocation fails. ! 31: * sfree() now invokes krunch(0). ! 32: * ! 33: * 88/01/21 Allan Cornish /usr/src/sys/coh/seg.c ! 34: * sfree() modified to eliminate critical race on ref cnts and segment gate. ! 35: * segfinm() now properly maintains segment reference counts. ! 36: * ! 37: * 87/11/13 Allan Cornish /usr/src/sys/coh/seg.c ! 38: * Support for protected mode segmentation added. ! 39: */ ! 40: #include <sys/coherent.h> ! 41: #include <sys/buf.h> ! 42: #include <errno.h> ! 43: #include <sys/ino.h> ! 44: #include <sys/inode.h> ! 45: #include <sys/proc.h> ! 46: #include <sys/sched.h> ! 47: #include <sys/seg.h> ! 48: #include <sys/uproc.h> ! 49: ! 50: /* ! 51: * Initialisation code. ! 52: */ ! 53: seginit() ! 54: { ! 55: /* ! 56: * Create empty circular-list of memory segments. ! 57: */ ! 58: segmq.s_forw = &segmq; ! 59: segmq.s_back = &segmq; ! 60: ! 61: /* ! 62: * Create empty circular-list of disk segments. ! 63: */ ! 64: segdq.s_forw = &segdq; ! 65: segdq.s_back = &segdq; ! 66: ! 67: if ( holebot != holetop ) { ! 68: /* ! 69: * Define the I/O mem hole between low memory and extended mem. ! 70: * NOTE: Setting lrefc to urefc+1 stopx segment from moving. ! 71: */ ! 72: segiom.s_paddr = holebot; ! 73: segiom.s_size = holetop - holebot; ! 74: segiom.s_flags = SFCORE | SFSYST; ! 75: segiom.s_urefc = 1; ! 76: segiom.s_lrefc = 2; ! 77: ! 78: /* ! 79: * Insert I/O memory segment into memory list. ! 80: */ ! 81: segiom.s_forw = &segmq; ! 82: segiom.s_back = &segmq; ! 83: segmq.s_forw = &segiom; ! 84: segmq.s_back = &segiom; ! 85: } ! 86: } ! 87: ! 88: /* ! 89: * Given an inode, `ip', and flags, `ff', describing a segment associated ! 90: * with the inode, see if the segment already exists and if so, return a ! 91: * copy. If the segment does not exists, allocate the segment having size ! 92: * `ss', and read the segment using the inode at seek offset `dq' with a ! 93: * size of `ds'. ! 94: */ ! 95: SEG * ! 96: ssalloc(rp, ip, ff, ss, dq, ds) ! 97: int *rp; ! 98: register INODE *ip; ! 99: fsize_t ss; ! 100: fsize_t dq; ! 101: fsize_t ds; ! 102: { ! 103: register SEG *sp; ! 104: register int f; ! 105: ! 106: *rp = -1; ! 107: if (ss == 0) { ! 108: *rp = 1; ! 109: return (NULL); ! 110: } ! 111: lock(seglink); ! 112: f = ff & (SFSHRX|SFTEXT); ! 113: ! 114: /* ! 115: * Look for the segment in the memory queue. ! 116: */ ! 117: for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) { ! 118: if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) { ! 119: unlock(seglink); ! 120: if ((sp = segdupl(sp)) != NULL) { ! 121: segfinm(sp); ! 122: *rp = 1; ! 123: } ! 124: return (sp); ! 125: } ! 126: } ! 127: ! 128: /* ! 129: * Look for the segment on the disk queue. ! 130: */ ! 131: for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) { ! 132: if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) { ! 133: unlock(seglink); ! 134: if ((sp = segdupl(sp)) != NULL) { ! 135: segfinm(sp); ! 136: *rp = 1; ! 137: } ! 138: return (sp); ! 139: } ! 140: } ! 141: unlock(seglink); ! 142: ! 143: /* ! 144: * Allocate and create the segment. ! 145: */ ! 146: if ((sp=salloc(ss, ff)) == NULL) ! 147: return (NULL); ! 148: if (exsread(sp, ip, ds, dq, (fsize_t)0) == 0) { ! 149: sfree(sp); ! 150: return (NULL); ! 151: } ! 152: if ((ff&SFSHRX) != 0) { ! 153: sp->s_ip = ip; ! 154: ip->i_refc++; ! 155: } ! 156: *rp = 0; ! 157: return (sp); ! 158: } ! 159: ! 160: /* ! 161: * Given a pointer to a newly created process, copy all of our segments ! 162: * into the given process. ! 163: */ ! 164: segadup(cpp) ! 165: register PROC *cpp; ! 166: { ! 167: register SEG *sp; ! 168: register int n; ! 169: register PROC *pp; ! 170: ! 171: pp = SELF; ! 172: cpp->p_flags |= PFSWIO; ! 173: for (n=0; n<NUSEG; n++) { ! 174: if ((sp=pp->p_segp[n]) == NULL) ! 175: continue; ! 176: if ((sp=segdupl(sp)) == NULL) ! 177: break; ! 178: cpp->p_segp[n] = sp; ! 179: if ((sp->s_flags&SFCORE) == 0) ! 180: cpp->p_flags &= ~PFCORE; ! 181: } ! 182: if (n < NUSEG) { ! 183: while (n > 0) { ! 184: if ((sp=cpp->p_segp[--n]) != NULL) { ! 185: cpp->p_segp[n] = NULL; ! 186: sfree(sp); ! 187: } ! 188: } ! 189: } ! 190: cpp->p_flags &= ~PFSWIO; ! 191: return (n); ! 192: } ! 193: ! 194: /* ! 195: * Duplicate a segment. ! 196: */ ! 197: SEG * ! 198: segdupl(sp) ! 199: register SEG *sp; ! 200: { ! 201: register SEG *sp1; ! 202: ! 203: if ((sp->s_flags&SFSHRX) != 0) { ! 204: sp->s_urefc++; ! 205: sp->s_lrefc++; ! 206: return (sp); ! 207: } ! 208: if ((sp->s_flags&SFCORE) == 0) ! 209: panic("Cannot duplicate non shared swapped segment"); ! 210: if ((sp1=salloc(sp->s_size, sp->s_flags|SFNSWP|SFNCLR)) == NULL) ! 211: sp1 = segdupd(sp); ! 212: else { ! 213: sp1->s_flags = sp->s_flags; ! 214: plrcopy( sp->s_paddr, sp1->s_paddr, sp->s_size ); ! 215: } ! 216: return (sp1); ! 217: } ! 218: ! 219: /* ! 220: * Allocate a segment `n' bytes long. `f' contains some pseudo flags. ! 221: */ ! 222: SEG * ! 223: salloc(n, f) ! 224: fsize_t n; ! 225: { ! 226: register SEG *sp; ! 227: register int r; ! 228: ! 229: r = (f&(SFSYST|SFHIGH|SFTEXT|SFSHRX|SFDOWN)) | SFCORE; ! 230: n += (BSIZE-1); ! 231: n &= ~(BSIZE-1); ! 232: ! 233: lock(seglink); ! 234: sp = sxalloc(n, f); ! 235: unlock(seglink); ! 236: ! 237: if ( sp == NULL ) { ! 238: krunch(1000); ! 239: lock(seglink); ! 240: sp = sxalloc(n, f); ! 241: unlock(seglink); ! 242: } ! 243: ! 244: if (sp != NULL) { ! 245: sp->s_flags = r; ! 246: vremap( sp ); ! 247: } ! 248: else { ! 249: if ((f&SFNSWP) != 0) ! 250: return (NULL); ! 251: if ((sp=kalloc(sizeof(SEG))) == NULL) ! 252: return (NULL); ! 253: sp->s_forw = sp; ! 254: sp->s_back = sp; ! 255: sp->s_flags = r; ! 256: sp->s_urefc = 1; ! 257: sp->s_lrefc = 1; ! 258: if (segsext(sp, n) == NULL) { ! 259: kfree(sp); ! 260: return (NULL); ! 261: } ! 262: } ! 263: if ((f&SFNCLR) == 0) ! 264: pclear( sp->s_paddr, n ); ! 265: return (sp); ! 266: } ! 267: ! 268: /* ! 269: * Free the given segment pointer. ! 270: */ ! 271: sfree(sp) ! 272: register SEG *sp; ! 273: { ! 274: register INODE *ip; ! 275: ! 276: if ( sp->s_urefc != 1 ) { ! 277: sp->s_urefc--; ! 278: sp->s_lrefc--; ! 279: return; ! 280: } ! 281: ! 282: lock(seglink); ! 283: --sp->s_lrefc; ! 284: if (--sp->s_urefc != 0) { ! 285: unlock(seglink); ! 286: return; ! 287: } ! 288: ! 289: sp->s_back->s_forw = sp->s_forw; ! 290: sp->s_forw->s_back = sp->s_back; ! 291: unlock(seglink); ! 292: ! 293: if (sp->s_lrefc != 0) ! 294: panic("Bad segment count"); ! 295: if ((ip=sp->s_ip) != NULL) ! 296: ldetach(ip); ! 297: vrelse( sp->s_faddr ); ! 298: kfree(sp); ! 299: krunch(0); ! 300: } ! 301: ! 302: /* ! 303: * Grow or shrink the segment `sp' so that it has size `n'. ! 304: */ ! 305: seggrow(sp, n) ! 306: register SEG *sp; ! 307: fsize_t n; ! 308: { ! 309: register SEG *sp1; ! 310: register fsize_t d; ! 311: register paddr_t pb; ! 312: register paddr_t nb; ! 313: register int dowflag; ! 314: ! 315: dowflag = sp->s_flags&SFDOWN; ! 316: ! 317: /* ! 318: * Size of new segment is smaller or the same size as the old ! 319: * segment. ! 320: */ ! 321: lock(seglink); ! 322: d = n - sp->s_size; ! 323: if (n <= sp->s_size) { ! 324: sp->s_size = n; ! 325: if (dowflag) ! 326: sp->s_paddr -= d; ! 327: ! 328: vremap( sp ); ! 329: unlock(seglink); ! 330: return (1); ! 331: } ! 332: ! 333: if ((sp1=sp->s_back) == &segmq) ! 334: pb = corebot; ! 335: else ! 336: pb = sp1->s_paddr + sp1->s_size; ! 337: ! 338: if ((sp1=sp->s_forw) == &segmq) ! 339: nb = coretop; ! 340: else ! 341: nb = sp1->s_paddr; ! 342: ! 343: /* ! 344: * If the segment does not grow down, see if there is enough ! 345: * space after the segment. ! 346: */ ! 347: if (dowflag==0 && nb-sp->s_paddr>=n) { ! 348: pclear(sp->s_paddr+sp->s_size, d); ! 349: sp->s_size = n; ! 350: vremap( sp ); ! 351: unlock(seglink); ! 352: return (1); ! 353: } ! 354: ! 355: /* ! 356: * If the segment grows down, see if there is enough space ! 357: * before the segment. ! 358: */ ! 359: if (dowflag!=0 && sp->s_paddr+sp->s_size-pb>=n) { ! 360: sp->s_paddr -= d; ! 361: sp->s_size = n; ! 362: pclear( sp->s_paddr, d ); ! 363: vremap( sp ); ! 364: unlock(seglink); ! 365: return (1); ! 366: } ! 367: ! 368: /* ! 369: * Is there enough space in total counting the gaps on either ! 370: * side of us? ! 371: */ ! 372: if (nb-pb >= n) { ! 373: if (dowflag == 0) { ! 374: plrcopy(sp->s_paddr, pb, sp->s_size); ! 375: pclear(pb+sp->s_size, d); ! 376: sp->s_paddr = pb; ! 377: } else { ! 378: prlcopy( sp->s_paddr, nb-sp->s_size, sp->s_size ); ! 379: pclear(nb-n, d); ! 380: sp->s_paddr = nb-n; ! 381: } ! 382: sp->s_size = n; ! 383: vremap( sp ); ! 384: unlock(seglink); ! 385: return (1); ! 386: } ! 387: ! 388: /* ! 389: * Try to allocate a segment somewhere else on the segment queue ! 390: * and copy ourselves there. ! 391: */ ! 392: unlock(seglink); ! 393: if ((sp1=salloc((fsize_t)n, sp->s_flags|SFNSWP|SFNCLR)) != NULL) { ! 394: if (dowflag == 0) { ! 395: plrcopy(sp->s_paddr, sp1->s_paddr, sp->s_size); ! 396: pclear(sp1->s_paddr+sp->s_size, d); ! 397: } else { ! 398: plrcopy(sp->s_paddr, sp1->s_paddr+d, sp->s_size); ! 399: pclear(sp1->s_paddr, d); ! 400: } ! 401: lock(seglink); ! 402: satcopy(sp, sp1); ! 403: unlock(seglink); ! 404: return (1); ! 405: } ! 406: ! 407: /* ! 408: * Last chance. Extend the segment by swapping it. ! 409: */ ! 410: if (segsext(sp, n) != NULL) { ! 411: if (dowflag == 0) ! 412: pclear(sp->s_paddr+n-d, d); ! 413: else { ! 414: prlcopy(sp->s_paddr, sp->s_paddr+d, n-d); ! 415: pclear(sp->s_paddr, d); ! 416: } ! 417: return (1); ! 418: } ! 419: ! 420: /* ! 421: * At least we tried. ! 422: */ ! 423: return (0); ! 424: } ! 425: ! 426: /* ! 427: * Given a segment pointer, `sp' and a segment size, grow the given segment ! 428: * to the given size. ! 429: */ ! 430: segsize(sp, s2) ! 431: register SEG *sp; ! 432: vaddr_t s2; ! 433: { ! 434: register vaddr_t s1; ! 435: ! 436: s1 = (vaddr_t) sp->s_size; ! 437: if (seggrow(sp, (fsize_t)s2) == 0) { ! 438: u.u_error = ENOMEM; ! 439: return; ! 440: } ! 441: if (sproto() == 0) ! 442: if (seggrow(sp, (fsize_t)s1)==0 || sproto()==0) ! 443: sendsig(SIGSEGV, SELF); ! 444: segload(); ! 445: } ! 446: ! 447: /* ! 448: * Grow the segment `sp1' to the size `s' in bytes by swapping it out ! 449: * and back in. The segment may not be locked. ! 450: */ ! 451: SEG * ! 452: segsext(sp1, s) ! 453: register SEG *sp1; ! 454: register fsize_t s; ! 455: { ! 456: register SEG *sp2; ! 457: ! 458: #ifndef NOMONITOR ! 459: if (swmflag) ! 460: printf("Segsext(%p, %u)\n", SELF, SELF->p_pid); ! 461: #endif ! 462: if (sexflag == 0) { ! 463: u.u_error = ENOMEM; ! 464: return (NULL); ! 465: } ! 466: lock(seglink); ! 467: if ((sp2=sdalloc(s)) == NULL) { ! 468: unlock(seglink); ! 469: return (NULL); ! 470: } ! 471: unlock(seglink); ! 472: sp1->s_lrefc++; ! 473: if (sp1->s_size != 0) ! 474: swapio(1, sp1->s_paddr, sp2->s_daddr, sp1->s_size); ! 475: lock(seglink); ! 476: satcopy(sp1, sp2); ! 477: unlock(seglink); ! 478: sp1->s_flags &= ~SFCORE; ! 479: sp1->s_lrefc--; ! 480: vremap(sp1); ! 481: segfinm(sp1); ! 482: return (sp1); ! 483: } ! 484: ! 485: /* ! 486: * Force the given segment to be in memory. One can only force ! 487: * one segment to be in memory at a time. ! 488: */ ! 489: segfinm(sp) ! 490: register SEG *sp; ! 491: { ! 492: register PROC *pp; ! 493: register int s; ! 494: ! 495: if ((sp->s_flags&SFCORE) != 0) ! 496: return; ! 497: pp = SELF; ! 498: sp->s_urefc++; ! 499: sp->s_lrefc++; ! 500: pp->p_segp[SIAUXIL] = sp; ! 501: pp->p_flags &= ~PFCORE; ! 502: #ifndef QWAKEUP ! 503: s = sphi(); ! 504: #endif ! 505: setrun(pp); ! 506: dispatch(); ! 507: #ifndef QWAKEUP ! 508: spl(s); ! 509: #endif ! 510: pp->p_segp[SIAUXIL] = NULL; ! 511: sfree(sp); ! 512: } ! 513: ! 514: /* ! 515: * Make a copy of the segment `sp1' which is in memory by writing ! 516: * it out to disk. ! 517: */ ! 518: SEG * ! 519: segdupd(sp1) ! 520: register SEG *sp1; ! 521: { ! 522: register SEG *sp2; ! 523: ! 524: if (sexflag == 0) ! 525: return (NULL); ! 526: lock(seglink); ! 527: if ((sp2=sdalloc(sp1->s_size)) == NULL) { ! 528: unlock(seglink); ! 529: return (NULL); ! 530: } ! 531: sp1->s_lrefc++; ! 532: unlock(seglink); ! 533: swapio(1, sp1->s_paddr, sp2->s_daddr, sp1->s_size); ! 534: sp1->s_lrefc--; ! 535: sp2->s_flags = sp1->s_flags & ~SFCORE; ! 536: sp2->s_size = sp1->s_size; ! 537: vremap( sp2 ); ! 538: return (sp2); ! 539: } ! 540: ! 541: /* ! 542: * Given a flag, a physical core address, a disk address and a count in ! 543: * bytes, perform an I/O operation between core and disk. If `flag' is ! 544: * set, the transfer is to the disk otherwise it is to memory. As you may ! 545: * have guessed, this is used by the swapper. ! 546: */ ! 547: swapio(f, p, d, n) ! 548: paddr_t p; ! 549: daddr_t d; ! 550: fsize_t n; ! 551: { ! 552: register BUF * bp; ! 553: register SEG * sp; ! 554: register int s; ! 555: register int nb; ! 556: static SEG swapseg; /* NOTE: FP_SEL(swapseg.s_faddr) must stay */ ! 557: ! 558: #ifndef NOMONITOR ! 559: if (swmflag > 1) ! 560: printf("swapio(%s,%x,%x,%x)\n",f?"out":"in",(int)p,(int)d,n); ! 561: #endif ! 562: if (d < swapbot || d+(n/BSIZE) > swaptop ! 563: || p < corebot || p+n > coretop) ! 564: panic("Swapio bad parameter"); ! 565: ! 566: bp = &swapbuf; ! 567: sp = &swapseg; ! 568: lock(bp->b_gate); ! 569: SELF->p_flags |= PFSWIO; ! 570: sp->s_flags = SFCORE; ! 571: sp->s_paddr = p; ! 572: sp->s_size = n; ! 573: vremap( sp ); ! 574: bp->b_faddr = sp->s_faddr; ! 575: ! 576: while (n != 0) { ! 577: nb = (n > SCHUNK) ? SCHUNK : n; ! 578: /* ! 579: * Prevent I/O transfer from crossing 64 Kbyte boundary. ! 580: */ ! 581: if ( (p & 0xFFFF0000L) != ((p+nb) & 0xFFFF0000L) ) ! 582: nb = 0x10000L - (p & 0x0000FFFFL); ! 583: bp->b_flag = BFNTP; ! 584: bp->b_req = f ? BWRITE : BREAD; ! 585: bp->b_dev = swapdev; ! 586: bp->b_bno = d; ! 587: bp->b_paddr = p; ! 588: bp->b_count = nb; ! 589: s = sphi(); ! 590: dblock(swapdev, bp); ! 591: while ((bp->b_flag&BFNTP) != 0) ! 592: sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO); ! 593: spl(s); ! 594: if ((bp->b_flag&BFERR) != 0) ! 595: panic("Swapio error"); ! 596: FP_OFF(bp->b_faddr) += nb; ! 597: p += nb; ! 598: d += nb / BSIZE; ! 599: n -= nb; ! 600: } ! 601: sp->s_flags = 0; ! 602: vremap( sp ); ! 603: unlock(bp->b_gate); ! 604: SELF->p_flags &= ~PFSWIO; ! 605: } ! 606: ! 607: /* ! 608: * Make the segment descriptor pointed to by `sp1' have the attributes ! 609: * of `sp2' including it's position in the segment queue and release ! 610: * `sp2'. `seglink' must be locked when this routine is called. ! 611: */ ! 612: satcopy(sp1, sp2) ! 613: register SEG *sp1; ! 614: register SEG *sp2; ! 615: { ! 616: if ( FP_SEL(sp2->s_faddr) != 0 ) ! 617: vrelse( sp2->s_faddr ); ! 618: ! 619: sp1->s_back->s_forw = sp1->s_forw; ! 620: sp1->s_forw->s_back = sp1->s_back; ! 621: sp2->s_back->s_forw = sp1; ! 622: sp1->s_back = sp2->s_back; ! 623: sp2->s_forw->s_back = sp1; ! 624: sp1->s_forw = sp2->s_forw; ! 625: sp1->s_size = sp2->s_size; ! 626: sp1->s_paddr = sp2->s_paddr; ! 627: sp1->s_daddr = sp2->s_daddr; ! 628: vremap(sp1); ! 629: kfree(sp2); ! 630: } ! 631: ! 632: /* ! 633: * Allocate a segment on disk that is `n' bytes long. ! 634: * The `seglink' gate should be locked before this routine is called. ! 635: */ ! 636: SEG * ! 637: sdalloc( s ) ! 638: fsize_t s; ! 639: { ! 640: register SEG *sp1; ! 641: register SEG *sp2; ! 642: register daddr_t d; ! 643: register daddr_t d1; ! 644: register daddr_t d2; ! 645: ! 646: d = s / BSIZE; ! 647: d1 = swapbot; ! 648: sp1 = &segdq; ! 649: do { ! 650: if (d1 >= swaptop) ! 651: return (NULL); ! 652: if ((sp1=sp1->s_forw) != &segdq) ! 653: d2 = sp1->s_daddr; ! 654: else ! 655: d2 = swaptop; ! 656: if (d2-d1 >= d) { ! 657: if ((sp2=kalloc(sizeof(SEG))) == NULL) ! 658: return (NULL); ! 659: sp1->s_back->s_forw = sp2; ! 660: sp2->s_back = sp1->s_back; ! 661: sp1->s_back = sp2; ! 662: sp2->s_forw = sp1; ! 663: sp2->s_urefc = 1; ! 664: sp2->s_lrefc = 1; ! 665: sp2->s_size = s; ! 666: sp2->s_daddr = d1; ! 667: return (sp2); ! 668: } ! 669: d1 = sp1->s_daddr + (sp1->s_size / BSIZE); ! 670: } while (sp1 != &segdq); ! 671: return (NULL); ! 672: } ! 673: ! 674: /* ! 675: * Allocate a segment in memory that is `n' bytes long. ! 676: * The `seglink' gate should be locked before this routine is called. ! 677: */ ! 678: SEG * ! 679: smalloc(s) ! 680: fsize_t s; ! 681: { ! 682: register SEG *sp1; ! 683: register SEG *sp2; ! 684: paddr_t p1; ! 685: paddr_t p2; ! 686: ! 687: p1 = corebot; ! 688: sp1 = &segmq; ! 689: do { ! 690: if ((sp1=sp1->s_forw) != &segmq) ! 691: p2 = sp1->s_paddr; ! 692: else ! 693: p2 = coretop; ! 694: ! 695: if (p2-p1 >= s) { ! 696: if ((sp2=kalloc(sizeof (SEG))) == NULL) ! 697: return (NULL); ! 698: sp1->s_back->s_forw = sp2; ! 699: sp2->s_back = sp1->s_back; ! 700: sp1->s_back = sp2; ! 701: sp2->s_forw = sp1; ! 702: sp2->s_urefc = 1; ! 703: sp2->s_lrefc = 1; ! 704: sp2->s_size = s; ! 705: sp2->s_paddr = p1; ! 706: /* s_faddr = 0; */ ! 707: /* s_flags = 0; */ ! 708: vremap( sp2 ); ! 709: return (sp2); ! 710: } ! 711: p1 = sp1->s_paddr + sp1->s_size; ! 712: } while (sp1 != &segmq); ! 713: return (NULL); ! 714: } ! 715: ! 716: /* ! 717: * Allocate a segment from the high end of memory that is `n' bytes long. ! 718: * The `seglink' gate should be locked before this routine is called. ! 719: */ ! 720: SEG * ! 721: shalloc( s ) ! 722: fsize_t s; ! 723: { ! 724: register SEG *sp1; ! 725: register SEG *sp2; ! 726: paddr_t p1; ! 727: paddr_t p2; ! 728: ! 729: sp1 = &segmq; ! 730: p2 = coretop; ! 731: do { ! 732: if ((sp1=sp1->s_back) != &segmq) ! 733: p1 = sp1->s_paddr + sp1->s_size; ! 734: else ! 735: p1 = corebot; ! 736: ! 737: if (p2-p1 >= s) { ! 738: if ((sp2=kalloc(sizeof (SEG))) == NULL) ! 739: return (NULL); ! 740: sp1->s_forw->s_back = sp2; ! 741: sp2->s_forw = sp1->s_forw; ! 742: sp1->s_forw = sp2; ! 743: sp2->s_back = sp1; ! 744: sp2->s_urefc = 1; ! 745: sp2->s_lrefc = 1; ! 746: sp2->s_size = s; ! 747: sp2->s_paddr = p2-s; ! 748: /* s_faddr = 0; */ ! 749: /* s_flags = 0; */ ! 750: vremap( sp2 ); ! 751: return (sp2); ! 752: } ! 753: p2 = sp1->s_paddr; ! 754: } while (sp1 != &segmq); ! 755: return (NULL); ! 756: } ! 757: ! 758: /* ! 759: * Set up `SR' structure in user area from segments descriptors in ! 760: * process structure. Also set up the user segmentation registers. ! 761: */ ! 762: sproto() ! 763: { ! 764: register int n; ! 765: register SEG *sp; ! 766: ! 767: kclear(u.u_segl, sizeof(u.u_segl)); ! 768: for (n=0; n<NUSEG; n++) { ! 769: if ((sp=SELF->p_segp[n]) == NULL) ! 770: continue; ! 771: if (n == SIUSERP) ! 772: u.u_segl[n].sr_base = &u; ! 773: else ! 774: u.u_segl[n].sr_flag |= SRFPMAP; ! 775: if (n!=SISTEXT && n!=SISDATA) ! 776: u.u_segl[n].sr_flag |= SRFDUMP; ! 777: if (n!=SIUSERP && n!=SISTEXT && n!=SIPTEXT) ! 778: u.u_segl[n].sr_flag |= SRFDATA; ! 779: u.u_segl[n].sr_size = sp->s_size; ! 780: u.u_segl[n].sr_segp = sp; ! 781: } ! 782: return (mproto()); ! 783: } ! 784: ! 785: /* ! 786: * Search for a busy text inode. ! 787: */ ! 788: sbusy(ip) ! 789: register INODE *ip; ! 790: { ! 791: register SEG *sp; ! 792: ! 793: lock(seglink); ! 794: /* ! 795: * Look for the segment in the memory queue. ! 796: */ ! 797: for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) { ! 798: if (sp->s_ip==ip ! 799: && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) { ! 800: unlock(seglink); ! 801: return (1); ! 802: } ! 803: } ! 804: ! 805: /* ! 806: * Look for the segment on the disk queue. ! 807: */ ! 808: for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) { ! 809: if (sp->s_ip==ip ! 810: && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) { ! 811: unlock(seglink); ! 812: return (1); ! 813: } ! 814: } ! 815: unlock(seglink); ! 816: return (0); ! 817: } ! 818: ! 819: /* ! 820: * Segment consistency checks for the paranoid. ! 821: segchk() ! 822: { ! 823: register SEG *sp; ! 824: register int nbad; ! 825: fsize_t s; ! 826: daddr_t d; ! 827: ! 828: nbad = 0; ! 829: sp = &segmq; ! 830: s = corebot; ! 831: while ((sp=sp->s_forw) != &segmq) { ! 832: if (sp->s_paddr < s) ! 833: nbad += badseg("mem", sp->s_paddr, 0); ! 834: s = sp->s_paddr + sp->s_size; ! 835: } ! 836: if (coretop < s) ! 837: nbad += badseg("mem", sp->s_back->s_paddr, sp->s_back->s_size); ! 838: sp = &segdq; ! 839: d = swapbot; ! 840: while ((sp=sp->s_forw) != &segdq) { ! 841: if (sp->s_daddr < d) ! 842: nbad += badseg("disk", (int)sp->s_daddr, 0); ! 843: d = sp->s_daddr + (sp->s_size / BSIZE); ! 844: } ! 845: if (swaptop < d) ! 846: nbad += badseg("disk", sp->s_back->s_daddr, sp->s_back->s_size); ! 847: } ! 848: ! 849: badseg(t, b, s) ! 850: char *t; ! 851: daddr_t b; ! 852: fsize_t s; ! 853: { ! 854: printf( "Bad %s segment at %X of len %X\n", t, b, s ); ! 855: return (1); ! 856: } ! 857: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.