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 | //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((uint)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 | |
97 | |