uvm_glue.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 625 行 · 第 1/2 页

C
625
字号
	 * cpu_fork() copy and update the pcb, and make the child ready	 * to run.  If this is a normal user fork, the child will exit	 * directly to user mode via child_return() on its first time	 * slice and will not return here.  If this is a kernel thread,	 * the specified entry point will be executed.	 */	cpu_fork(p1, p2, stack, stacksize, func, arg);}/* * uvm_exit: exit a virtual address space * * - the process passed to us is a dead (pre-zombie) process; we *   are running on a different context now (the reaper). * - we must run in a separate thread because freeing the vmspace *   of the dead process may block. */voiduvm_exit(p)	struct proc *p;{	vaddr_t va = (vaddr_t)p->p_addr;	uvmspace_free(p->p_vmspace);	p->p_flag &= ~P_INMEM;	uvm_fault_unwire(kernel_map, va, va + USPACE);	uvm_km_free(kernel_map, va, USPACE);	p->p_addr = NULL;}/* * uvm_init_limit: init per-process VM limits * * - called for process 0 and then inherited by all others. */voiduvm_init_limits(p)	struct proc *p;{	/*	 * Set up the initial limits on process VM.  Set the maximum	 * resident set size to be all of (reasonably) available memory.	 * This causes any single, large process to start random page	 * replacement once it fills memory.	 */	p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ;	p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ;	p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ;	p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ;	p->p_rlimit[RLIMIT_RSS].rlim_cur = ptoa(uvmexp.free);}#ifdef DEBUGint	enableswap = 1;int	swapdebug = 0;#define	SDB_FOLLOW	1#define SDB_SWAPIN	2#define SDB_SWAPOUT	4#endif/* * uvm_swapin: swap in a process's u-area. */voiduvm_swapin(p)	struct proc *p;{	vaddr_t addr;	int s;	addr = (vaddr_t)p->p_addr;	/* make P_INMEM true */	uvm_fault_wire(kernel_map, addr, addr + USPACE,	    VM_PROT_READ | VM_PROT_WRITE);	/*	 * Some architectures need to be notified when the user area has	 * moved to new physical page(s) (e.g.  see mips/mips/vm_machdep.c).	 */	cpu_swapin(p);	SCHED_LOCK(s);	if (p->p_stat == SRUN)		setrunqueue(p);	p->p_flag |= P_INMEM;	SCHED_UNLOCK(s);	p->p_swtime = 0;	++uvmexp.swapins;}/* * uvm_scheduler: process zero main loop * * - attempt to swapin every swaped-out, runnable process in order of *	priority. * - if not enough memory, wake the pagedaemon and let it clear space. */voiduvm_scheduler(){	struct proc *p;	int pri;	struct proc *pp;	int ppri;loop:#ifdef DEBUG	while (!enableswap)		tsleep(&proc0, PVM, "noswap", 0);#endif	pp = NULL;		/* process to choose */	ppri = INT_MIN;	/* its priority */	proclist_lock_read();	LIST_FOREACH(p, &allproc, p_list) {		/* is it a runnable swapped out process? */		if (p->p_stat == SRUN && (p->p_flag & P_INMEM) == 0) {			pri = p->p_swtime + p->p_slptime -			    (p->p_nice - NZERO) * 8;			if (pri > ppri) {   /* higher priority?  remember it. */				pp = p;				ppri = pri;			}		}	}	/*	 * XXXSMP: possible unlock/sleep race between here and the	 * "scheduler" tsleep below..	 */	proclist_unlock_read();#ifdef DEBUG	if (swapdebug & SDB_FOLLOW)		printf("scheduler: running, procp %p pri %d\n", pp, ppri);#endif	/*	 * Nothing to do, back to sleep	 */	if ((p = pp) == NULL) {		tsleep(&proc0, PVM, "scheduler", 0);		goto loop;	}	/*	 * we have found swapped out process which we would like to bring	 * back in.	 *	 * XXX: this part is really bogus cuz we could deadlock on memory	 * despite our feeble check	 */	if (uvmexp.free > atop(USPACE)) {#ifdef DEBUG		if (swapdebug & SDB_SWAPIN)			printf("swapin: pid %d(%s)@%p, pri %d free %d\n",	     p->p_pid, p->p_comm, p->p_addr, ppri, uvmexp.free);#endif		uvm_swapin(p);		goto loop;	}	/*	 * not enough memory, jab the pageout daemon and wait til the coast	 * is clear	 */#ifdef DEBUG	if (swapdebug & SDB_FOLLOW)		printf("scheduler: no room for pid %d(%s), free %d\n",	   p->p_pid, p->p_comm, uvmexp.free);#endif	uvm_wait("schedpwait");#ifdef DEBUG	if (swapdebug & SDB_FOLLOW)		printf("scheduler: room again, free %d\n", uvmexp.free);#endif	goto loop;}/* * swappable: is process "p" swappable? */#define	swappable(p)							\	(((p)->p_flag & (P_SYSTEM | P_INMEM | P_WEXIT)) == P_INMEM &&	\	 (p)->p_holdcnt == 0)/* * swapout_threads: find threads that can be swapped and unwire their *	u-areas. * * - called by the pagedaemon * - try and swap at least one processs * - processes that are sleeping or stopped for maxslp or more seconds *   are swapped... otherwise the longest-sleeping or stopped process *   is swapped, otherwise the longest resident process... */voiduvm_swapout_threads(){	struct proc *p;	struct proc *outp, *outp2;	int outpri, outpri2;	int didswap = 0;	extern int maxslp; 	/* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */#ifdef DEBUG	if (!enableswap)		return;#endif	/*	 * outp/outpri  : stop/sleep process with largest sleeptime < maxslp	 * outp2/outpri2: the longest resident process (its swap time)	 */	outp = outp2 = NULL;	outpri = outpri2 = 0;	proclist_lock_read();	LIST_FOREACH(p, &allproc, p_list) {		if (!swappable(p))			continue;		switch (p->p_stat) {		case SRUN:		case SONPROC:			if (p->p_swtime > outpri2) {				outp2 = p;				outpri2 = p->p_swtime;			}			continue;					case SSLEEP:		case SSTOP:			if (p->p_slptime >= maxslp) {				uvm_swapout(p);				didswap++;			} else if (p->p_slptime > outpri) {				outp = p;				outpri = p->p_slptime;			}			continue;		}	}	proclist_unlock_read();	/*	 * If we didn't get rid of any real duds, toss out the next most	 * likely sleeping/stopped or running candidate.  We only do this	 * if we are real low on memory since we don't gain much by doing	 * it (USPACE bytes).	 */	if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE))) {		if ((p = outp) == NULL)			p = outp2;#ifdef DEBUG		if (swapdebug & SDB_SWAPOUT)			printf("swapout_threads: no duds, try procp %p\n", p);#endif		if (p)			uvm_swapout(p);	}	pmap_update();}/* * uvm_swapout: swap out process "p" * * - currently "swapout" means "unwire U-area" and "pmap_collect()"  *   the pmap. * - XXXCDC: should deactivate all process' private anonymous memory */static voiduvm_swapout(p)	struct proc *p;{	vaddr_t addr;	int s;#ifdef DEBUG	if (swapdebug & SDB_SWAPOUT)		printf("swapout: pid %d(%s)@%p, stat %x pri %d free %d\n",	   p->p_pid, p->p_comm, p->p_addr, p->p_stat,	   p->p_slptime, uvmexp.free);#endif	/*	 * Do any machine-specific actions necessary before swapout.	 * This can include saving floating point state, etc.	 */	cpu_swapout(p);	/*	 * Mark it as (potentially) swapped out.	 */	SCHED_LOCK(s);	p->p_flag &= ~P_INMEM;	if (p->p_stat == SRUN)		remrunqueue(p);	SCHED_UNLOCK(s);	p->p_swtime = 0;	++uvmexp.swapouts;	/*	 * Unwire the to-be-swapped process's user struct and kernel stack.	 */	addr = (vaddr_t)p->p_addr;	uvm_fault_unwire(kernel_map, addr, addr + USPACE); /* !P_INMEM */	pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map));}

⌨️ 快捷键说明

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