summaryrefslogtreecommitdiff
path: root/kalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kalloc.c')
-rw-r--r--kalloc.c89
1 files changed, 23 insertions, 66 deletions
diff --git a/kalloc.c b/kalloc.c
index ca87018..65de759 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -1,8 +1,6 @@
// Physical memory allocator, intended to allocate
-// memory for user processes. Allocates in 4096-byte pages.
-// Free list is kept sorted and combines adjacent pages into
-// long runs, to make it easier to allocate big segments.
-// This combining is not useful now that xv6 uses paging.
+// memory for user processes, kernel stacks, page table pages,
+// and pipe buffers. Allocates 4096-byte pages.
#include "types.h"
#include "defs.h"
@@ -12,7 +10,6 @@
struct run {
struct run *next;
- int len; // bytes
};
struct {
@@ -20,92 +17,52 @@ struct {
struct run *freelist;
} kmem;
-int nfreemem;
-
// Initialize free list of physical pages.
void
kinit(char *p, uint len)
{
initlock(&kmem.lock, "kmem");
- nfreemem = 0;
- kfree(p, len);
+ char *p1 = (char*)PGROUNDUP((uint)p);
+ char *p2 = PGROUNDDOWN(p + len);
+ for( ; p1 < p2; p1 += 4096)
+ kfree(p1);
}
-// Free the len bytes of memory pointed at by v,
+// Free the page of physical memory pointed at by v,
// which normally should have been returned by a
-// call to kalloc(len). (The exception is when
+// call to kalloc(). (The exception is when
// initializing the allocator; see kinit above.)
void
-kfree(char *v, int len)
+kfree(char *v)
{
- struct run *r, *rend, **rp, *p, *pend;
+ struct run *r;
- if(len <= 0 || len % PGSIZE)
+ if(((uint) v) % PGSIZE || (uint)v < 1024*1024 || (uint)v >= PHYSTOP)
panic("kfree");
// Fill with junk to catch dangling refs.
- memset(v, 1, len);
+ memset(v, 1, PGSIZE);
acquire(&kmem.lock);
- nfreemem += len;
- p = (struct run*)v;
- pend = (struct run*)(v + len);
- for(rp=&kmem.freelist; (r=*rp) != 0 && r <= pend; rp=&r->next){
- rend = (struct run*)((char*)r + r->len);
- if(r <= p && p < rend) {
- cprintf("freeing a free page: r = 0x%x p = 0x%x rend = 0x%x\n",
- r, p, rend);
- panic("freeing free page");
- }
- if(rend == p){ // r before p: expand r to include p
- r->len += len;
- if(r->next && r->next == pend){ // r now next to r->next?
- r->len += r->next->len;
- r->next = r->next->next;
- }
- goto out;
- }
- if(pend == r){ // p before r: expand p to include, replace r
- p->len = len + r->len;
- p->next = r->next;
- *rp = p;
- goto out;
- }
- }
- // Insert p before r in list.
- p->len = len;
- p->next = r;
- *rp = p;
-
- out:
+ r = (struct run *) v;
+ r->next = kmem.freelist;
+ kmem.freelist = r;
release(&kmem.lock);
}
-// Allocate n bytes of physical memory.
-// Returns a kernel-segment pointer.
+// Allocate one 4096-byte page of physical memory.
+// Returns a pointer that the kernel can use.
// Returns 0 if the memory cannot be allocated.
char*
-kalloc(int n)
+kalloc()
{
- char *p;
- struct run *r, **rp;
-
- if(n % PGSIZE || n <= 0)
- panic("kalloc");
+ struct run *r;
acquire(&kmem.lock);
- for(rp=&kmem.freelist; (r=*rp) != 0; rp=&r->next){
- if(r->len >= n){
- r->len -= n;
- p = (char*)r + r->len;
- if(r->len == 0)
- *rp = r->next;
- nfreemem -= n;
- release(&kmem.lock);
- return p;
- }
- }
+ r = kmem.freelist;
+ if(r)
+ kmem.freelist = r->next;
release(&kmem.lock);
- return 0;
+ return (char*) r;
}