From 7d7dc9331bf33f77c9c3a71350782dadae8dd371 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Tue, 31 Aug 2010 12:54:47 -0400 Subject: [PATCH] kalloc/kfree now only a page at a time do not keep sorted contiguous free list --- defs.h | 5 ++-- kalloc.c | 89 ++++++++++++++----------------------------------------- main.c | 4 +-- mmu.h | 2 +- param.h | 4 +-- pipe.c | 6 ++-- proc.c | 6 ++-- umalloc.c | 4 +-- vm.c | 17 +++++------ 9 files changed, 46 insertions(+), 91 deletions(-) diff --git a/defs.h b/defs.h index 02da96f..ca7367d 100644 --- a/defs.h +++ b/defs.h @@ -60,9 +60,8 @@ extern uchar ioapicid; void ioapicinit(void); // kalloc.c -extern int nfreemem; -char* kalloc(int); -void kfree(char*, int); +char* kalloc(void); +void kfree(char*); void kinit(char*,uint); // kbd.c 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; } diff --git a/main.c b/main.c index 1a49bc6..878ea36 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,7 @@ main(void) void jkstack(void) { - char *kstack = kalloc(PGSIZE); + char *kstack = kalloc(); if (!kstack) panic("jkstack\n"); char *top = kstack + PGSIZE; @@ -92,7 +92,7 @@ bootothers(void) continue; // Fill in %esp, %eip and start code on cpu. - stack = kalloc(KSTACKSIZE); + stack = kalloc(); *(void**)(code-4) = stack + KSTACKSIZE; *(void**)(code-8) = mpmain; lapicstartap(c->id, (uint)code); diff --git a/mmu.h b/mmu.h index f4fc732..db40f25 100644 --- a/mmu.h +++ b/mmu.h @@ -112,7 +112,7 @@ struct segdesc { #define PDXSHIFT 22 // offset of PDX in a linear address #define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1)) -#define PGROUNDDOWN(a) ((char*)((((unsigned int)a) & ~(PGSIZE-1)))) +#define PGROUNDDOWN(a) ((char*)((((unsigned int)(a)) & ~(PGSIZE-1)))) // Page table/directory entry flags. #define PTE_P 0x001 // Present diff --git a/param.h b/param.h index c1959d1..48c3352 100644 --- a/param.h +++ b/param.h @@ -1,6 +1,5 @@ #define NPROC 64 // maximum number of processes -#define PAGE 4096 // conveniently chosen to be equal to PGSIZE -#define KSTACKSIZE PAGE // size of per-process kernel stack +#define KSTACKSIZE 4096 // size of per-process kernel stack #define NCPU 8 // maximum number of CPUs #define NOFILE 16 // open files per process #define NFILE 100 // open files per system @@ -8,3 +7,4 @@ #define NINODE 50 // maximum number of active i-nodes #define NDEV 10 // maximum major device number #define ROOTDEV 1 // device number of file system root disk +#define PHYSTOP 0x1000000 // use phys mem up to here as free pool diff --git a/pipe.c b/pipe.c index 4a1857c..bc847b9 100644 --- a/pipe.c +++ b/pipe.c @@ -27,7 +27,7 @@ pipealloc(struct file **f0, struct file **f1) *f0 = *f1 = 0; if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) goto bad; - if((p = (struct pipe*)kalloc(PAGE)) == 0) + if((p = (struct pipe*)kalloc()) == 0) goto bad; p->readopen = 1; p->writeopen = 1; @@ -47,7 +47,7 @@ pipealloc(struct file **f0, struct file **f1) //PAGEBREAK: 20 bad: if(p) - kfree((char*)p, PAGE); + kfree((char*)p); if(*f0) fileclose(*f0); if(*f1) @@ -68,7 +68,7 @@ pipeclose(struct pipe *p, int writable) } if(p->readopen == 0 && p->writeopen == 0) { release(&p->lock); - kfree((char*)p, PAGE); + kfree((char*)p); } else release(&p->lock); } diff --git a/proc.c b/proc.c index e69bacf..5ac2780 100644 --- a/proc.c +++ b/proc.c @@ -84,7 +84,7 @@ found: release(&ptable.lock); // Allocate kernel stack if possible. - if((p->kstack = kalloc(KSTACKSIZE)) == 0){ + if((p->kstack = kalloc()) == 0){ p->state = UNUSED; return 0; } @@ -169,7 +169,7 @@ fork(void) // Copy process state from p. if (!(np->pgdir = copyuvm(proc->pgdir, proc->sz))) { - kfree(np->kstack, KSTACKSIZE); + kfree(np->kstack); np->kstack = 0; np->state = UNUSED; return -1; @@ -418,7 +418,7 @@ wait(void) if(p->state == ZOMBIE){ // Found one. pid = p->pid; - kfree(p->kstack, KSTACKSIZE); + kfree(p->kstack); p->kstack = 0; freevm(p->pgdir); p->state = UNUSED; diff --git a/umalloc.c b/umalloc.c index afc86a5..4984591 100644 --- a/umalloc.c +++ b/umalloc.c @@ -49,8 +49,8 @@ morecore(uint nu) char *p; Header *hp; - if(nu < PAGE) - nu = PAGE; + if(nu < 4096) + nu = 4096; p = sbrk(nu * sizeof(Header)); if(p == (char*) -1) return 0; diff --git a/vm.c b/vm.c index 262f079..46d18fc 100644 --- a/vm.c +++ b/vm.c @@ -29,7 +29,6 @@ // (both in physical memory and in the kernel's virtual address // space). -#define PHYSTOP 0x1000000 #define USERTOP 0xA0000 static uint kerntext; // Linker starts kernel at 1MB @@ -53,7 +52,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create) pde = &pgdir[PDX(va)]; if (*pde & PTE_P) { pgtab = (pte_t*) PTE_ADDR(*pde); - } else if (!create || !(r = (uint) kalloc(PGSIZE))) + } else if (!create || !(r = (uint) kalloc())) return 0; else { pgtab = (pte_t*) r; @@ -156,7 +155,7 @@ setupkvm(void) pde_t *pgdir; // Allocate page directory - if (!(pgdir = (pde_t *) kalloc(PGSIZE))) + if (!(pgdir = (pde_t *) kalloc())) return 0; memset(pgdir, 0, PGSIZE); // Map IO space from 640K to 1Mbyte @@ -206,7 +205,7 @@ allocuvm(pde_t *pgdir, char *addr, uint sz) for(a = first; a <= last; a += PGSIZE){ pte_t *pte = walkpgdir(pgdir, a, 0); if(pte == 0 || (*pte & PTE_P) == 0){ - char *mem = kalloc(PGSIZE); + char *mem = kalloc(); if(mem == 0){ // XXX clean up? return 0; @@ -235,7 +234,7 @@ deallocuvm(pde_t *pgdir, char *addr, uint sz) uint pa = PTE_ADDR(*pte); if(pa == 0) panic("deallocuvm"); - kfree((void *) pa, PGSIZE); + kfree((void *) pa); *pte = 0; } } @@ -260,15 +259,15 @@ freevm(pde_t *pgdir) uint pa = PTE_ADDR(pgtab[j]); uint va = PGADDR(i, j, 0); if (va < USERTOP) // user memory - kfree((void *) pa, PGSIZE); + kfree((void *) pa); pgtab[j] = 0; } } - kfree((void *) da, PGSIZE); + kfree((void *) da); pgdir[i] = 0; } } - kfree((void *) pgdir, PGSIZE); + kfree((void *) pgdir); } int @@ -324,7 +323,7 @@ copyuvm(pde_t *pgdir, uint sz) panic("copyuvm: pte should exist\n"); if(*pte & PTE_P){ pa = PTE_ADDR(*pte); - if (!(mem = kalloc(PGSIZE))) + if (!(mem = kalloc())) return 0; memmove(mem, (char *)pa, PGSIZE); if (!mappages(d, (void *)i, PGSIZE, PADDR(mem), PTE_W|PTE_U))