Mercurial > hg > Members > innparusu > xv6-rpi
comparison src/kalloc.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
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 #include "arm.h" | |
12 | |
13 void freerange(void *vstart, void *vend); | |
14 extern char end[]; // first address after kernel loaded from ELF file | |
15 | |
16 struct run { | |
17 struct run *next; | |
18 }; | |
19 | |
20 static struct { | |
21 struct spinlock lock; | |
22 int use_lock; | |
23 struct run *freelist; | |
24 } kmem; | |
25 | |
26 void kmem_init (void) | |
27 { | |
28 initlock(&kmem.lock, "kmem"); | |
29 kmem.use_lock = 0; | |
30 } | |
31 | |
32 // Initialization happens in two phases. | |
33 // 1. main() calls kinit1() while still using entrypgdir to place just | |
34 // the pages mapped by entrypgdir on free list. | |
35 // 2. main() calls kinit2() with the rest of the physical pages | |
36 // after installing a full page table that maps them on all cores. | |
37 void kinit1(void *vstart, void *vend) | |
38 { | |
39 freerange(vstart, vend); | |
40 } | |
41 | |
42 void kinit2(void *vstart, void *vend) | |
43 { | |
44 freerange(vstart, vend); | |
45 kmem.use_lock = 1; | |
46 } | |
47 | |
48 void freerange(void *vstart, void *vend) | |
49 { | |
50 char *p; | |
51 | |
52 p = (char*)align_up (vstart, PTE_SZ); | |
53 | |
54 for(; p + PTE_SZ <= (char*)vend; p += PTE_SZ) { | |
55 kfree(p); | |
56 } | |
57 } | |
58 | |
59 //PAGEBREAK: 21 | |
60 // Free the page of physical memory pointed at by v, | |
61 // which normally should have been returned by a | |
62 // call to kalloc(). (The exception is when | |
63 // initializing the allocator; see kinit above.) | |
64 void kfree(char *v) | |
65 { | |
66 struct run *r; | |
67 | |
68 if((uint)v % PTE_SZ || v < end || v2p(v) >= PHYSTOP) { | |
69 cprintf("kfree(0x%x)\n", v); | |
70 panic("kfree"); | |
71 } | |
72 | |
73 // Fill with junk to catch dangling refs. | |
74 //memset(v, 0x00, PG_SIZE); | |
75 | |
76 if(kmem.use_lock) { | |
77 acquire(&kmem.lock); | |
78 } | |
79 | |
80 r = (struct run*)v; | |
81 r->next = kmem.freelist; | |
82 kmem.freelist = r; | |
83 | |
84 if(kmem.use_lock) { | |
85 release(&kmem.lock); | |
86 } | |
87 } | |
88 | |
89 // Allocate one 4096-byte page of physical memory. | |
90 // Returns a pointer that the kernel can use. | |
91 // Returns 0 if the memory cannot be allocated. | |
92 char* kalloc(void) | |
93 { | |
94 struct run *r; | |
95 | |
96 if(kmem.use_lock) { | |
97 acquire(&kmem.lock); | |
98 } | |
99 | |
100 r = kmem.freelist; | |
101 | |
102 if(r) { | |
103 kmem.freelist = r->next; | |
104 } | |
105 | |
106 if(kmem.use_lock) { | |
107 release(&kmem.lock); | |
108 } | |
109 | |
110 return (char*)r; | |
111 } |