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