cowtest passed
This commit is contained in:
@@ -8,12 +8,23 @@
|
||||
#include "spinlock.h"
|
||||
#include "riscv.h"
|
||||
#include "defs.h"
|
||||
|
||||
void freerange(void *pa_start, void *pa_end);
|
||||
uint64 getRefIdx(uint64 pa);
|
||||
|
||||
struct spinlock reference_lock; // 加锁
|
||||
int pm_reference[(PHYSTOP - KERNBASE)/PGSIZE]; // 记录物理页的引用计数
|
||||
|
||||
extern char end[]; // first address after kernel.
|
||||
// defined by kernel.ld.
|
||||
|
||||
// va映射为idx
|
||||
uint64
|
||||
getRefIdx(uint64 pa)
|
||||
{
|
||||
return (pa-KERNBASE)/PGSIZE;
|
||||
}
|
||||
|
||||
|
||||
struct run {
|
||||
struct run *next;
|
||||
};
|
||||
@@ -27,6 +38,7 @@ void
|
||||
kinit()
|
||||
{
|
||||
initlock(&kmem.lock, "kmem");
|
||||
initlock(&reference_lock, "pm_reference");
|
||||
freerange(end, (void*)PHYSTOP);
|
||||
}
|
||||
|
||||
@@ -51,15 +63,19 @@ kfree(void *pa)
|
||||
if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)
|
||||
panic("kfree");
|
||||
|
||||
// Fill with junk to catch dangling refs.
|
||||
memset(pa, 1, PGSIZE);
|
||||
acquire(&reference_lock);
|
||||
pm_reference[getRefIdx((uint64)pa)] --;
|
||||
if(pm_reference[getRefIdx((uint64)pa)] <= 0){
|
||||
// Fill with junk to catch dangling refs.
|
||||
memset(pa, 1, PGSIZE);
|
||||
r = (struct run*)pa;
|
||||
acquire(&kmem.lock);
|
||||
r->next = kmem.freelist;
|
||||
kmem.freelist = r;
|
||||
release(&kmem.lock);
|
||||
}
|
||||
|
||||
r = (struct run*)pa;
|
||||
|
||||
acquire(&kmem.lock);
|
||||
r->next = kmem.freelist;
|
||||
kmem.freelist = r;
|
||||
release(&kmem.lock);
|
||||
release(&reference_lock);
|
||||
}
|
||||
|
||||
// Allocate one 4096-byte page of physical memory.
|
||||
@@ -76,7 +92,43 @@ kalloc(void)
|
||||
kmem.freelist = r->next;
|
||||
release(&kmem.lock);
|
||||
|
||||
if(r)
|
||||
if(r){
|
||||
memset((char*)r, 5, PGSIZE); // fill with junk
|
||||
pm_reference[getRefIdx((uint64) r)] = 1;
|
||||
}
|
||||
return (void*)r;
|
||||
}
|
||||
|
||||
// reference操作
|
||||
void
|
||||
reference_operation(void* pa, int op)
|
||||
{
|
||||
acquire(&reference_lock);
|
||||
if(op) pm_reference[getRefIdx((uint64)pa)]++;
|
||||
else pm_reference[getRefIdx((uint64)pa)]--;
|
||||
release(&reference_lock);
|
||||
}
|
||||
|
||||
void*
|
||||
cowcopy_pa(void* pa){
|
||||
acquire(&reference_lock);
|
||||
if(pm_reference[getRefIdx((uint64)pa)] <= 1){
|
||||
release(&reference_lock);
|
||||
return pa;
|
||||
}
|
||||
|
||||
char* new = kalloc();
|
||||
if(new == 0){
|
||||
release(&reference_lock);
|
||||
panic("out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memmove((void*)new, pa, PGSIZE);
|
||||
|
||||
// 变更引用计数
|
||||
pm_reference[getRefIdx((uint64)pa)] --;
|
||||
release(&reference_lock);
|
||||
return (void*)new;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user