annotate src/buddy.c @ 295:274bbf78b87b

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