xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

kalloc.c (2092B)


      1 // Physical memory allocator, intended to allocate
      2 // memory for user processes, kernel stacks, page table pages,
      3 // and pipe buffers. Allocates 4096-byte pages.
      4 
      5 #include "types.h"
      6 #include "defs.h"
      7 #include "param.h"
      8 #include "memlayout.h"
      9 #include "mmu.h"
     10 #include "spinlock.h"
     11 
     12 void freerange(void *vstart, void *vend);
     13 extern char end[]; // first address after kernel loaded from ELF file
     14 
     15 struct run {
     16   struct run *next;
     17 };
     18 
     19 struct {
     20   struct spinlock lock;
     21   int use_lock;
     22   struct run *freelist;
     23 } kmem;
     24 
     25 // Initialization happens in two phases.
     26 // 1. main() calls kinit1() while still using entrypgdir to place just
     27 // the pages mapped by entrypgdir on free list.
     28 // 2. main() calls kinit2() with the rest of the physical pages
     29 // after installing a full page table that maps them on all cores.
     30 void
     31 kinit1(void *vstart, void *vend)
     32 {
     33   initlock(&kmem.lock, "kmem");
     34   kmem.use_lock = 0;
     35   freerange(vstart, vend);
     36 }
     37 
     38 void
     39 kinit2(void *vstart, void *vend)
     40 {
     41   freerange(vstart, vend);
     42   kmem.use_lock = 1;
     43 }
     44 
     45 void
     46 freerange(void *vstart, void *vend)
     47 {
     48   char *p;
     49   p = (char*)PGROUNDUP((uintp)vstart);
     50   for(; p + PGSIZE <= (char*)vend; p += PGSIZE)
     51     kfree(p);
     52 }
     53 
     54 //PAGEBREAK: 21
     55 // Free the page of physical memory pointed at by v,
     56 // which normally should have been returned by a
     57 // call to kalloc().  (The exception is when
     58 // initializing the allocator; see kinit above.)
     59 void
     60 kfree(char *v)
     61 {
     62   struct run *r;
     63 
     64   if((uintp)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
     65     panic("kfree");
     66 
     67   // Fill with junk to catch dangling refs.
     68   memset(v, 1, PGSIZE);
     69 
     70   if(kmem.use_lock)
     71     acquire(&kmem.lock);
     72   r = (struct run*)v;
     73   r->next = kmem.freelist;
     74   kmem.freelist = r;
     75   if(kmem.use_lock)
     76     release(&kmem.lock);
     77 }
     78 
     79 // Allocate one 4096-byte page of physical memory.
     80 // Returns a pointer that the kernel can use.
     81 // Returns 0 if the memory cannot be allocated.
     82 char*
     83 kalloc(void)
     84 {
     85   struct run *r;
     86 
     87   if(kmem.use_lock)
     88     acquire(&kmem.lock);
     89   r = kmem.freelist;
     90   if(r)
     91     kmem.freelist = r->next;
     92   if(kmem.use_lock)
     93     release(&kmem.lock);
     94   return (char*)r;
     95 }
     96