diff options
author | Mole Shang <[email protected]> | 2024-02-13 19:39:56 +0800 |
---|---|---|
committer | Mole Shang <[email protected]> | 2024-02-13 19:39:56 +0800 |
commit | 89ef6f717ed4b3e702e5f6f906f58fe1ea27d366 (patch) | |
tree | 760cce316675479a6cca77551438e8d2cc5fe9ae /kernel/kalloc.c | |
parent | cfae93475dfb4cb5cfe264f4c029136e1447c262 (diff) | |
parent | 4a6593f1a6f666c618d303a4858c4c6d31b41c63 (diff) | |
download | xv6-labs-89ef6f717ed4b3e702e5f6f906f58fe1ea27d366.tar.gz xv6-labs-89ef6f717ed4b3e702e5f6f906f58fe1ea27d366.tar.bz2 xv6-labs-89ef6f717ed4b3e702e5f6f906f58fe1ea27d366.zip |
Merge branch 'cow' into net
Conflicts:
.gitignore
Makefile
conf/lab.mk
kernel/defs.h
kernel/syscall.c
kernel/vm.c
user/pingpong.c
user/user.h
user/usys.pl
Diffstat (limited to 'kernel/kalloc.c')
-rw-r--r-- | kernel/kalloc.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/kernel/kalloc.c b/kernel/kalloc.c index 0699e7e..581f0f6 100644 --- a/kernel/kalloc.c +++ b/kernel/kalloc.c @@ -23,10 +23,41 @@ struct { struct run *freelist; } kmem; +int phypg_refcnt[PHYSTOP/PGSIZE]; + +// Increase the refcnt +int +refcnt_inc(uint64 pa) +{ + acquire(&kmem.lock); + int *prefcnt = &phypg_refcnt[pa/PGSIZE]; + if(pa > PHYSTOP || *prefcnt < 1) + panic("increase refcnt"); + (*prefcnt)++; + release(&kmem.lock); + return *prefcnt; +} + +// Decrease the refcnt +int +refcnt_dec(uint64 pa) +{ + acquire(&kmem.lock); + int *prefcnt = &phypg_refcnt[pa/PGSIZE]; + if(pa > PHYSTOP || *prefcnt < 1) + panic("decrease refcnt"); + (*prefcnt)--; + release(&kmem.lock); + return *prefcnt; +} + void kinit() { initlock(&kmem.lock, "kmem"); + // init all refcnt to 1, which would later be freed to 0 by kfree() + for(uint64 p = PGROUNDUP((uint64)end); p + PGSIZE <= PHYSTOP; p += PGSIZE) + phypg_refcnt[p/PGSIZE] = 1; freerange(end, (void*)PHYSTOP); } @@ -51,6 +82,12 @@ kfree(void *pa) if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP) panic("kfree"); + refcnt_dec((uint64)pa); + + if(phypg_refcnt[(uint64)pa/PGSIZE] > 0) + // We still have refs to this phy page, do not actually free it + return; + // Fill with junk to catch dangling refs. memset(pa, 1, PGSIZE); @@ -72,11 +109,29 @@ kalloc(void) acquire(&kmem.lock); r = kmem.freelist; - if(r) + if(r){ + if(phypg_refcnt[(uint64)r/PGSIZE]) + panic("kalloc: invalid refcnt"); + phypg_refcnt[(uint64)r/PGSIZE] = 1; kmem.freelist = r->next; + } release(&kmem.lock); if(r) memset((char*)r, 5, PGSIZE); // fill with junk return (void*)r; } + +int +get_freemem(void) +{ + int n; + struct run *r; + + acquire(&kmem.lock); + for (n = 0, r = kmem.freelist; r; r = r->next) + n++; + release(&kmem.lock); + + return n * PGSIZE; +} |