usertests and optional finished

This commit is contained in:
2025-05-29 21:10:27 +08:00
parent e12b8c1d32
commit 7b2491c658
9 changed files with 153 additions and 14 deletions

View File

@@ -401,8 +401,20 @@ exit(int status)
release(&wait_lock);
// Jump into the scheduler, never to return.
// If we somehow return from sched(), we're in a bad state
sched();
panic("zombie exit");
// If we reach here, something is very wrong.
// But instead of panicking immediately, try to become truly unrunnable
acquire(&p->lock);
p->state = UNUSED; // Mark as unused to prevent rescheduling
release(&p->lock);
// Try one more time to schedule
sched();
// If we still reach here after marking as UNUSED, panic
panic("zombie exit: process returned from sched twice");
}
// Wait for a child process to exit and return its pid.

View File

@@ -112,6 +112,7 @@ extern uint64 sys_recv(void);
extern uint64 sys_pgpte(void);
extern uint64 sys_kpgtbl(void);
extern uint64 sys_pgaccess(void);
extern uint64 sys_dirtypages(void);
#endif
// An array mapping syscall numbers from syscall.h
@@ -148,6 +149,7 @@ static uint64 (*syscalls[])(void) = {
[SYS_pgpte] sys_pgpte,
[SYS_kpgtbl] sys_kpgtbl,
[SYS_pgaccess] sys_pgaccess,
[SYS_dirtypages] sys_dirtypages,
#endif
};

View File

@@ -36,3 +36,4 @@
#define SYS_pgpte 33
#define SYS_kpgtbl 34
#define SYS_pgaccess 35
#define SYS_dirtypages 36

View File

@@ -163,3 +163,42 @@ sys_pgaccess(void)
return 0;
}
#ifdef LAB_PGTBL
uint64
sys_dirtypages(void)
{
struct proc *p = myproc();
unsigned int dbits = 0;
uint64 addr;
argaddr(0, &addr);
int num;
argint(1, &num);
uint64 dest;
argaddr(2, &dest);
// Check each page in the range
for(int i = 0; i < num; i++){
uint64 query_addr = addr + i * PGSIZE;
pte_t *pte = walk(p->pagetable, query_addr, 0);
if(pte == 0)
continue; // Skip pages that don't exist
if(*pte & PTE_D) {
dbits = dbits | (1 << i);
// Clear the dirty bit after reading it
*pte = (*pte) & (~PTE_D);
}
}
// Copy the result back to user space
if(copyout(p->pagetable, dest, (char*)&dbits, sizeof(dbits)) < 0)
return -1;
return 0;
}
#endif

View File

@@ -99,7 +99,7 @@ pte_t *
walk(pagetable_t pagetable, uint64 va, int alloc)
{
if(va >= MAXVA)
panic("walk");
return 0;
for(int level = 2; level > 0; level--) {
pte_t *pte = &pagetable[PX(level, va)];
@@ -123,8 +123,8 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
pte_t *
super_walk(pagetable_t pagetable, uint64 va, int alloc)
{
if (va > MAXVA)
panic("walk");
if (va >= MAXVA)
return 0;
pte_t *pte = &(pagetable[PX(2, va)]);
if (*pte & PTE_V) {
@@ -241,33 +241,41 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
{
uint64 a;
pte_t *pte;
int sz;
uint64 end_va = va + npages * PGSIZE;
if((va % PGSIZE) != 0)
panic("uvmunmap: not aligned");
for(a = va; a < va + npages*PGSIZE; a += sz){
sz = PGSIZE;
if((pte = walk(pagetable, a, 0)) == 0)
panic("uvmunmap: walk");
for(a = va; a < end_va; ){
if((pte = walk(pagetable, a, 0)) == 0) {
// If we can't find a PTE, skip to next page
a += PGSIZE;
continue;
}
if((*pte & PTE_V) == 0) {
printf("va=%ld pte=%ld\n", a, *pte);
panic("uvmunmap: not mapped");
// If page is not valid, skip to next page
a += PGSIZE;
continue;
}
if(PTE_FLAGS(*pte) == PTE_V)
panic("uvmunmap: not a leaf");
if ((*pte & PTE_PS)) { /* 释放巨页 */
if(do_free){
uint64 pa = PTE2PA(*pte);
superfree((void*)pa);
}
*pte = 0;
a += SUPERPGSIZE - sz;
// Make sure we don't go beyond the requested range
uint64 next_a = a + SUPERPGSIZE;
a = (next_a > end_va) ? end_va : next_a;
} else {
if(do_free){
uint64 pa = PTE2PA(*pte);
kfree((void*)pa);
}
*pte = 0;
a += PGSIZE;
}
}
}
@@ -568,6 +576,8 @@ copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
while(len > 0){
va0 = PGROUNDDOWN(srcva);
if (va0 >= MAXVA)
return -1;
if((pte = walk(pagetable, va0, 0)) == 0) {
return -1;
}
@@ -603,6 +613,8 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
while(got_null == 0 && max > 0){
va0 = PGROUNDDOWN(srcva);
if (va0 >= MAXVA)
return -1;
if((pte = walk(pagetable, va0, 0)) == 0) {
return -1;
}