annotate src/buddy.c @ 52:1adde248a61f default tip

merge
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Fri, 07 Jun 2019 17:30:15 +0900
parents 83c23a36980d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 // Buddy memory allocator
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 #include "types.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 #include "defs.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 #include "param.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 #include "memlayout.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 #include "mmu.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 #include "spinlock.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 #include "arm.h"
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
9
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 // this file implement the buddy memory allocator. Each order divides
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 // the memory pool into equal-sized blocks (2^n). We use bitmap to record
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 // allocation status for each block. This allows for efficient merging
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 // when blocks are freed. We also use double-linked list to chain together
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 // free blocks (for each order), thus allowing fast allocation. There is
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 // about 8% overhead (maximum) for this structure.
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
17
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 #define MAX_ORD 12
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 #define MIN_ORD 6
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #define N_ORD (MAX_ORD - MIN_ORD +1)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
21
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 struct mark {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 uint32 lnks; // double links (actually indexes)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 uint32 bitmap; // bitmap, whether the block is available (1=available)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 };
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
26
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 // lnks is a combination of previous link (index) and next link (index)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 #define PRE_LNK(lnks) ((lnks) >> 16)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 #define NEXT_LNK(lnks) ((lnks) & 0xFFFF)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 #define LNKS(pre, next) (((pre) << 16) | ((next) & 0xFFFF))
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 #define NIL ((uint16)0xFFFF)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
32
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 struct order {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 uint32 head; // the first non-empty mark
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 uint32 offset; // the first mark
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 };
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
37
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 struct kmem {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 struct spinlock lock;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 uint start; // start of memory for marks
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 uint start_heap; // start of allocatable memory
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 uint end;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 struct order orders[N_ORD]; // orders used for buddy systems
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 };
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
45
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 static struct kmem kmem;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
47
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 // coversion between block id to mark and memory address
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 static inline struct mark* get_mark (int order, int idx)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 return (struct mark*)kmem.start + (kmem.orders[order - MIN_ORD].offset + idx);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
53
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 static inline void* blkid2mem (int order, int blkid)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 return (void*)(kmem.start_heap + (1 << order) * blkid);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
58
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 static inline int mem2blkid (int order, void *mem)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 return ((uint)mem - kmem.start_heap) >> order;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
63
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 static inline int available (uint bitmap, int blk_id)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 return bitmap & (1 << (blk_id & 0x1F));
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
68
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 void kmem_init (void)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 initlock(&kmem.lock, "kmem");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
73
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 void kmem_init2(void *vstart, void *vend)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 int i, j;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 uint32 total, n;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 uint len;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 struct order *ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 struct mark *mk;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
81
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 kmem.start = (uint)vstart;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 kmem.end = (uint)vend;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 len = kmem.end - kmem.start;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
85
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 // reserved memory at vstart for an array of marks (for all the orders)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 n = (len >> (MAX_ORD + 5)) + 1; // estimated # of marks for max order
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 total = 0;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
89
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 for (i = N_ORD - 1; i >= 0; i--) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 ord = kmem.orders + i;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 ord->offset = total;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 ord->head = NIL;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
94
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 // set the bitmaps to mark all blocks not available
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 for (j = 0; j < n; j++) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 mk = get_mark(i + MIN_ORD, j);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 mk->lnks = LNKS(NIL, NIL);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 mk->bitmap = 0;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
101
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 total += n;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 n <<= 1; // each order doubles required marks
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
105
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 // add all available memory to the highest order bucket
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 kmem.start_heap = align_up(kmem.start + total * sizeof(*mk), 1 << MAX_ORD);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
108
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 for (i = kmem.start_heap; i < kmem.end; i += (1 << MAX_ORD)){
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 kfree ((void*)i, MAX_ORD);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
113
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 // mark a block as unavailable
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 static void unmark_blk (int order, int blk_id)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 struct mark *mk, *p;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 struct order *ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 int prev, next;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
120
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 ord = &kmem.orders[order - MIN_ORD];
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 mk = get_mark (order, blk_id >> 5);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
123
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 // clear the bit in the bitmap
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 if (!available(mk->bitmap, blk_id)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 panic ("double alloc\n");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
128
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 mk->bitmap &= ~(1 << (blk_id & 0x1F));
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
130
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 // if it's the last block in the bitmap, delete from the list
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 if (mk->bitmap == 0) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 blk_id >>= 5;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
134
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 prev = PRE_LNK(mk->lnks);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 next = NEXT_LNK(mk->lnks);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
137
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 if (prev != NIL) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 p = get_mark(order, prev);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 p->lnks = LNKS(PRE_LNK(p->lnks), next);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
141
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 } else if (ord->head == blk_id) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 // if we are the first in the link
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 ord->head = next;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
146
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 if (next != NIL) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 p = get_mark(order, next);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 p->lnks = LNKS(prev, NEXT_LNK(p->lnks));
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
151
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 mk->lnks = LNKS(NIL, NIL);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
155
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 // mark a block as available
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 static void mark_blk (int order, int blk_id)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 struct mark *mk, *p;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 struct order *ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 int insert;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
162
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 ord = &kmem.orders[order - MIN_ORD];
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 mk = get_mark (order, blk_id >> 5);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
165
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 // whether we need to insert it into the list
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 insert = (mk->bitmap == 0);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
168
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 // clear the bit map
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 if (available(mk->bitmap, blk_id)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 panic ("double free\n");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
173
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 mk->bitmap |= (1 << (blk_id & 0x1F));
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
175
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 // just insert it to the head, no need to keep the list ordered
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 if (insert) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 blk_id >>= 5;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 mk->lnks = LNKS(NIL, ord->head);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
180
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 // fix the pre pointer of the next mark
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 if (ord->head != NIL) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 p = get_mark(order, ord->head);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 p->lnks = LNKS(blk_id, NEXT_LNK(p->lnks));
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
186
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 ord->head = blk_id;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
190
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 // get a block
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 static void* get_blk (int order)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 struct mark *mk;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 int blk_id;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 int i;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 struct order *ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
198
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 ord = &kmem.orders[order - MIN_ORD];
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 mk = get_mark(order, ord->head);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
201
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 if (mk->bitmap == 0) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 panic ("empty mark in the list\n");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
205
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 for (i = 0; i < 32; i++) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 if (mk->bitmap & (1 << i)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 blk_id = ord->head * 32 + i;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 unmark_blk(order, blk_id);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
210
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 return blkid2mem(order, blk_id);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
214
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 return NULL;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
217
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 void _kfree (void *mem, int order);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
219
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
220
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 static void *_kmalloc (int order)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 struct order *ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 uint8 *up;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
225
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 ord = &kmem.orders[order - MIN_ORD];
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 up = NULL;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
228
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 if (ord->head != NIL) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 up = get_blk(order);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
231
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 } else if (order < MAX_ORD){
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 // if currently no block available, try to split a parent
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 up = _kmalloc (order + 1);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
235
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 if (up != NULL) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 _kfree (up + (1 << order), order);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
240
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 return up;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
243
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 // allocate memory that has the size of (1 << order)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 void *kmalloc (int order)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 uint8 *up;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
248
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 if ((order > MAX_ORD) || (order < MIN_ORD)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 panic("kmalloc: order out of range\n");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
252
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 acquire(&kmem.lock);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 up = _kmalloc(order);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 release(&kmem.lock);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
256
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 return up;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
259
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 void _kfree (void *mem, int order)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 int blk_id, buddy_id;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 struct mark *mk;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
264
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 blk_id = mem2blkid(order, mem);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 mk = get_mark(order, blk_id >> 5);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
267
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 if (available(mk->bitmap, blk_id)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 panic ("kfree: double free");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
271
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 buddy_id = blk_id ^ 0x0001; // blk_id and buddy_id differs in the last bit
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 // buddy must be in the same bit map
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 if (!available(mk->bitmap, buddy_id) || (order == MAX_ORD)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 mark_blk(order, blk_id);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 } else {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 // our buddy is also free, merge it
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 unmark_blk (order, buddy_id);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 _kfree (blkid2mem(order, blk_id & ~0x0001), order+1);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
282
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 // free kernel memory, we require order parameter here to avoid
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 // storing size info somewhere which might break the alignment
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 void kfree (void *mem, int order)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 if ((order > MAX_ORD) || (order < MIN_ORD) || (uint)mem & ((1<<order) -1)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 panic("kfree: order out of range or memory unaligned\n");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
290
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 acquire(&kmem.lock);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 _kfree(mem, order);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 release(&kmem.lock);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
295
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 // free a page
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 void free_page(void *v)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 kfree (v, PTE_SHIFT);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
301
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 // allocate a page
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 void* alloc_page (void)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 return kmalloc (PTE_SHIFT);
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
307
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 // round up power of 2, then get the order
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 int get_order (uint32 v)
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 uint32 ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
313
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 v--;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 v |= v >> 1;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 v |= v >> 2;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 v |= v >> 4;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 v |= v >> 8;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 v |= v >> 16;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 v++;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
321
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 for (ord = 0; ord < 32; ord++) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 if (v & (1 << ord)) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 break;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
327
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 if (ord < MIN_ORD) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 ord = MIN_ORD;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 } else if (ord > MAX_ORD) {
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 panic ("order too big!");
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
333
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 return ord;
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
335
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 }
Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
parents:
diff changeset
337