summaryrefslogtreecommitdiff
path: root/kernel/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/proc.c')
-rw-r--r--kernel/proc.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/kernel/proc.c b/kernel/proc.c
index 58a8a0b..9a9bae9 100644
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -39,6 +39,7 @@ proc_mapstacks(pagetable_t kpgtbl)
if(pa == 0)
panic("kalloc");
uint64 va = KSTACK((int) (p - proc));
+ p->alarm_tickspassed = 0;
kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W);
}
}
@@ -132,6 +133,25 @@ found:
return 0;
}
+ // Allocate a usyscall page and fill pid.
+ if((p->usyscall = (struct usyscall *)kalloc()) == 0){
+ freeproc(p);
+ release(&p->lock);
+ return 0;
+ }
+ p->usyscall->pid = p->pid;
+
+ // reset sigalarm props
+ p->alarm_interval = 0;
+ p->alarm_handler = 0;
+ p->alarm_tickspassed = 0;
+ p->alarm_caninvoke = 1;
+ if((p->atpfm = (struct trapframe *)kalloc()) == 0){
+ freeproc(p);
+ release(&p->lock);
+ return 0;
+ }
+
// An empty user page table.
p->pagetable = proc_pagetable(p);
if(p->pagetable == 0){
@@ -158,8 +178,18 @@ freeproc(struct proc *p)
if(p->trapframe)
kfree((void*)p->trapframe);
p->trapframe = 0;
+ if(p->usyscall)
+ kfree((void*)p->usyscall);
+ p->usyscall = 0;
if(p->pagetable)
proc_freepagetable(p->pagetable, p->sz);
+ if(p->atpfm)
+ kfree((void*)p->atpfm);
+ p->atpfm = 0;
+ p->alarm_interval = 0;
+ p->alarm_handler = 0;
+ p->alarm_tickspassed = 0;
+ p->alarm_caninvoke = 1;
p->pagetable = 0;
p->sz = 0;
p->pid = 0;
@@ -172,7 +202,7 @@ freeproc(struct proc *p)
}
// Create a user page table for a given process, with no user memory,
-// but with trampoline and trapframe pages.
+// but with trampoline, trapframe and usyscall pages.
pagetable_t
proc_pagetable(struct proc *p)
{
@@ -202,6 +232,14 @@ proc_pagetable(struct proc *p)
return 0;
}
+ // map the usyscall page below the trapframe page, for
+ // ugetpid().
+ if(mappages(pagetable, USYSCALL, PGSIZE,
+ (uint64)(p->usyscall), PTE_R | PTE_U) < 0){
+ uvmunmap(pagetable, USYSCALL, 1, 0);
+ uvmfree(pagetable, 0);
+ return 0;
+ }
return pagetable;
}
@@ -212,6 +250,7 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz)
{
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
uvmunmap(pagetable, TRAPFRAME, 1, 0);
+ uvmunmap(pagetable, USYSCALL, 1, 0);
uvmfree(pagetable, sz);
}
@@ -299,6 +338,9 @@ fork(void)
// copy saved user registers.
*(np->trapframe) = *(p->trapframe);
+ // inherit trace_mask
+ np->trace_mask = p->trace_mask;
+
// Cause fork to return 0 in the child.
np->trapframe->a0 = 0;
@@ -686,3 +728,43 @@ procdump(void)
printf("\n");
}
}
+
+int
+get_nproc(void)
+{
+ int n = 0;
+ struct proc *p;
+
+ for(int i = 0; i < NPROC; i++) {
+ p = &proc[i];
+ acquire(&p->lock);
+ if(p->state != UNUSED)
+ n++;
+ release(&p->lock);
+ }
+
+ return n;
+}
+
+// lab pagetable: report which pages have been accessed (r/w)
+// according to PTE_A and store it in a bit mask (3rd param)
+int
+pgaccess(uint64 base, int len, uint64 mask_addr)
+{
+ struct proc *p = myproc();
+ pagetable_t pgtbl = p->pagetable;
+ pte_t *pte;
+ int mask = 0;
+
+ // iterater thru pages
+ for(int i = 0; i < len; i++) {
+ pte = walk(pgtbl, base + i * PGSIZE, 0);
+ if(*pte & PTE_A) {
+ *pte &= (~PTE_A); // clear PTE_A to avoid setting it forever
+ mask |= (1L << i);
+ }
+ }
+
+ // now copyout the mask to user memory
+ return copyout(pgtbl, mask_addr, (char *)&mask, sizeof(mask));
+}