xref: /xv6-public/kalloc.c (revision 4638cabf)
1f5527388Srsc // Physical memory allocator, intended to allocate
27d7dc933SRobert Morris // memory for user processes, kernel stacks, page table pages,
37d7dc933SRobert Morris // and pipe buffers. Allocates 4096-byte pages.
455e95b16Srtm 
555e95b16Srtm #include "types.h"
655e95b16Srtm #include "defs.h"
78148b6eeSrtm #include "param.h"
89aa0337dSFrans Kaashoek #include "memlayout.h"
940889627SFrans Kaashoek #include "mmu.h"
104e8f237bSrtm #include "spinlock.h"
114e8f237bSrtm 
12c092540eSRobert Morris void freerange(void *vstart, void *vend);
13c092540eSRobert Morris extern char end[]; // first address after kernel loaded from ELF file
14*da3b931dSFrans Kaashoek                    // defined by the kernel linker script in kernel.ld
15c092540eSRobert Morris 
1655e95b16Srtm struct run {
1755e95b16Srtm   struct run *next;
1855e95b16Srtm };
1934295f46Srsc 
2034295f46Srsc struct {
2134295f46Srsc   struct spinlock lock;
22c092540eSRobert Morris   int use_lock;
2355e95b16Srtm   struct run *freelist;
2434295f46Srsc } kmem;
2555e95b16Srtm 
26c092540eSRobert Morris // Initialization happens in two phases.
27c092540eSRobert Morris // 1. main() calls kinit1() while still using entrypgdir to place just
28c092540eSRobert Morris // the pages mapped by entrypgdir on free list.
29c092540eSRobert Morris // 2. main() calls kinit2() with the rest of the physical pages
30c092540eSRobert Morris // after installing a full page table that maps them on all cores.
31c092540eSRobert Morris void
kinit1(void * vstart,void * vend)32c092540eSRobert Morris kinit1(void *vstart, void *vend)
339aa0337dSFrans Kaashoek {
34c092540eSRobert Morris   initlock(&kmem.lock, "kmem");
35c092540eSRobert Morris   kmem.use_lock = 0;
36c092540eSRobert Morris   freerange(vstart, vend);
379aa0337dSFrans Kaashoek }
384587b358SRobert Morris 
3955e95b16Srtm void
kinit2(void * vstart,void * vend)40c092540eSRobert Morris kinit2(void *vstart, void *vend)
41c092540eSRobert Morris {
42c092540eSRobert Morris   freerange(vstart, vend);
43c092540eSRobert Morris   kmem.use_lock = 1;
44c092540eSRobert Morris }
45c092540eSRobert Morris 
46c092540eSRobert Morris void
freerange(void * vstart,void * vend)47c092540eSRobert Morris freerange(void *vstart, void *vend)
4855e95b16Srtm {
491a81e38bSRuss Cox   char *p;
50c092540eSRobert Morris   p = (char*)PGROUNDUP((uint)vstart);
51c092540eSRobert Morris   for(; p + PGSIZE <= (char*)vend; p += PGSIZE)
523597d5dcSRobert Morris     kfree(p);
5355e95b16Srtm }
545048762cSAustin Clements //PAGEBREAK: 21
557d7dc933SRobert Morris // Free the page of physical memory pointed at by v,
5631085bb4Srsc // which normally should have been returned by a
577d7dc933SRobert Morris // call to kalloc().  (The exception is when
5831085bb4Srsc // initializing the allocator; see kinit above.)
5955e95b16Srtm void
kfree(char * v)607d7dc933SRobert Morris kfree(char *v)
6155e95b16Srtm {
627d7dc933SRobert Morris   struct run *r;
6355e95b16Srtm 
64a7c03bd9SRobert Morris   if((uint)v % PGSIZE || v < end || V2P(v) >= PHYSTOP)
6555e95b16Srtm     panic("kfree");
6655e95b16Srtm 
67d4c64e5dSrsc   // Fill with junk to catch dangling refs.
687d7dc933SRobert Morris   memset(v, 1, PGSIZE);
698b4e2a08Srtm 
70c092540eSRobert Morris   if(kmem.use_lock)
7134295f46Srsc     acquire(&kmem.lock);
727d7dc933SRobert Morris   r = (struct run*)v;
737d7dc933SRobert Morris   r->next = kmem.freelist;
747d7dc933SRobert Morris   kmem.freelist = r;
75c092540eSRobert Morris   if(kmem.use_lock)
7634295f46Srsc     release(&kmem.lock);
7755e95b16Srtm }
7855e95b16Srtm 
797d7dc933SRobert Morris // Allocate one 4096-byte page of physical memory.
807d7dc933SRobert Morris // Returns a pointer that the kernel can use.
81f5527388Srsc // Returns 0 if the memory cannot be allocated.
8255e95b16Srtm char*
kalloc(void)831a81e38bSRuss Cox kalloc(void)
8455e95b16Srtm {
857d7dc933SRobert Morris   struct run *r;
8655e95b16Srtm 
87c092540eSRobert Morris   if(kmem.use_lock)
8834295f46Srsc     acquire(&kmem.lock);
897d7dc933SRobert Morris   r = kmem.freelist;
907d7dc933SRobert Morris   if(r)
917d7dc933SRobert Morris     kmem.freelist = r->next;
92c092540eSRobert Morris   if(kmem.use_lock)
9334295f46Srsc     release(&kmem.lock);
947d7dc933SRobert Morris   return (char*)r;
9555e95b16Srtm }
9640889627SFrans Kaashoek 
97