xref: /xv6-public/kalloc.c (revision da3b931d)
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                    // defined by the kernel linker script in kernel.ld
15 
16 struct run {
17   struct run *next;
18 };
19 
20 struct {
21   struct spinlock lock;
22   int use_lock;
23   struct run *freelist;
24 } kmem;
25 
26 // Initialization happens in two phases.
27 // 1. main() calls kinit1() while still using entrypgdir to place just
28 // the pages mapped by entrypgdir on free list.
29 // 2. main() calls kinit2() with the rest of the physical pages
30 // after installing a full page table that maps them on all cores.
31 void
32 kinit1(void *vstart, void *vend)
33 {
34   initlock(&kmem.lock, "kmem");
35   kmem.use_lock = 0;
36   freerange(vstart, vend);
37 }
38 
39 void
40 kinit2(void *vstart, void *vend)
41 {
42   freerange(vstart, vend);
43   kmem.use_lock = 1;
44 }
45 
46 void
47 freerange(void *vstart, void *vend)
48 {
49   char *p;
50   p = (char*)PGROUNDUP((uint)vstart);
51   for(; p + PGSIZE <= (char*)vend; p += PGSIZE)
52     kfree(p);
53 }
54 
55 //PAGEBREAK: 21
56 // Free the page of physical memory pointed at by v,
57 // which normally should have been returned by a
58 // call to kalloc().  (The exception is when
59 // initializing the allocator; see kinit above.)
60 void
61 kfree(char *v)
62 {
63   struct run *r;
64 
65   if((uint)v % PGSIZE || v < end || V2P(v) >= PHYSTOP)
66     panic("kfree");
67 
68   // Fill with junk to catch dangling refs.
69   memset(v, 1, PGSIZE);
70 
71   if(kmem.use_lock)
72     acquire(&kmem.lock);
73   r = (struct run*)v;
74   r->next = kmem.freelist;
75   kmem.freelist = r;
76   if(kmem.use_lock)
77     release(&kmem.lock);
78 }
79 
80 // Allocate one 4096-byte page of physical memory.
81 // Returns a pointer that the kernel can use.
82 // Returns 0 if the memory cannot be allocated.
83 char*
84 kalloc(void)
85 {
86   struct run *r;
87 
88   if(kmem.use_lock)
89     acquire(&kmem.lock);
90   r = kmem.freelist;
91   if(r)
92     kmem.freelist = r->next;
93   if(kmem.use_lock)
94     release(&kmem.lock);
95   return (char*)r;
96 }
97 
98