MIT6.S081 Lab6
Lab6 COW
Copy-on-write on xv6
In this lab, we need to implement COW on xv6. The idea of the lab is quite straight forward but there are some subtle details
needs to be treated carefully.
Main idea of the lab, is to lazily allocate the physical page to child process. This lab takes almost 15h to debug (what fk), so I will give a detailed description of how I code and hope to give a rather clear idea.
- Firstly, define some utils functions to manipulate
refrence count table
- int get_ref(uint64 pa) // return reference count
- int dec_ref(uint64 pa) // decrease reference count
- int safy_inc_ref(uint64 pa) // do increment with lock
- uint64 split_COW(uint64 pa) // return a new page according to the origin physical page
- Define a reference counting table, because physical page used for allocation starts from
KERNBASE
(not so accurate) toPHYSTOP
.- so declear a array with
((PHYSTOP - KERNBASE) / PGSIZE)
elements.
- so declear a array with
- The reference counting scheme:
- Decrease reference count in
kfree()
, once counting number <= 0 (may have negative number because in kinit() kernel will kfree() all pages first) - Set reference count = 1 in
kalloc()
- In the fork()::uvmcopy(), we should do reference increase
- When actually split the COW-page, decrease reference of origin page and alloc a new page.
- Decrease reference count in
Once we decide the scheme, we could modify the uvmcopy() to let it map the new_pagetable to old pa.
1 | int |
In the trap.c:usertrap(), we should handle the page fault like previous lazy allocation lab. So I just skip this part.
Note the check condition should be:va < p->sz && ((pte = walk(pagetable, va, 0)) != 0) && (*pte & PTE_COW) && (*pte & PTE_V)
Then we do the COW split
1 | int do_COW(pagetable_t pagetable, uint64 va){ |
Note we do the reference reduce in cow_split()
and the new page’s reference is set to 1 in kfree()
Finally let’s check the cow_split()
1 | uint64 |
Just add some glue functions like safe_inc_ref
, dec_ref
… don’t forget to modify kfree() and kalloc()
. Then we are done!
![](Lab6 COW/lab6-pic1.png)
Some hints
- Do get pa by
PTE2PA
macro and not useaddrwalk()
because it may return 0 if PTE_U not set. - Use panic to decide some condition shouldn’t happen
- Add locks to reference table, maybe you could try smaller granularity like give each index a lock…