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