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