⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vm_proc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct pte proto;	size_t ods;	register int size;	register u_int v;	if (change == 0)		return;	if (change % CLSIZE)		panic("expand");	p = u.u_procp;#ifdef PGINPROF	vmsizmon();#endif		/* Update the sizes to reflect the change.	*/	ods = u.u_dsize;	v = dptov(p, p->p_dsize);	p->p_dsize += change;	u.u_dsize += change;		/* Compute the base of the allocated/freed region. */	base = u.u_pcb.pcb_p0br + u.u_tsize + ods;	if (change < 0){		base += change;		/* If we shrunk, give back the virtual memory.	*/		p->p_rssize -= vmemfree(base, -change);	}		/* If shrinking, clear pte's, otherwise		*/		/* initialize zero fill on demand pte's.	*/	*(int *)&proto = PG_UW;	if (change < 0)		change = -change;	else {		proto.pg_fod = 1;		((struct fpte *)&proto)->pg_fileno = PG_FZERO;		cnt.v_nzfod += change;	}	base0 = base;	size = change;	while (--change >= 0)		*base++ = proto;		/* We changed mapping for the current process,	*/		/* so must update the hardware translation	*/	newptes(base0, v, size);}#endif vax#ifdef mips/* * Change the size of the data+stack regions of the process. * If the size is shrinking, it's easy-- just release virtual memory. * If it's growing, initalize new page table entries as  * 'zero fill on demand' pages. */expand(change, region)	int change, region;{	register struct proc *p;	register struct pte *base;	struct pte proto;	size_t osize;	int size;	u_int v;	int avail;XPRINTF(XPR_VM,"enter expand",0,0,0,0);	p = u.u_procp;	if (change == 0)		return;	if (change % CLSIZE)		panic("expand");#ifdef PGINPROF	vmsizmon();#endif	/*	 * Update the sizes to reflect the change.  Note that we may	 * swap as a result of a ptexpand, but this will work, because	 * the routines which swap out will get the current text and data	 * sizes from the arguments they are passed, and when the process	 * resumes the lengths in the proc structure are used to 	 * build the new page tables.	 */	if (region == 0) {		osize = u.u_dsize;		v = dptov(p, p->p_dsize);		avail = (p->p_datapt * NPTEPG) - p->p_dsize;		p->p_dsize += change;		u.u_dsize += change;		if (change > avail) {			ptexpand(clrnd(ctopt(change - avail)), osize, 			    u.u_ssize, region);		}		base = p->p_databr + osize + (change > 0 ? 0 : change);	} else {		osize = u.u_ssize;		avail = (p->p_stakpt * NPTEPG)			- REDZONEPAGES - p->p_ssize;		p->p_ssize += change;		v = sptov(p, p->p_ssize - 1);		u.u_ssize += change;		if (change > avail) {			ptexpand(clrnd(ctopt(change - avail)), u.u_dsize, 			    osize, region);		}		base = (p->p_stakbr + p->p_stakpt * NPTEPG) 			- (p->p_ssize + REDZONEPAGES) + (change > 0 ? 0 : change);	}	/*	 * If we shrunk, give back the virtual memory.	 */	if (change < 0) {		p->p_rssize -= vmemfree(base, -change);		XPRINTF(XPR_VM, "expand p_rssize %d change %d", p->p_rssize,		    change, 0, 0);	}		/*	 * If shrinking, clear pte's, otherwise	 * initialize zero fill on demand pte's.	 */	*(int *)&proto = PG_UW;	if (change < 0)		change = -change;	else {		proto.pg_fod = 1;		((struct fpte *)&proto)->pg_fileno = PG_FZERO;		cnt.v_nzfod += change;	}	size = change;	while (--change >= 0)		*base++ = proto;	/*	 * We changed mapping for the current process,	 * so must update the hardware translation	 */	newptes(p, v, size);}smexpand(){XPRINTF(XPR_VM,"enter smexpand",0,0,0,0);	/* wow! - rr */}#endif mips/* * Create a duplicate copy of the current process * in process slot p, which has been partially initialized * by newproc(). * * Could deadlock here if two large proc's get page tables * and then each gets part of his UPAGES if they then have * consumed all the available memory.  This can only happen when *	USRPTSIZE + UPAGES * NPROC > maxmem * which is impossible except on systems with tiny real memories, * when large procs stupidly fork() instead of vfork(). */procdup(p, isvfork)	register struct proc *p;{	register struct file *fp;	register int n;	/*	 * Allocate page tables for new process, waiting	 * for memory to be free.	 */#ifdef mips	XPRINTF(XPR_VM, "enter procdup pid = %d", p->p_pid, 0, 0, 0);#endif mips#ifdef vax	while (vgetpt(p, vmemall) == 0) {#endif vax#ifdef mips        if (isvfork == 0) {		while (vgetpt(p, vmemall, vmemfree) == 0) {#endif mips		kmapwnt++;#ifdef mips		XPRINTF(XPR_VM, "procdup sleeping vgetpt failed pid = %d",			p->p_pid, 0, 0, 0);#endif mips		sleep((caddr_t)kernelmap, PSWP+4);	}#ifdef mips	}#endif mips	/*	 * Snapshot the current u. area pcb and get a u.	 * for the new process, a copy of our u.	 */#ifdef vax	resume(pcbb(u.u_procp));#endif vax#ifdef mips	XPRINTF(XPR_VM, "procdup calling vgetu pid = %d", p->p_pid, 0, 0, 0);        save();#endif mips	(void) vgetu(p, vmemall, Forkmap, &forkutl, &u);	/*	 * Arrange for a non-local goto when the new process	 * is started, to resume here, returning nonzero from savectx.	 */	forkutl.u_pcb.pcb_sswap = (int *)&u.u_ssave;#ifdef vax	if (savectx(&forkutl.u_ssave))#endif vax#ifdef mips	XPRINTF(XPR_VM, "procdup calling setjmp pid = %d", p->p_pid, 0, 0, 0);		/*         * TODO: can this setjmp() be avoided? perhaps only update PC.         */        if (setjmp(&forkutl.u_ssave))#endif mips		/*		 * Return 1 in child.		 */		return (1);	/* 001	 * Increase reference counts on shared objects	 * and remove INUSE reference to inode.	 */	for (n = 0; n <= u.u_omax; n++) {		fp = u.u_ofile[n];		if (fp == NULL)			continue;		fp->f_count++;		forkutl.u_pofile[n] &= ~(UF_INUSE);	}	/*	 * If the new process is being created in vfork(), then	 * exchange vm resources with it.  We want to end up with	 * just a u. area and an empty p0 region, so initialize the	 * prototypes in the other area before the exchange.	 */	if (isvfork) {#ifdef vax		forkutl.u_pcb.pcb_p0lr = u.u_pcb.pcb_p0lr & AST_CLR;		forkutl.u_pcb.pcb_p1lr = P1PAGES - HIGHPAGES;#endif#ifdef mips		/*		 * I think this is a bug on the VAX verion anyway.		 * The child is started with an empty page table and		 * then the parent and child swap page tables. The above		 * statement has no effect because the parent will not		 * run again in user mode until after it gets its page		 * table back.		 * Copying resched isn't really necessary, I'm not sure		 * why they copy the AST bits on the VAX.		 */		forkutl.u_pcb.pcb_resched = u.u_pcb.pcb_resched;#endif		vpassvm(u.u_procp, p, &u, &forkutl, Forkmap);#ifdef mips		clear_tlbmappings(p);#endif mips		/*		 * Return 0 in parent.		 */		return (0);	}	/*	 * A real fork; clear vm statistics of new process	 * and link into the new text segment.	 * Equivalent things happen during vfork() in vpassvm().	 */	bzero((caddr_t)&forkutl.u_ru, sizeof (struct rusage));	bzero((caddr_t)&forkutl.u_cru, sizeof (struct rusage));	forkutl.u_dmap = u.u_cdmap;	forkutl.u_smap = u.u_csmap;	forkutl.u_outime = 0;	/*	 * Attach to the text segment.	 */	if (p->p_textp) {		p->p_textp->x_count++;#ifdef GFSDEBUG		if(p->p_textp->x_freef || p->p_textp->x_freeb) {			cprintf("procdup: pid %d xp 0x%x on free list\n",			p->p_pid, p->p_textp);			panic("procdup");		}#endif#ifdef mips                while (xlink(p) == 0) {                        kmapwnt++;#ifdef mips		XPRINTF(XPR_VM, "procdup sleeping xlink failed pid = %d",			p->p_pid, 0, 0, 0);#endif mips                        sleep((caddr_t)kernelmap, PSWP+4);                }#endif mips#ifdef vax		xlink(p);#endif vax	}#ifdef mips	XPRINTF(XPR_VM, "procdup calling clear_tlbmappings pid = %d", p->p_pid, 0, 0, 0);        clear_tlbmappings(p);#endif mips	/* attach all shared memory segments	SHMEM	*/	if(p->p_smbeg != 0) {		smfork(u.u_procp, p);	}	/*	 * Duplicate data and stack space of current process	 * in the new process.	 */	vmdup(p, dptopte(p, 0), dptov(p, 0), p->p_dsize, CDATA);	vmdup(p, sptopte(p, p->p_ssize - 1), sptov(p, p->p_ssize - 1), p->p_ssize, CSTACK);	/*	 * Return 0 in parent.	 */	return (0);}/* *	this is where all the work for fork is done. *	we take out the loops for i=0,1 and put the code inline *	we also use only registers in the while loop *	As far as this goes, we only run with CLSIZE==2 anyways!!!! */vmdup(p, pte, v, count, type)#if CLSIZE==2	register struct proc *p;#else	struct proc *p;#endif	register struct pte *pte;	register unsigned v;	register size_t count;	int type;{	register struct pte *opte = vtopte(u.u_procp, v);	register struct cmap *c;#if CLSIZE!=2	register int i;#endif#ifdef mips	XPRINTF(XPR_VM,"enter vmdup",0,0,0,0);#endif mips	while (count != 0) {		count -= CLSIZE;		if (opte->pg_fod) {			v += CLSIZE;#if CLSIZE==2			*(int *)pte++ = *(int *)opte++;			*(int *)pte++ = *(int *)opte++;#else			for (i = 0; i < CLSIZE; i++)				*(int *)pte++ = *(int *)opte++;#endif			continue;		}#ifdef vax		opte += CLSIZE;#endif vax		(void) vmemall(pte, CLSIZE, p, type);		p->p_rssize += CLSIZE;#if CLSIZE==2		copyseg((caddr_t)ctob(v), pte->pg_pfnum);		*(int *)(pte) |= (PG_V|PG_M) + PG_UW;		c = &cmap[pgtocm(pte->pg_pfnum)]; /* grab before bumping pte */		v++;pte++;		copyseg((caddr_t)ctob(v), pte->pg_pfnum);		*(int *)(pte) |= (PG_V|PG_M) + PG_UW;		v++;pte++;		MUNLOCK(c); /* unlock page */#else		for (i = 0; i < CLSIZE; i++) {			copyseg((caddr_t)ctob(v+i), (pte+i)->pg_pfnum);			*(int *)(pte+i) |= (PG_V|PG_M) + PG_UW;		}		v += CLSIZE;		c = &cmap[pgtocm(pte->pg_pfnum)];		MUNLOCK(c);		pte += CLSIZE;#endif#ifdef mips		opte += CLSIZE;#endif mips	}	p->p_flag |= SPTECHG;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -