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