source: mainline/generic/src/mm/buddy.c@ 328f2934

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 328f2934 was 328f2934, checked in by Sergey Bondari <bondari@…>, 20 years ago

Buddy allocator for physical memory complete implementation.
Tested on IA32, AMD64, MIPS32. RWLock Test #5 is not passed.
NOTE: Other architectures could be broken (but should not be)

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*
2 * Copyright (C) 2005 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <mm/buddy.h>
30#include <mm/frame.h>
31#include <mm/heap.h>
32#include <arch/types.h>
33#include <typedefs.h>
34#include <list.h>
35#include <debug.h>
36#include <print.h>
37
38/** Create buddy system
39 *
40 * Allocate memory for and initialize new buddy system.
41 *
42 * @param max_order The biggest allocable size will be 2^max_order.
43 * @param op Operations for new buddy system.
44 * @param data Pointer to be used by implementation.
45 *
46 * @return New buddy system.
47 */
48buddy_system_t *buddy_system_create(__u8 max_order, buddy_system_operations_t *op, void *data)
49{
50 buddy_system_t *b;
51 int i;
52
53 ASSERT(max_order < BUDDY_SYSTEM_INNER_BLOCK);
54
55 ASSERT(op->find_buddy);
56 ASSERT(op->set_order);
57 ASSERT(op->get_order);
58 ASSERT(op->bisect);
59 ASSERT(op->coalesce);
60 ASSERT(op->mark_busy);
61
62 /*
63 * Allocate memory for structure describing the whole buddy system.
64 */
65 b = (buddy_system_t *) early_malloc(sizeof(buddy_system_t));
66
67 if (b) {
68 /*
69 * Allocate memory for all orders this buddy system will work with.
70 */
71 b->order = (link_t *) early_malloc(max_order * sizeof(link_t));
72 if (!b->order) {
73 early_free(b);
74 return NULL;
75 }
76
77 for (i = 0; i < max_order; i++)
78 list_initialize(&b->order[i]);
79
80 b->max_order = max_order;
81 b->op = op;
82 b->data = data;
83 }
84
85 return b;
86}
87
88/** Check if buddy system can allocate block
89 *
90 * @param b Buddy system pointer
91 * @param i Size of the block (2^i)
92 *
93 * @return True if block can be allocated
94 */
95bool buddy_system_can_alloc(buddy_system_t *b, __u8 i) {
96 __u8 k;
97
98 ASSERT(i < b->max_order);
99
100 for (k=i; k < b->max_order; k++) {
101 if (!list_empty(&b->order[k])) {
102 return true;
103 }
104 }
105
106 return false;
107
108}
109
110/** Allocate block from buddy system.
111 *
112 * @param b Buddy system pointer.
113 * @param i Returned block will be 2^i big.
114 *
115 * @return Block of data represented by link_t.
116 */
117link_t *buddy_system_alloc(buddy_system_t *b, __u8 i)
118{
119 link_t *res, *hlp;
120
121 ASSERT(i < b->max_order);
122
123 /*
124 * If the list of order i is not empty,
125 * the request can be immediatelly satisfied.
126 */
127 if (!list_empty(&b->order[i])) {
128 res = b->order[i].next;
129 list_remove(res);
130 b->op->mark_busy(b, res);
131 return res;
132 }
133
134 /*
135 * If order i is already the maximal order,
136 * the request cannot be satisfied.
137 */
138 if (i == b->max_order - 1)
139 return NULL;
140
141 /*
142 * Try to recursively satisfy the request from higher order lists.
143 */
144 hlp = buddy_system_alloc(b, i + 1);
145
146 /*
147 * The request could not be satisfied
148 * from higher order lists.
149 */
150 if (!hlp)
151 return NULL;
152
153 res = hlp;
154
155 /*
156 * Bisect the block and set order of both of its parts to i.
157 */
158 hlp = b->op->bisect(b, res);
159 b->op->set_order(b, res, i);
160 b->op->set_order(b, hlp, i);
161
162 /*
163 * Return the other half to buddy system.
164 * PROBLEM!!!! FILL FIND OTHER PART AS BUDDY AND LINK TOGETHER
165 */
166 b->op->mark_busy(b, res);
167 buddy_system_free(b, hlp);
168
169 return res;
170
171}
172
173/** Return block to buddy system.
174 *
175 * @param b Buddy system pointer.
176 * @param block Block to return.
177 */
178void buddy_system_free(buddy_system_t *b, link_t *block)
179{
180 link_t *buddy, *hlp;
181 __u8 i;
182
183 /*
184 * Determine block's order.
185 */
186 i = b->op->get_order(b, block);
187
188 ASSERT(i < b->max_order);
189
190 if (i != b->max_order - 1) {
191 /*
192 * See if there is any buddy in the list of order i.
193 */
194 buddy = b->op->find_buddy(b, block);
195 if (buddy) {
196
197 ASSERT(b->op->get_order(b, buddy) == i);
198 /*
199 * Remove buddy from the list of order i.
200 */
201 list_remove(buddy);
202
203 /*
204 * Invalidate order of both block and buddy.
205 */
206 b->op->set_order(b, block, BUDDY_SYSTEM_INNER_BLOCK);
207 b->op->set_order(b, buddy, BUDDY_SYSTEM_INNER_BLOCK);
208
209 /*
210 * Coalesce block and buddy into one block.
211 */
212 hlp = b->op->coalesce(b, block, buddy);
213
214 /*
215 * Set order of the coalesced block to i + 1.
216 */
217 b->op->set_order(b, hlp, i + 1);
218
219 /*
220 * Recursively add the coalesced block to the list of order i + 1.
221 */
222 buddy_system_free(b, hlp);
223 return;
224 }
225 }
226
227 /*
228 * Insert block into the list of order i.
229 */
230 list_append(block, &b->order[i]);
231
232}
Note: See TracBrowser for help on using the repository browser.