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 + -
显示快捷键?