diff options
Diffstat (limited to 'kalloc.c')
-rw-r--r-- | kalloc.c | 89 |
1 files changed, 23 insertions, 66 deletions
@@ -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; } |