version 1.29, 1999/07/25 06:30:36 |
version 1.29.2.1, 2000/11/20 18:12:00 |
|
|
#include <sys/shm.h> |
#include <sys/shm.h> |
#endif |
#endif |
|
|
#include <vm/vm.h> |
|
#include <vm/vm_page.h> |
|
#include <vm/vm_kern.h> |
|
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
|
#include <machine/cpu.h> |
#include <machine/cpu.h> |
Line 109 int readbuffers = 0; /* allow KGDB to r |
|
Line 105 int readbuffers = 0; /* allow KGDB to r |
|
|
|
|
|
/* |
/* |
* uvm_sleep: atomic unlock and sleep for UVM_UNLOCK_AND_WAIT(). |
|
*/ |
|
|
|
void |
|
uvm_sleep(event, slock, canintr, msg, timo) |
|
void *event; |
|
struct simplelock *slock; |
|
boolean_t canintr; |
|
const char *msg; |
|
int timo; |
|
{ |
|
int s, pri; |
|
|
|
pri = PVM; |
|
if (canintr) |
|
pri |= PCATCH; |
|
|
|
s = splhigh(); |
|
if (slock != NULL) |
|
simple_unlock(slock); |
|
(void) tsleep(event, pri, msg, timo); |
|
splx(s); |
|
} |
|
|
|
/* |
|
* uvm_kernacc: can the kernel access a region of memory |
* uvm_kernacc: can the kernel access a region of memory |
* |
* |
* - called from malloc [DIAGNOSTIC], and /dev/kmem driver (mem.c) |
* - called from malloc [DIAGNOSTIC], and /dev/kmem driver (mem.c) |
Line 149 uvm_kernacc(addr, len, rw) |
|
Line 120 uvm_kernacc(addr, len, rw) |
|
vaddr_t saddr, eaddr; |
vaddr_t saddr, eaddr; |
vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; |
vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; |
|
|
saddr = trunc_page(addr); |
saddr = trunc_page((vaddr_t)addr); |
eaddr = round_page(addr+len); |
eaddr = round_page((vaddr_t)addr+len); |
vm_map_lock_read(kernel_map); |
vm_map_lock_read(kernel_map); |
rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot); |
rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot); |
vm_map_unlock_read(kernel_map); |
vm_map_unlock_read(kernel_map); |
Line 190 uvm_useracc(addr, len, rw) |
|
Line 161 uvm_useracc(addr, len, rw) |
|
map = &curproc->p_vmspace->vm_map; |
map = &curproc->p_vmspace->vm_map; |
|
|
vm_map_lock_read(map); |
vm_map_lock_read(map); |
rv = uvm_map_checkprot(map, trunc_page(addr), round_page(addr+len), |
rv = uvm_map_checkprot(map, trunc_page((vaddr_t)addr), |
prot); |
round_page((vaddr_t)addr+len), prot); |
vm_map_unlock_read(map); |
vm_map_unlock_read(map); |
|
|
return(rv); |
return(rv); |
Line 212 uvm_useracc(addr, len, rw) |
|
Line 183 uvm_useracc(addr, len, rw) |
|
*/ |
*/ |
void |
void |
uvm_chgkprot(addr, len, rw) |
uvm_chgkprot(addr, len, rw) |
register caddr_t addr; |
caddr_t addr; |
size_t len; |
size_t len; |
int rw; |
int rw; |
{ |
{ |
Line 221 uvm_chgkprot(addr, len, rw) |
|
Line 192 uvm_chgkprot(addr, len, rw) |
|
vaddr_t sva, eva; |
vaddr_t sva, eva; |
|
|
prot = rw == B_READ ? VM_PROT_READ : VM_PROT_READ|VM_PROT_WRITE; |
prot = rw == B_READ ? VM_PROT_READ : VM_PROT_READ|VM_PROT_WRITE; |
eva = round_page(addr + len); |
eva = round_page((vaddr_t)addr + len); |
for (sva = trunc_page(addr); sva < eva; sva += PAGE_SIZE) { |
for (sva = trunc_page((vaddr_t)addr); sva < eva; sva += PAGE_SIZE) { |
/* |
/* |
* Extract physical address for the page. |
* Extract physical address for the page. |
* We use a cheezy hack to differentiate physical |
* We use a cheezy hack to differentiate physical |
Line 231 uvm_chgkprot(addr, len, rw) |
|
Line 202 uvm_chgkprot(addr, len, rw) |
|
*/ |
*/ |
if (pmap_extract(pmap_kernel(), sva, &pa) == FALSE) |
if (pmap_extract(pmap_kernel(), sva, &pa) == FALSE) |
panic("chgkprot: invalid page"); |
panic("chgkprot: invalid page"); |
pmap_enter(pmap_kernel(), sva, pa, prot, TRUE, 0); |
pmap_enter(pmap_kernel(), sva, pa, prot, PMAP_WIRED); |
} |
} |
} |
} |
#endif |
#endif |
Line 255 uvm_vslock(p, addr, len, access_type) |
|
Line 226 uvm_vslock(p, addr, len, access_type) |
|
int rv; |
int rv; |
|
|
map = &p->p_vmspace->vm_map; |
map = &p->p_vmspace->vm_map; |
start = trunc_page(addr); |
start = trunc_page((vaddr_t)addr); |
end = round_page(addr + len); |
end = round_page((vaddr_t)addr + len); |
|
|
rv = uvm_fault_wire(map, start, end, access_type); |
rv = uvm_fault_wire(map, start, end, access_type); |
|
|
Line 276 uvm_vsunlock(p, addr, len) |
|
Line 247 uvm_vsunlock(p, addr, len) |
|
caddr_t addr; |
caddr_t addr; |
size_t len; |
size_t len; |
{ |
{ |
uvm_fault_unwire(&p->p_vmspace->vm_map, trunc_page(addr), |
uvm_fault_unwire(&p->p_vmspace->vm_map, trunc_page((vaddr_t)addr), |
round_page(addr+len)); |
round_page((vaddr_t)addr+len)); |
} |
} |
|
|
/* |
/* |
Line 296 uvm_vsunlock(p, addr, len) |
|
Line 267 uvm_vsunlock(p, addr, len) |
|
* than just hang |
* than just hang |
*/ |
*/ |
void |
void |
uvm_fork(p1, p2, shared, stack, stacksize) |
uvm_fork(p1, p2, shared, stack, stacksize, func, arg) |
struct proc *p1, *p2; |
struct proc *p1, *p2; |
boolean_t shared; |
boolean_t shared; |
void *stack; |
void *stack; |
size_t stacksize; |
size_t stacksize; |
|
void (*func) __P((void *)); |
|
void *arg; |
{ |
{ |
struct user *up = p2->p_addr; |
struct user *up = p2->p_addr; |
int rv; |
int rv; |
|
|
if (shared == TRUE) |
if (shared == TRUE) { |
|
p2->p_vmspace = NULL; |
uvmspace_share(p1, p2); /* share vmspace */ |
uvmspace_share(p1, p2); /* share vmspace */ |
else |
} else |
p2->p_vmspace = uvmspace_fork(p1->p_vmspace); /* fork vmspace */ |
p2->p_vmspace = uvmspace_fork(p1->p_vmspace); /* fork vmspace */ |
|
|
/* |
/* |
Line 337 uvm_fork(p1, p2, shared, stack, stacksiz |
|
Line 311 uvm_fork(p1, p2, shared, stack, stacksiz |
|
(caddr_t)&up->u_stats.pstat_startcopy)); |
(caddr_t)&up->u_stats.pstat_startcopy)); |
|
|
/* |
/* |
* cpu_fork will copy and update the kernel stack and pcb, and make |
* cpu_fork() copy and update the pcb, and make the child ready |
* the child ready to run. The child will exit directly to user |
* to run. If this is a normal user fork, the child will exit |
* mode on its first time slice, and will not return here. |
* 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); |
cpu_fork(p1, p2, stack, stacksize, func, arg); |
} |
} |
|
|
/* |
/* |
|
|
|
|
uvmspace_free(p->p_vmspace); |
uvmspace_free(p->p_vmspace); |
uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE); |
uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE); |
|
p->p_addr = NULL; |
} |
} |
|
|
/* |
/* |
|
|
* moved to new physical page(s) (e.g. see mips/mips/vm_machdep.c). |
* moved to new physical page(s) (e.g. see mips/mips/vm_machdep.c). |
*/ |
*/ |
cpu_swapin(p); |
cpu_swapin(p); |
s = splstatclock(); |
SCHED_LOCK(s); |
if (p->p_stat == SRUN) |
if (p->p_stat == SRUN) |
setrunqueue(p); |
setrunqueue(p); |
p->p_flag |= P_INMEM; |
p->p_flag |= P_INMEM; |
splx(s); |
SCHED_UNLOCK(s); |
p->p_swtime = 0; |
p->p_swtime = 0; |
++uvmexp.swapins; |
++uvmexp.swapins; |
} |
} |
|
|
void |
void |
uvm_scheduler() |
uvm_scheduler() |
{ |
{ |
register struct proc *p; |
struct proc *p; |
register int pri; |
int pri; |
struct proc *pp; |
struct proc *pp; |
int ppri; |
int ppri; |
UVMHIST_FUNC("uvm_scheduler"); UVMHIST_CALLED(maphist); |
UVMHIST_FUNC("uvm_scheduler"); UVMHIST_CALLED(maphist); |
|
|
} |
} |
} |
} |
} |
} |
|
/* |
|
* XXXSMP: possible unlock/sleep race between here and the |
|
* "scheduler" tsleep below.. |
|
*/ |
proclist_unlock_read(); |
proclist_unlock_read(); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
|
|
printf("scheduler: no room for pid %d(%s), free %d\n", |
printf("scheduler: no room for pid %d(%s), free %d\n", |
p->p_pid, p->p_comm, uvmexp.free); |
p->p_pid, p->p_comm, uvmexp.free); |
#endif |
#endif |
(void) splhigh(); |
|
uvm_wait("schedpwait"); |
uvm_wait("schedpwait"); |
(void) spl0(); |
|
#ifdef DEBUG |
#ifdef DEBUG |
if (swapdebug & SDB_FOLLOW) |
if (swapdebug & SDB_FOLLOW) |
printf("scheduler: room again, free %d\n", uvmexp.free); |
printf("scheduler: room again, free %d\n", uvmexp.free); |
|
|
void |
void |
uvm_swapout_threads() |
uvm_swapout_threads() |
{ |
{ |
register struct proc *p; |
struct proc *p; |
struct proc *outp, *outp2; |
struct proc *outp, *outp2; |
int outpri, outpri2; |
int outpri, outpri2; |
int didswap = 0; |
int didswap = 0; |
Line 554 uvm_swapout_threads() |
|
Line 533 uvm_swapout_threads() |
|
continue; |
continue; |
switch (p->p_stat) { |
switch (p->p_stat) { |
case SRUN: |
case SRUN: |
|
case SONPROC: |
if (p->p_swtime > outpri2) { |
if (p->p_swtime > outpri2) { |
outp2 = p; |
outp2 = p; |
outpri2 = p->p_swtime; |
outpri2 = p->p_swtime; |
Line 602 uvm_swapout_threads() |
|
Line 582 uvm_swapout_threads() |
|
|
|
static void |
static void |
uvm_swapout(p) |
uvm_swapout(p) |
register struct proc *p; |
struct proc *p; |
{ |
{ |
vaddr_t addr; |
vaddr_t addr; |
int s; |
int s; |
|
|
/* |
/* |
* Mark it as (potentially) swapped out. |
* Mark it as (potentially) swapped out. |
*/ |
*/ |
s = splstatclock(); |
SCHED_LOCK(s); |
p->p_flag &= ~P_INMEM; |
p->p_flag &= ~P_INMEM; |
if (p->p_stat == SRUN) |
if (p->p_stat == SRUN) |
remrunqueue(p); |
remrunqueue(p); |
splx(s); |
SCHED_UNLOCK(s); |
p->p_swtime = 0; |
p->p_swtime = 0; |
++uvmexp.swapouts; |
++uvmexp.swapouts; |
} |
} |