|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 8477 (0x211d) Types: TextFile Notes: UNIX file Names: »swap.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦2d53db1df⟧ UNIX Filesystem └─⟦this⟧ »sys/ker/swap.c«
/* (-lgl * The information contained herein is a trade secret of Mark Williams * Company, and is confidential information. It is provided under a * license agreement, and may be copied or disclosed only under the * terms of that agreement. Any reproduction or disclosure of this * material without the express written authorization of Mark Williams * Company or persuant to the license agreement is unlawful. * * COHERENT Version 0.7.3 * Copyright (c) 1982, 1983, 1984. * An unpublished work by Mark Williams Company, Chicago. * All rights reserved. -lgl) */ /* * Coherent. * Swapper. */ #include <coherent.h> #include <proc.h> #include <sched.h> #include <seg.h> #include <uproc.h> #include <buf.h> /* * Functions. */ SEG *xmalloc(); SEG *xdalloc(); swap() { register SEG *sp; register PROC *pp1; register PROC *pp2; register PROC *pp3; register unsigned s; register unsigned n; register unsigned t; register unsigned v; register unsigned m; register int i; static unsigned ltimer; #ifndef NOMONITOR if (swmflag) printf("Swap starts %d\n", sexflag); #endif if (sexflag != 0) uexit(1); sexflag++; while (SELF->p_ssig == 0) { lock(pnxgate); t = (utimer-ltimer)/NSUTICK; v = t*SVCLOCK; ltimer += t*NSUTICK; m = 0; pp2 = NULL; for (pp1=procq.p_nback; pp1!=&procq; pp1=pp1->p_nback) { if ((pp1->p_flags&PFCORE) != 0) { pp1->p_sval >>= t; pp1->p_ival -= t; if (pp1->p_ival < -30000) pp1->p_ival = -30000; continue; } addu(pp1->p_sval, v); if (pp1->p_state != PSRUN) continue; s = 0; for (i=0; i<NUSEG+1; i++) if ((sp=pp1->p_segp[i]) != NULL) if ((sp->s_flags&SFCORE) == 0) s += sp->s_size; if ((s=ctokrd(s)) == 0) s = 1; n = (pp1->p_sval+pp1->p_rval)/s; if (n > m) { m = n; pp2 = pp1; } } unlock(pnxgate); if (pp2 == NULL) goto con; #ifndef NOMONITOR if (swmflag) printf("Swapin(%p, %d)\n", pp2, pp2->p_pid); #endif xxx: while (testcore(pp2)==0 || proccore(pp2)!=0) { if ((pp2->p_flags&PFAUXM) != 0) { auxmdisk(pp2); goto xxx; } procdisk(pp2); i = 32767; pp3 = NULL; lock(pnxgate); for (pp1=procq.p_nforw; pp1!=&procq; pp1=pp1->p_nforw){ if (pp1->p_flags&(PFSWIO|PFLOCK|PFKERN)) continue; if ((pp1->p_flags&PFAUXM) != 0) { auxmdisk(pp1); unlock(pnxgate); goto xxx; } if ((pp1->p_flags&PFCORE) == 0) { if (procdisk(pp1) != 0) { unlock(pnxgate); goto xxx; } continue; } if (pp1->p_ival>-64 && pp1->p_sval!=0) continue; if (pp1->p_ival < i) { i = pp1->p_ival; pp3 = pp1; } } unlock(pnxgate); if (pp3 == NULL) { #ifndef NOMONITOR if (swmflag) printf("No one to swap out\n"); #endif break; } if (i > 0) { #ifndef NOMONITOR if (swmflag) printf("Dispatch(%p, %d)\n", pp3, pp3->p_pid); #endif pp3->p_flags |= PFDISP; break; } #ifndef NOMONITOR if (swmflag) printf("Swapout(%p, %d)\n", pp3, pp3->p_pid); #endif procdisk(pp3); } #ifndef NOMONITOR if (swmflag) printf("Swapdone\n"); #endif con: timeout(&stimer, NSRTICK, wakeup, (char *)&stimer); sleep((char *)&stimer, CVSWAP, IVSWAP, SVSWAP); } --sexflag; uexit(1); } /* * See if the given process may fit in core. */ testcore(pp) register PROC *pp; { register SEG *sp; register saddr_t s; register saddr_t s1; register saddr_t s2; register int i; s = 0; for (i=0; i<NUSEG+1; i++) { if ((sp=pp->p_segp[i]) == NULL) continue; if ((sp->s_flags&SFCORE) != 0) continue; if (sp->s_size > s) s = sp->s_size; } s1 = corebot; sp = &segmq; do { sp = sp->s_forw; s2 = sp->s_mbase; if (s2-s1 >= s) return (1); s1 = sp->s_mbase + sp->s_size; } while (sp != &segmq); return (0); } /* * Swap all segments associated with a particular process into core. * The number of segments still swapped out is returned. */ proccore(pp) register PROC *pp; { register SEG *sp; register int i; register int n; register int f; n = 0; f = pp->p_flags&PFSWAP; for (i=0; i<NUSEG+1; i++) { if ((sp=pp->p_segp[i]) == NULL) continue; if (f != 0) sp->s_lrefc++; if ((sp->s_flags&SFCORE)==0 && segcore(sp)==0) n++; } if (n == 0) pp->p_flags |= PFCORE|PFSPROTO; pp->p_flags &= ~PFSWAP; return (n); } /* * Swap out all segments associated with a given process. */ procdisk(pp) register PROC *pp; { register SEG *sp; register int i; register int f; int n; n = 0; f = pp->p_flags&PFSWAP; pp->p_flags &= ~PFCORE; for (i=0; i<NUSEG+1; i++) { if ((sp=pp->p_segp[i]) == NULL) continue; if (f == 0) --sp->s_lrefc; if ((sp->s_flags&SFCORE) == 0) continue; if (sp->s_lrefc == 0) if (segdisk(sp) != 0) n++; } pp->p_flags |= PFSWAP; return (n); } /* * Swap out all auxiliary segments used by a process. */ auxmdisk(pp) register PROC *pp; { register SEG *sp; register int i; register int f; register int m; SEG *segl[NUSEG]; #ifndef NOMONITOR if (swmflag) printf("Auxiliary(%p, %d)\n", pp, pp->p_pid); #endif sp = pp->p_segp[SIUSERP]; if ((sp->s_flags&SFCORE) == 0) { panic("We may be in trouble"); return; } m = pp->p_flags&PFCORE; f = pp->p_flags&PFAUXM; pp->p_flags &= ~(PFAUXM|PFCORE); skcopy(sp, offset(uproc, u_sege[0]), segl, sizeof(u.u_sege)); for (i=0; i<NUSEG; i++) { if ((sp=segl[i]) == NULL) continue; if (f != 0) --sp->s_lrefc; if ((sp->s_flags&SFCORE) == 0) continue; if (sp->s_lrefc == 0) segdisk(sp); } pp->p_flags |= m; } /* * Swap the given segment into core. */ segcore(sp1) register SEG *sp1; { register SEG *sp2; lock(seglink); sp2 = xmalloc(sp1->s_size); unlock(seglink); if (sp2 == NULL) return (0); sp1->s_lrefc++; swapio(0, sp2->s_mbase, sp1->s_dbase, sp2->s_size); lock(seglink); sp1->s_back->s_forw = sp1->s_forw; sp1->s_forw->s_back = sp1->s_back; sp2->s_back->s_forw = sp1; sp1->s_back = sp2->s_back; sp2->s_forw->s_back = sp1; sp1->s_forw = sp2->s_forw; sp1->s_flags |= SFCORE; sp1->s_mbase = sp2->s_mbase; --sp1->s_lrefc; unlock(seglink); return (1); } /* * Swap the given segment out onto disk. */ segdisk(sp1) register SEG *sp1; { register SEG *sp2; lock(seglink); sp2 = xdalloc(sp1->s_size); unlock(seglink); if (sp2 == NULL) return (0); sp1->s_lrefc++; swapio(1, sp1->s_mbase, sp2->s_dbase, sp1->s_size); lock(seglink); sp1->s_back->s_forw = sp1->s_forw; sp1->s_forw->s_back = sp1->s_back; sp2->s_back->s_forw = sp1; sp1->s_back = sp2->s_back; sp2->s_forw->s_back = sp1; sp1->s_forw = sp2->s_forw; sp1->s_flags &= ~SFCORE; sp1->s_dbase = sp2->s_dbase; --sp1->s_lrefc; unlock(seglink); return (1); } /* * Allocate a segment on disk that is `n' clicks long. * The `seglink' gate should be locked before this routine is called. * This routine is the same as `sdalloc' except that we can't run out of * alloc space to allocate the segment and we allocate in high regions. */ SEG * xdalloc(s) saddr_t s; { register SEG *sp1; register SEG *sp2; register daddr_t d; register daddr_t d1; register daddr_t d2; d = stod(s); d2 = swaptop; sp1 = &segdq; do { if ((sp1=sp1->s_back) != &segdq) d1 = sp1->s_dbase + stod(sp1->s_size); else d1 = swapbot; if (d2-d1 >= d) { sp2 = &segswap; kclear((char *)sp2, sizeof(SEG)); sp1->s_forw->s_back = sp2; sp2->s_forw = sp1->s_forw; sp1->s_forw = sp2; sp2->s_back = sp1; sp2->s_urefc = 1; sp2->s_lrefc = 1; sp2->s_size = s; sp2->s_dbase = d2 - d; return (sp2); } d2 = sp1->s_dbase; } while (sp1 != &segdq); return (NULL); } /* * Allocate a segment in memory that is `n' clicks long. * The `seglink' gate should be locked before this routine is called. * This routine is the same as `smalloc' except that we can't run out of * alloc space to allocate the segment. */ SEG * xmalloc(s) register saddr_t s; { register SEG *sp1; register SEG *sp2; register saddr_t s1; register saddr_t s2; s1 = corebot; sp1 = &segmq; do { if ((sp1=sp1->s_forw) != &segmq) s2 = sp1->s_mbase; else s2 = coretop; if (s2-s1 >= s) { sp2 = &segswap; kclear((char *)sp2, sizeof(SEG)); sp1->s_back->s_forw = sp2; sp2->s_back = sp1->s_back; sp1->s_back = sp2; sp2->s_forw = sp1; sp2->s_urefc = 1; sp2->s_lrefc = 1; sp2->s_size = s; sp2->s_mbase = s1; return (sp2); } s1 = sp1->s_mbase + sp1->s_size; } while (sp1 != &segmq); return (NULL); }