annotate src/kalloc.c @ 0:53676d1f5817 default tip

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