Annotation of researchv10dc/sys/vm/vmproc.c, revision 1.1.1.1

1.1       root        1: /*     vmproc.c        4.5     81/03/08        */
                      2: 
                      3: #include "sys/param.h"
                      4: #include "sys/systm.h"
                      5: #include "sys/user.h"
                      6: #include "sys/proc.h"
                      7: #include "sys/mtpr.h"
                      8: #include "sys/pte.h"
                      9: #include "sys/map.h"
                     10: #include "sys/cmap.h"
                     11: #include "sys/text.h"
                     12: #include "sys/inode.h"
                     13: #include "sys/vm.h"
                     14: 
                     15: struct pte *Forkmap;
                     16: struct user *forkutl;
                     17: 
                     18: struct dmap zdmap;             /* well, it has to be somewhere */
                     19: 
                     20: /*
                     21:  * Get virtual memory resources for a new process.
                     22:  * Called after page tables are allocated, but before they
                     23:  * are initialized, we initialize the memory management registers,
                     24:  * and then expand the page tables for the data and stack segments
                     25:  * creating zero fill pte's there.  Text pte's are set up elsewhere.
                     26:  *
                     27:  * SHOULD FREE EXTRA PAGE TABLE PAGES HERE OR SOMEWHERE.
                     28:  */
                     29: vgetvm(ts, ds, ss)
                     30:        clicks_t ts, ds, ss;
                     31: {
                     32: 
                     33:        mtpr(P0LR, ts);
                     34:        u.u_pcb.pcb_p0lr = ts | AST_NONE;
                     35:        mtpr(P1LR, P1TOP - UPAGES);
                     36:        u.u_pcb.pcb_p1lr = P1TOP - UPAGES;
                     37:        u.u_procp->p_tsize = ts;
                     38:        u.u_tsize = ts;
                     39:        expand((int)ss, P1BR);
                     40:        expand((int)ds, P0BR);
                     41: }
                     42: 
                     43: /*
                     44:  * Release the virtual memory resources (memory
                     45:  * pages, and swap area) associated with the current process.
                     46:  * Caller must not be swappable.  Used at exit or execl.
                     47:  */
                     48: vrelvm()
                     49: {
                     50:        register struct proc *p = u.u_procp;
                     51:        
                     52:        /*
                     53:         * Release memory; text first, then data and stack pages.
                     54:         */
                     55:        xfree();
                     56:        p->p_rssize -= vmemfree(dptopte(p, 0), p->p_dsize);
                     57:        p->p_rssize -= vmemfree(sptopte(p, p->p_ssize - 1), p->p_ssize);
                     58:        if (p->p_rssize != 0)
                     59:                panic("vrelvm rss");
                     60:        /*
                     61:         * Wait for all page outs to complete, then
                     62:         * release swap space.
                     63:         */
                     64:        p->p_swrss = 0;
                     65:        while (p->p_poip)
                     66:                sleep((caddr_t)&p->p_poip, PSWP+1);
                     67:        (void) vsexpand((clicks_t)0, &u.u_dmap, 1);
                     68:        (void) vsexpand((clicks_t)0, &u.u_smap, 1);
                     69:        p->p_tsize = 0;
                     70:        p->p_dsize = 0;
                     71:        p->p_ssize = 0;
                     72:        u.u_tsize = 0;
                     73:        u.u_dsize = 0;
                     74:        u.u_ssize = 0;
                     75: }
                     76: 
                     77: /*
                     78:  * Change the size of the data+stack regions of the process.
                     79:  * If the size is shrinking, it's easy-- just release virtual memory.
                     80:  * If it's growing, initalize new page table entries as 
                     81:  * 'zero fill on demand' pages.
                     82:  */
                     83: expand(change, region)
                     84: {
                     85:        register struct proc *p;
                     86:        register struct pte *base, *p0, *p1;
                     87:        struct pte proto;
                     88:        int a0, a1;
                     89: 
                     90:        p = u.u_procp;
                     91:        if (change == 0)
                     92:                return;
                     93:        if (change % CLSIZE)
                     94:                panic("expand");
                     95: #ifdef PGINPROF
                     96:        vmsizmon();
                     97: #endif
                     98:        /*
                     99:         * Update the sizes to reflect the change.  Note that we may
                    100:         * swap as a result of a ptexpand, but this will work, because
                    101:         * the routines which swap out will get the current text and data
                    102:         * sizes from the arguments they are passed, and when the process
                    103:         * resumes the lengths in the proc structure are used to 
                    104:         * build the new page tables.
                    105:         */
                    106:        if (region == P0BR) {
                    107:                p->p_dsize += change;
                    108:                u.u_dsize += change;
                    109:        } else {
                    110:                p->p_ssize += change;
                    111:                u.u_ssize += change;
                    112:        }
                    113:        /*
                    114:         * Compute the end of the text+data regions and the beginning
                    115:         * of the stack region in the page tables,
                    116:         * and expand the page tables if necessary.
                    117:         */
                    118:        p0 = (struct pte *)mfpr(P0BR) + mfpr(P0LR);
                    119:        p1 = (struct pte *)mfpr(P1BR) + mfpr(P1LR);
                    120:        if (change > p1 - p0)
                    121:                ptexpand(clrnd(ctopt(change - (p1 - p0))));
                    122:        /* PTEXPAND SHOULD GIVE BACK EXCESS PAGE TABLE PAGES */
                    123:        /*
                    124:         * Compute the base of the allocated/freed region.
                    125:         */
                    126:        if (region == P0BR) {
                    127:                base = (struct pte *)mfpr(P0BR);
                    128:                base += (a0 = mfpr(P0LR)) + (change > 0 ? 0 : change);
                    129:        } else {
                    130:                base = (struct pte *)mfpr(P1BR);
                    131:                base += (a1 = mfpr(P1LR)) - (change > 0 ? change : 0);
                    132:        }
                    133: 
                    134:        /*
                    135:         * If we shrunk, give back the virtual memory.
                    136:         */
                    137:        if (change < 0)
                    138:                p->p_rssize -= vmemfree(base, -change);
                    139: 
                    140:        /*
                    141:         * Update the processor length registers and copies in the pcb.
                    142:         */
                    143:        if (region == P0BR)  {
                    144:                mtpr(P0LR, a0 + change);
                    145:                u.u_pcb.pcb_p0lr = a0 + change | (u.u_pcb.pcb_p0lr & AST_CLR);
                    146:        } else {
                    147:                mtpr(P1LR, a1 - change);
                    148:                u.u_pcb.pcb_p1lr = a1 - change;
                    149:        }
                    150:        *(int *)&proto = PG_UW;
                    151:        if (change < 0)
                    152:                change = -change;
                    153:        else {
                    154:                proto.pg_fod = 1;
                    155:                ((struct fpte *)&proto)->pg_source = PG_FZERO;
                    156:                cnt.v_nzfod += change;
                    157:        }
                    158:        while (--change >= 0)
                    159:                *base++ = proto;
                    160:        mtpr(TBIA,0);
                    161: }
                    162: 
                    163: /*
                    164:  * Create a duplicate copy of the current process
                    165:  * in process slot p, which has been partially initialized
                    166:  * by newproc().
                    167:  *
                    168:  * Could deadlock here if two large proc's get page tables
                    169:  * and then each gets part of his UPAGES if they then have
                    170:  * consumed all the available memory.  This can only happen when
                    171:  *     USRPTSIZE + UPAGES * NPROC > maxmem
                    172:  * which happens only when large procs fork on machines with tiny real memories
                    173:  */
                    174: procdup(p)
                    175:        register struct proc *p;
                    176: {
                    177:        extern struct map kernelmap[];
                    178: 
                    179:        /*
                    180:         * allocate page tables and a user block;
                    181:         * copy parent's user to child
                    182:         */
                    183:        while (vgetpt(p, vmemall) == 0) {
                    184:                kmapwnt++;
                    185:                sleep((caddr_t)kernelmap, PSWP+4);
                    186:        }
                    187:        resume(pcbb(u.u_procp));
                    188:        (void) vgetu(p, vmemall, Forkmap, forkutl, &u);
                    189:        /*
                    190:         * child: return here when scheduled and returns 1
                    191:         */
                    192:        forkutl->u_pcb.pcb_sswap = u.u_ssav;
                    193:        if (savectx(forkutl->u_ssav))
                    194:                return (1);
                    195:        /*
                    196:         * parent:
                    197:         * finish setting up child:
                    198:         * clear vm counters, attach text, copy data and stack
                    199:         * return 0
                    200:         */
                    201:        forkutl->u_vm = zvms;
                    202:        forkutl->u_cvm = zvms;
                    203:        forkutl->u_dmap = u.u_cdmap;
                    204:        forkutl->u_smap = u.u_csmap;
                    205:        forkutl->u_outime = 0;
                    206:        if (p->p_textp && ((p->p_textp->x_flag&XTRC) == 0 || vmxdup(p))) {
                    207:                p->p_textp->x_count++;
                    208:                xlink(p);
                    209:        }
                    210:        vmdup(p, dptopte(p, 0), dptov(p, 0), p->p_dsize, CDATA);
                    211:        vmdup(p, sptopte(p, p->p_ssize - 1), sptov(p, p->p_ssize - 1), p->p_ssize, CSTACK);
                    212:        return (0);
                    213: }
                    214: 
                    215: /*
                    216:  * Duplicate text segment (cf. xalloc).
                    217:  */
                    218: vmxdup(p)
                    219: register struct proc *p;
                    220: {
                    221:        register struct text *xp, *uxp;
                    222:        register clicks_t ts;
                    223: 
                    224:        if ((uxp = u.u_procp->p_textp) == 0)
                    225:                return 0;
                    226: 
                    227:        for (xp = text; xp < textNTEXT && xp->x_iptr; xp++)
                    228:                /* void */ ;
                    229:        if (xp >= textNTEXT)
                    230:                return 1;
                    231: 
                    232:        xp->x_flag = XLOCK|XTRC|XLOAD;
                    233:        xp->x_size = ts = uxp->x_size;
                    234:        if (vsxalloc(xp) == NULL)
                    235:                return 1;
                    236: 
                    237:        xp->x_count = 1;
                    238:        xp->x_ccount = 0;
                    239:        xp->x_rssize = 0;
                    240:        (xp->x_iptr = uxp->x_iptr)->i_count++;
                    241:        p->p_textp = xp;
                    242:        xlink(p);
                    243:        vmdup(p, tptopte(p, 0), tptov(p, 0), ts, CTEXT);
                    244:        xp->x_flag |= XWRIT;
                    245:        xp->x_flag &= ~XLOAD;
                    246:        xunlock(xp);
                    247: 
                    248:        return 0;
                    249: }
                    250: 
                    251: vmdup(p, pte, v, count, type)
                    252:        struct proc *p;
                    253:        register struct pte *pte;
                    254:        register unsigned v;
                    255:        register clicks_t count;
                    256:        int type;
                    257: {
                    258:        register struct pte *opte = vtopte(u.u_procp, v);
                    259:        register int i;
                    260: 
                    261:        while (count != 0) {
                    262:                count -= CLSIZE;
                    263:                if (opte->pg_fod && type != CTEXT) {
                    264:                        v += CLSIZE;
                    265:                        for (i = 0; i < CLSIZE; i++)
                    266:                                *(int *)pte++ = *(int *)opte++;
                    267:                        continue;
                    268:                }
                    269:                opte += CLSIZE;
                    270:                (void) vmemall(pte, CLSIZE, p, type);
                    271:                if (type == CTEXT)
                    272:                        p->p_textp->x_rssize += CLSIZE;
                    273:                else
                    274:                        p->p_rssize += CLSIZE;
                    275:                for (i = 0; i < CLSIZE; i++) {
                    276:                        copyseg((caddr_t)ctob(v+i), (pte+i)->pg_pfnum);
                    277:                        *(int *)(pte+i) |= (type == CTEXT) ?
                    278:                            ((PG_V|PG_M) + PG_URKR) : ((PG_V|PG_M) + PG_UW);
                    279:                }
                    280:                v += CLSIZE;
                    281:                munlock(pte->pg_pfnum);
                    282:                pte += CLSIZE;
                    283:        }
                    284: }
                    285: 
                    286: /*
                    287:  * Check that a process will not be too large.
                    288:  */
                    289: chksize(ts, ds, ss)
                    290:        clicks_t ts, ds, ss;
                    291: {
                    292: 
                    293:        if (ts>maxtsize || ds>maxdsize || ss>maxssize) {
                    294:                u.u_error = ENOMEM;
                    295:                return(1);
                    296:        }
                    297:        return (0);
                    298: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.