|
|
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.