|
|
1.1 ! root 1: /* $Header: /kernel/kersrc/ldrv/RCS/ldswap.c,v 1.1 92/07/17 15:27:54 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: * Swapper. ! 18: * ! 19: * $Log: ldswap.c,v $ ! 20: * Revision 1.1 92/07/17 15:27:54 bin ! 21: * Initial revision ! 22: * ! 23: * Revision 1.1 88/03/24 16:30:50 src ! 24: * Initial revision ! 25: * ! 26: * 87/11/05 Allan Cornish /usr/src/sys/ldrv/ldswap.c ! 27: * New seg struct now used to allow extended addressing. ! 28: * ! 29: * 87/10/26 Allan Cornish /usr/src/sys/ldrv/ldswap.c ! 30: * Modified to support loadable drivers - temporary modification. ! 31: * Now requires SIGKILL signal in order to terminate. ! 32: * ! 33: * 87/01/05 Allan Cornish /usr/src/sys/ker/swap.c ! 34: * Swap() now waits for all processes to be swapped in before exit on signal. ! 35: */ ! 36: #include <sys/coherent.h> ! 37: #include <sys/proc.h> ! 38: #include <sys/sched.h> ! 39: #include <sys/seg.h> ! 40: #include <sys/uproc.h> ! 41: #include <sys/buf.h> ! 42: ! 43: /* ! 44: * Functions. ! 45: */ ! 46: SEG *xmalloc(); ! 47: SEG *xdalloc(); ! 48: void Kwakeup(); ! 49: void Ktimeout(); ! 50: ! 51: main() ! 52: { ! 53: register SEG *sp; ! 54: register PROC *pp1; ! 55: register PROC *pp2; ! 56: register PROC *pp3; ! 57: register unsigned s; ! 58: register unsigned n; ! 59: register unsigned t; ! 60: register unsigned v; ! 61: register unsigned m; ! 62: register int i; ! 63: static unsigned ltimer; ! 64: ! 65: if (sexflag != 0) ! 66: uexit(1); ! 67: sexflag++; ! 68: ! 69: while (1) { ! 70: lock( pnxgate ); ! 71: t = (utimer - ltimer) / NSUTICK; ! 72: v = t * SVCLOCK; ! 73: ltimer += t * NSUTICK; ! 74: ! 75: /* ! 76: * Search for process to swap into memory. ! 77: */ ! 78: pp2 = NULL; ! 79: m = 0; ! 80: s = 0; ! 81: for (pp1 = procq.p_nback; pp1 != &procq; pp1 = pp1->p_nback) { ! 82: ! 83: /* ! 84: * Process resides in memory. ! 85: */ ! 86: if ( (pp1->p_flags & PFCORE) != 0 ) { ! 87: pp1->p_sval >>= t; ! 88: pp1->p_ival -= t; ! 89: if (pp1->p_ival < -30000) ! 90: pp1->p_ival = -30000; ! 91: continue; ! 92: } ! 93: ! 94: /* ! 95: * Update swap value - high values swapped in first. ! 96: */ ! 97: addu( pp1->p_sval, v ); ! 98: s = 1; ! 99: ! 100: /* ! 101: * Process is not runnable. ! 102: */ ! 103: if ( pp1->p_state != PSRUN ) ! 104: continue; ! 105: ! 106: /* ! 107: * Calculate disk usage in Kbytes. ! 108: */ ! 109: s = 0; ! 110: for ( i = 0; i < NUSEG+1; i++ ) ! 111: if ( (sp = pp1->p_segp[i]) != NULL ) ! 112: if ( (sp->s_flags & SFCORE) == 0 ) ! 113: s += sp->s_size / 1024; ! 114: if ( s == 0 ) ! 115: s = 1; ! 116: ! 117: /* ! 118: * Compute importance: ! 119: * ! 120: * swap value + response value ! 121: * --------------------------- ! 122: * Kbytes to be swapped in ! 123: */ ! 124: n = (pp1->p_sval + pp1->p_rval) / s; ! 125: ! 126: /* ! 127: * More important. ! 128: */ ! 129: if ( n > m ) { ! 130: m = n; ! 131: pp2 = pp1; ! 132: } ! 133: } ! 134: unlock( pnxgate ); ! 135: ! 136: /* ! 137: * No runnable processes swapped out. ! 138: */ ! 139: if ( pp2 == NULL ) { ! 140: /* ! 141: * No processes swapped out, and KILL signal received. ! 142: */ ! 143: if ( (s == 0) && (SELF->p_ssig & 0x0100) ) ! 144: break; ! 145: goto con; ! 146: } ! 147: ! 148: #ifndef NOMONITOR ! 149: if (swmflag) ! 150: printf("Swapin(%p, %d)\n", pp2, pp2->p_pid); ! 151: #endif ! 152: xxx: ! 153: /* ! 154: * Try to swap process into memory. ! 155: */ ! 156: while ( (testcore(pp2) == 0) || (proccore(pp2) != 0) ) { ! 157: ! 158: /* ! 159: * Swap process out. ! 160: */ ! 161: procdisk(pp2); ! 162: i = 32767; ! 163: pp3 = NULL; ! 164: ! 165: /* ! 166: * Search for process to swap out. ! 167: */ ! 168: lock( pnxgate ); ! 169: for (pp1=procq.p_nforw; pp1!=&procq; pp1=pp1->p_nforw){ ! 170: ! 171: if ( pp1->p_flags & (PFSWIO|PFLOCK|PFKERN) ) ! 172: continue; ! 173: ! 174: /* ! 175: * Process is not totally memory resident. ! 176: */ ! 177: if ( (pp1->p_flags&PFCORE) == 0 ) { ! 178: /* ! 179: * Swap segments out to disk. ! 180: */ ! 181: if ( procdisk(pp1) != 0 ) { ! 182: unlock( pnxgate ); ! 183: goto xxx; ! 184: } ! 185: continue; ! 186: } ! 187: ! 188: /* ! 189: * Process too important to swap out. ! 190: */ ! 191: if ((pp1->p_ival > -64) && (pp1->p_sval != 0)) ! 192: continue; ! 193: ! 194: /* ! 195: * Less important. ! 196: */ ! 197: if ( pp1->p_ival < i ) { ! 198: i = pp1->p_ival; ! 199: pp3 = pp1; ! 200: } ! 201: } ! 202: unlock( pnxgate ); ! 203: ! 204: /* ! 205: * No processes to swap out. ! 206: */ ! 207: if ( pp3 == NULL ) { ! 208: #ifndef NOMONITOR ! 209: if (swmflag) ! 210: printf("No one to swap out\n"); ! 211: #endif ! 212: break; ! 213: } ! 214: ! 215: /* ! 216: * Process is too important to swap out. ! 217: */ ! 218: if ( i > 0 ) { ! 219: #ifndef NOMONITOR ! 220: if (swmflag) ! 221: printf("Dispatch(%p, %d)\n", ! 222: pp3, pp3->p_pid); ! 223: #endif ! 224: pp3->p_flags |= PFDISP; ! 225: break; ! 226: } ! 227: #ifndef NOMONITOR ! 228: if (swmflag) ! 229: printf("Swapout(%p, %d)\n", pp3, pp3->p_pid); ! 230: #endif ! 231: /* ! 232: * Swap process out to disk. ! 233: */ ! 234: procdisk( pp3 ); ! 235: } ! 236: ! 237: #ifndef NOMONITOR ! 238: if (swmflag) ! 239: printf("Swapdone\n"); ! 240: #endif ! 241: con: ! 242: kcall( Ktimeout, &stimer, NSRTICK, Kwakeup, (char *)&stimer ); ! 243: sleep( (char *)&stimer, CVSWAP, IVSWAP, SVSWAP ); ! 244: } ! 245: sexflag--; ! 246: uexit( 1 ); ! 247: } ! 248: ! 249: /* ! 250: * See if the given process may fit in core. ! 251: */ ! 252: testcore( pp ) ! 253: register PROC *pp; ! 254: { ! 255: register SEG *sp; ! 256: register fsize_t s; ! 257: register paddr_t s1; ! 258: register paddr_t s2; ! 259: register int i; ! 260: ! 261: /* ! 262: * Find largest segment in process. ! 263: */ ! 264: s = 0; ! 265: for ( i = 0; i < NUSEG+1; i++ ) { ! 266: ! 267: if ( (sp = pp->p_segp[i]) == NULL ) ! 268: continue; ! 269: ! 270: /* ! 271: * Segment is memory resident. ! 272: */ ! 273: if ( (sp->s_flags & SFCORE) != 0 ) ! 274: continue; ! 275: ! 276: /* ! 277: * Largest segment so far. ! 278: */ ! 279: if ( sp->s_size > s ) ! 280: s = sp->s_size; ! 281: } ! 282: ! 283: /* ! 284: * See if largest segment will fit in memory. ! 285: */ ! 286: s1 = corebot; ! 287: sp = &segmq; ! 288: do { ! 289: /* ! 290: * Advance to next memory segment. ! 291: */ ! 292: sp = sp->s_forw; ! 293: s2 = sp->s_paddr; ! 294: ! 295: /* ! 296: * It fits! ! 297: */ ! 298: if ( s2 - s1 >= s ) ! 299: return (1); ! 300: ! 301: /* ! 302: * Compute start of next hole. ! 303: */ ! 304: s1 = sp->s_paddr + sp->s_size; ! 305: ! 306: } while ( sp != &segmq ); ! 307: ! 308: return( 0 ); ! 309: } ! 310: ! 311: /* ! 312: * Swap all segments associated with a particular process into core. ! 313: * The number of segments still swapped out is returned. ! 314: */ ! 315: proccore( pp ) ! 316: register PROC *pp; ! 317: { ! 318: register SEG *sp; ! 319: register int i; ! 320: register int n; ! 321: register int f; ! 322: ! 323: f = pp->p_flags & PFSWAP; ! 324: ! 325: /* ! 326: * Try to swap in all user segments and the auxiliary segment. ! 327: */ ! 328: for ( n = 0, i = 0; i < NUSEG+1; i++ ) { ! 329: ! 330: if ( (sp = pp->p_segp[i]) == NULL ) ! 331: continue; ! 332: ! 333: /* ! 334: * Process was swapped out. ! 335: */ ! 336: if ( f != 0 ) ! 337: sp->s_lrefc++; ! 338: ! 339: /* ! 340: * Segment is disk resident - try to swap it in. ! 341: */ ! 342: if ( (sp->s_flags & SFCORE) == 0 ) ! 343: if ( segcore(sp) == 0 ) ! 344: n++; ! 345: } ! 346: ! 347: /* ! 348: * No segments left on disk - mark process as being memory resident. ! 349: */ ! 350: if ( n == 0 ) ! 351: pp->p_flags |= PFCORE; ! 352: ! 353: /* ! 354: * Mark process as no longer being disk resident. ! 355: */ ! 356: pp->p_flags &= ~PFSWAP; ! 357: ! 358: return( n ); ! 359: } ! 360: ! 361: /* ! 362: * Swap out all segments associated with a given process. ! 363: */ ! 364: procdisk( pp ) ! 365: register PROC *pp; ! 366: { ! 367: register SEG *sp; ! 368: register int i; ! 369: register int f; ! 370: int n; ! 371: ! 372: f = pp->p_flags & PFSWAP; ! 373: ! 374: /* ! 375: * Mark process as no longer being memory resident BEFORE swapping. ! 376: */ ! 377: pp->p_flags &= ~PFCORE; ! 378: ! 379: /* ! 380: * Try to swap out all user segments and the auxiliary segment. ! 381: */ ! 382: for ( n = 0, i = 0; i < NUSEG+1; i++ ) { ! 383: ! 384: if ( (sp = pp->p_segp[i]) == NULL ) ! 385: continue; ! 386: ! 387: /* ! 388: * Process not already swapped out. ! 389: */ ! 390: if ( f == 0 ) ! 391: sp->s_lrefc--; ! 392: ! 393: /* ! 394: * Segment already swapped out. ! 395: */ ! 396: if ( (sp->s_flags & SFCORE) == 0 ) ! 397: continue; ! 398: ! 399: /* ! 400: * Segment no longer referenced by a memory-resident process. ! 401: */ ! 402: if ( (sp->s_lrefc == 0) && (segdisk(sp) != 0) ) ! 403: n++; ! 404: } ! 405: ! 406: /* ! 407: * Mark process as being disk resident. ! 408: */ ! 409: pp->p_flags |= PFSWAP; ! 410: ! 411: return( n ); ! 412: } ! 413: ! 414: /* ! 415: * Swap the given segment into core. ! 416: * NOTE: Although swapped out, the segment may have a descriptor table entry, ! 417: * and therefore have a valid s_faddr field. ! 418: */ ! 419: segcore( sp1 ) ! 420: register SEG *sp1; ! 421: { ! 422: register SEG *sp2; ! 423: ! 424: /* ! 425: * Lock segmentation. ! 426: */ ! 427: lock( seglink ); ! 428: ! 429: /* ! 430: * Segment has been moved to memory while we waited to lock. ! 431: */ ! 432: if ( (sp1->s_flags & SFCORE) != 0 ) { ! 433: unlock(seglink); ! 434: return( 1 ); ! 435: } ! 436: ! 437: /* ! 438: * Allocate a memory segment sp2. ! 439: */ ! 440: if ((sp2 = xmalloc( sp1->s_size )) == NULL ) { ! 441: unlock( seglink ); ! 442: return( 0 ); ! 443: } ! 444: ! 445: /* ! 446: * Copy the disk segment sp1 into the memory segment sp2. ! 447: */ ! 448: sp1->s_lrefc++; ! 449: swapio(0, sp2->s_paddr, sp1->s_daddr, sp2->s_size ); ! 450: sp1->s_lrefc--; ! 451: ! 452: /* ! 453: * Remove segment sp1 from the disk queue. ! 454: */ ! 455: sp1->s_back->s_forw = sp1->s_forw; ! 456: sp1->s_forw->s_back = sp1->s_back; ! 457: ! 458: /* ! 459: * Insert segment sp1 into memory queue replacing segment sp2. ! 460: */ ! 461: sp2->s_back->s_forw = sp1; ! 462: sp1->s_back = sp2->s_back; ! 463: sp2->s_forw->s_back = sp1; ! 464: sp1->s_forw = sp2->s_forw; ! 465: ! 466: /* ! 467: * Enable access to memory segment sp1. ! 468: */ ! 469: sp1->s_flags |= SFCORE; ! 470: sp1->s_paddr = sp2->s_paddr; ! 471: vremap( sp1 ); ! 472: ! 473: /* ! 474: * Unlock segmentation. ! 475: */ ! 476: unlock( seglink ); ! 477: ! 478: return( 1 ); ! 479: } ! 480: ! 481: /* ! 482: * Swap the given segment out onto disk. ! 483: */ ! 484: segdisk( sp1 ) ! 485: register SEG *sp1; ! 486: { ! 487: register SEG *sp2; ! 488: ! 489: /* ! 490: * Lock segmentation. ! 491: */ ! 492: lock( seglink ); ! 493: ! 494: /* ! 495: * Verify segment sp1 did not become busy while we waited to lock. ! 496: * IE: raw disk i/o, or shared code fork. ! 497: */ ! 498: if ( sp1->s_lrefc != 0 ) { ! 499: unlock( seglink ); ! 500: return( 0 ); ! 501: } ! 502: ! 503: /* ! 504: * Segment has been moved to disk while we waited to lock. ! 505: */ ! 506: if ( (sp1->s_flags & SFCORE) == 0 ) { ! 507: unlock(seglink); ! 508: return( 1 ); ! 509: } ! 510: ! 511: /* ! 512: * Allocate a disk segment sp2. ! 513: */ ! 514: if ( (sp2 = xdalloc( sp1->s_size )) == NULL ) { ! 515: unlock( seglink ); ! 516: return( 0 ); ! 517: } ! 518: ! 519: /* ! 520: * Disable access to memory segment sp1. ! 521: */ ! 522: sp1->s_flags &= ~SFCORE; ! 523: sp1->s_daddr = sp2->s_daddr; ! 524: vremap( sp1 ); ! 525: ! 526: /* ! 527: * Copy the memory segment sp1 into the disk segment sp2. ! 528: */ ! 529: sp1->s_lrefc++; ! 530: swapio( 1, sp1->s_paddr, sp2->s_daddr, sp1->s_size ); ! 531: sp1->s_lrefc--; ! 532: ! 533: /* ! 534: * Remove segment sp1 from the memory queue. ! 535: */ ! 536: sp1->s_back->s_forw = sp1->s_forw; ! 537: sp1->s_forw->s_back = sp1->s_back; ! 538: ! 539: /* ! 540: * Insert segment sp1 into disk queue replacing segment sp2. ! 541: */ ! 542: sp2->s_back->s_forw = sp1; ! 543: sp1->s_back = sp2->s_back; ! 544: sp2->s_forw->s_back = sp1; ! 545: sp1->s_forw = sp2->s_forw; ! 546: ! 547: /* ! 548: * Unlock segmentation. ! 549: */ ! 550: unlock( seglink ); ! 551: ! 552: return( 1 ); ! 553: } ! 554: ! 555: /* ! 556: * Allocate a segment on disk that is `n' bytes long. ! 557: * The `seglink' gate should be locked before this routine is called. ! 558: * This routine is the same as `sdalloc' except that we can't run out of ! 559: * alloc space to allocate the segment and we allocate in high regions. ! 560: * NOTE: descriptor table entries are not released. ! 561: */ ! 562: SEG * ! 563: xdalloc( s ) ! 564: fsize_t s; ! 565: { ! 566: register SEG *sp1; ! 567: register SEG *sp2; ! 568: register daddr_t d; ! 569: register daddr_t d1; ! 570: register daddr_t d2; ! 571: ! 572: d = s / BSIZE; ! 573: d2 = swaptop; ! 574: sp1 = &segdq; ! 575: do { ! 576: if ( (sp1 = sp1->s_back) != &segdq ) ! 577: d1 = sp1->s_daddr + (sp1->s_size / BSIZE); ! 578: else ! 579: d1 = swapbot; ! 580: ! 581: if ( d2 - d1 >= d ) { ! 582: sp2 = &segswap; ! 583: kclear( (char *)sp2, sizeof(SEG) ); ! 584: sp1->s_forw->s_back = sp2; ! 585: sp2->s_forw = sp1->s_forw; ! 586: sp1->s_forw = sp2; ! 587: sp2->s_back = sp1; ! 588: sp2->s_urefc = 1; ! 589: sp2->s_lrefc = 1; ! 590: sp2->s_size = s; ! 591: sp2->s_daddr = d2 - d; ! 592: return( sp2 ); ! 593: } ! 594: ! 595: d2 = sp1->s_daddr; ! 596: ! 597: } while ( sp1 != &segdq ); ! 598: ! 599: return( NULL ); ! 600: } ! 601: ! 602: /* ! 603: * Allocate a segment in memory that is `n' bytes long. ! 604: * The `seglink' gate should be locked before this routine is called. ! 605: * This routine is the same as `smalloc' except that we can't run out of ! 606: * alloc space to allocate the segment. ! 607: * NOTE: Do NOT remap virtual descriptor table entry. ! 608: * This is a scratch entry, and the s_faddr field is not retained. ! 609: */ ! 610: SEG * ! 611: xmalloc( s ) ! 612: register fsize_t s; ! 613: { ! 614: register SEG *sp1; ! 615: register SEG *sp2; ! 616: register paddr_t s1; ! 617: register paddr_t s2; ! 618: ! 619: s1 = corebot; ! 620: sp1 = &segmq; ! 621: do { ! 622: if ( (sp1 = sp1->s_forw) != &segmq ) ! 623: s2 = sp1->s_paddr; ! 624: else ! 625: s2 = coretop; ! 626: ! 627: if ( s2 - s1 >= s ) { ! 628: sp2 = &segswap; ! 629: kclear( (char *)sp2, sizeof(SEG) ); ! 630: sp1->s_back->s_forw = sp2; ! 631: sp2->s_back = sp1->s_back; ! 632: sp1->s_back = sp2; ! 633: sp2->s_forw = sp1; ! 634: sp2->s_urefc = 1; ! 635: sp2->s_lrefc = 1; ! 636: sp2->s_size = s; ! 637: sp2->s_paddr = s1; ! 638: return( sp2 ); ! 639: } ! 640: ! 641: s1 = sp1->s_paddr + sp1->s_size; ! 642: ! 643: } while ( sp1 != &segmq ); ! 644: ! 645: return( NULL ); ! 646: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.