Rev 479 | Rev 487 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | jermar | 1 | /* |
2 | * Copyright (C) 2001-2004 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 | |||
368 | jermar | 29 | #include <typedefs.h> |
1 | jermar | 30 | #include <arch/types.h> |
31 | #include <mm/heap.h> |
||
32 | #include <mm/frame.h> |
||
33 | #include <mm/vm.h> |
||
34 | #include <panic.h> |
||
367 | jermar | 35 | #include <debug.h> |
368 | jermar | 36 | #include <list.h> |
1 | jermar | 37 | #include <synch/spinlock.h> |
115 | jermar | 38 | #include <arch/asm.h> |
195 | vana | 39 | #include <arch.h> |
115 | jermar | 40 | |
367 | jermar | 41 | spinlock_t zone_head_lock; /**< this lock protects zone_head list */ |
42 | link_t zone_head; /**< list of all zones in the system */ |
||
43 | |||
479 | bondari | 44 | static struct buddy_system_operations zone_buddy_system_operations = { |
45 | .find_buddy = zone_buddy_find_buddy, |
||
46 | .bisect = zone_buddy_bisect, |
||
47 | .coalesce = zone_buddy_coalesce, |
||
48 | .set_order = zone_buddy_set_order, |
||
49 | .get_order = zone_buddy_get_order, |
||
50 | }; |
||
51 | |||
368 | jermar | 52 | /** Initialize physical memory management |
53 | * |
||
54 | * Initialize physical memory managemnt. |
||
55 | */ |
||
1 | jermar | 56 | void frame_init(void) |
57 | { |
||
125 | jermar | 58 | if (config.cpu_active == 1) { |
367 | jermar | 59 | zone_init(); |
1 | jermar | 60 | } |
61 | |||
62 | frame_arch_init(); |
||
368 | jermar | 63 | |
1 | jermar | 64 | if (config.cpu_active == 1) { |
368 | jermar | 65 | frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE); |
66 | } |
||
1 | jermar | 67 | } |
68 | |||
368 | jermar | 69 | /** Allocate a frame |
70 | * |
||
71 | * Allocate a frame of physical memory. |
||
72 | * |
||
73 | * @param flags Flags for host zone selection and address processing. |
||
74 | * |
||
75 | * @return Allocated frame. |
||
1 | jermar | 76 | */ |
77 | __address frame_alloc(int flags) |
||
78 | { |
||
413 | jermar | 79 | ipl_t ipl; |
368 | jermar | 80 | link_t *cur, *tmp; |
81 | zone_t *z; |
||
82 | zone_t *zone = NULL; |
||
83 | frame_t *frame = NULL; |
||
84 | __address v; |
||
1 | jermar | 85 | |
86 | loop: |
||
413 | jermar | 87 | ipl = interrupts_disable(); |
368 | jermar | 88 | spinlock_lock(&zone_head_lock); |
89 | |||
90 | /* |
||
91 | * First, find suitable frame zone. |
||
92 | */ |
||
93 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
||
94 | z = list_get_instance(cur, zone_t, link); |
||
1 | jermar | 95 | |
368 | jermar | 96 | spinlock_lock(&z->lock); |
97 | /* |
||
98 | * Check if the zone has any free frames. |
||
99 | */ |
||
100 | if (z->free_count) { |
||
101 | zone = z; |
||
102 | break; |
||
1 | jermar | 103 | } |
368 | jermar | 104 | spinlock_unlock(&z->lock); |
1 | jermar | 105 | } |
368 | jermar | 106 | |
107 | if (!zone) { |
||
108 | if (flags & FRAME_PANIC) |
||
109 | panic("Can't allocate frame.\n"); |
||
110 | |||
111 | /* |
||
112 | * TODO: Sleep until frames are available again. |
||
113 | */ |
||
114 | spinlock_unlock(&zone_head_lock); |
||
413 | jermar | 115 | interrupts_restore(ipl); |
1 | jermar | 116 | |
368 | jermar | 117 | panic("Sleep not implemented.\n"); |
118 | goto loop; |
||
119 | } |
||
1 | jermar | 120 | |
368 | jermar | 121 | tmp = zone->free_head.next; |
122 | frame = list_get_instance(tmp, frame_t, link); |
||
123 | |||
124 | frame->refcount++; |
||
125 | list_remove(tmp); /* remove frame from free_head */ |
||
126 | zone->free_count--; |
||
127 | zone->busy_count++; |
||
1 | jermar | 128 | |
479 | bondari | 129 | //v = zone->base + (frame - zone->frames) * FRAME_SIZE; |
130 | v = FRAME2ADDR(zone, frame); |
||
368 | jermar | 131 | |
132 | if (flags & FRAME_KA) |
||
133 | v = PA2KA(v); |
||
134 | |||
135 | spinlock_unlock(&zone->lock); |
||
136 | |||
137 | spinlock_unlock(&zone_head_lock); |
||
413 | jermar | 138 | interrupts_restore(ipl); |
368 | jermar | 139 | |
140 | return v; |
||
1 | jermar | 141 | } |
142 | |||
368 | jermar | 143 | /** Free a frame. |
144 | * |
||
145 | * Find respective frame structrue for supplied addr. |
||
146 | * Decrement frame reference count. |
||
147 | * If it drops to zero, move the frame structure to free list. |
||
148 | * |
||
149 | * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE. |
||
1 | jermar | 150 | */ |
151 | void frame_free(__address addr) |
||
152 | { |
||
413 | jermar | 153 | ipl_t ipl; |
368 | jermar | 154 | link_t *cur; |
155 | zone_t *z; |
||
156 | zone_t *zone = NULL; |
||
157 | frame_t *frame; |
||
1 | jermar | 158 | |
368 | jermar | 159 | ASSERT(addr % FRAME_SIZE == 0); |
1 | jermar | 160 | |
413 | jermar | 161 | ipl = interrupts_disable(); |
368 | jermar | 162 | spinlock_lock(&zone_head_lock); |
1 | jermar | 163 | |
368 | jermar | 164 | /* |
165 | * First, find host frame zone for addr. |
||
166 | */ |
||
167 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
||
168 | z = list_get_instance(cur, zone_t, link); |
||
169 | |||
170 | spinlock_lock(&z->lock); |
||
171 | |||
172 | if (IS_KA(addr)) |
||
173 | addr = KA2PA(addr); |
||
174 | |||
175 | /* |
||
176 | * Check if addr belongs to z. |
||
177 | */ |
||
178 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
||
179 | zone = z; |
||
180 | break; |
||
1 | jermar | 181 | } |
368 | jermar | 182 | spinlock_unlock(&z->lock); |
1 | jermar | 183 | } |
184 | |||
368 | jermar | 185 | ASSERT(zone != NULL); |
186 | |||
479 | bondari | 187 | frame = ADDR2FRAME(zone, addr); |
188 | // frame = &zone->frames[(addr - zone->base)/FRAME_SIZE]; |
||
368 | jermar | 189 | ASSERT(frame->refcount); |
190 | |||
191 | if (!--frame->refcount) { |
||
192 | list_append(&frame->link, &zone->free_head); /* append frame to free_head */ |
||
193 | zone->free_count++; |
||
194 | zone->busy_count--; |
||
195 | } |
||
196 | |||
197 | spinlock_unlock(&zone->lock); |
||
198 | |||
199 | spinlock_unlock(&zone_head_lock); |
||
413 | jermar | 200 | interrupts_restore(ipl); |
1 | jermar | 201 | } |
202 | |||
368 | jermar | 203 | /** Mark frame not free. |
204 | * |
||
205 | * Find respective frame structrue for supplied addr. |
||
373 | jermar | 206 | * Increment frame reference count and remove the frame structure from free list. |
368 | jermar | 207 | * |
208 | * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE. |
||
1 | jermar | 209 | */ |
210 | void frame_not_free(__address addr) |
||
211 | { |
||
413 | jermar | 212 | ipl_t ipl; |
368 | jermar | 213 | link_t *cur; |
214 | zone_t *z; |
||
215 | zone_t *zone = NULL; |
||
216 | frame_t *frame; |
||
1 | jermar | 217 | |
368 | jermar | 218 | ASSERT(addr % FRAME_SIZE == 0); |
219 | |||
413 | jermar | 220 | ipl = interrupts_disable(); |
368 | jermar | 221 | spinlock_lock(&zone_head_lock); |
1 | jermar | 222 | |
368 | jermar | 223 | /* |
224 | * First, find host frame zone for addr. |
||
225 | */ |
||
226 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
||
227 | z = list_get_instance(cur, zone_t, link); |
||
228 | |||
229 | spinlock_lock(&z->lock); |
||
230 | |||
231 | if (IS_KA(addr)) |
||
232 | addr = KA2PA(addr); |
||
233 | |||
234 | /* |
||
235 | * Check if addr belongs to z. |
||
236 | */ |
||
237 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
||
238 | zone = z; |
||
239 | break; |
||
1 | jermar | 240 | } |
368 | jermar | 241 | spinlock_unlock(&z->lock); |
1 | jermar | 242 | } |
368 | jermar | 243 | |
244 | ASSERT(zone != NULL); |
||
245 | |||
479 | bondari | 246 | //frame = &zone->frames[(addr - zone->base)/FRAME_SIZE]; |
247 | frame = ADDR2FRAME(zone, addr); |
||
368 | jermar | 248 | |
249 | if (!frame->refcount) { |
||
250 | frame->refcount++; |
||
251 | |||
252 | list_remove(&frame->link); /* remove frame from free_head */ |
||
253 | zone->free_count--; |
||
254 | zone->busy_count++; |
||
255 | } |
||
256 | |||
257 | spinlock_unlock(&zone->lock); |
||
258 | |||
259 | spinlock_unlock(&zone_head_lock); |
||
413 | jermar | 260 | interrupts_restore(ipl); |
1 | jermar | 261 | } |
262 | |||
368 | jermar | 263 | /** Mark frame region not free. |
264 | * |
||
265 | * Mark frame region not free. |
||
266 | * |
||
267 | * @param start First address. |
||
268 | * @param stop Last address. |
||
269 | */ |
||
1 | jermar | 270 | void frame_region_not_free(__address start, __address stop) |
271 | { |
||
368 | jermar | 272 | __address a; |
1 | jermar | 273 | |
368 | jermar | 274 | start /= FRAME_SIZE; |
275 | stop /= FRAME_SIZE; |
||
276 | for (a = start; a <= stop; a++) |
||
277 | frame_not_free(a * FRAME_SIZE); |
||
1 | jermar | 278 | } |
367 | jermar | 279 | |
368 | jermar | 280 | |
367 | jermar | 281 | /** Initialize zonekeeping |
282 | * |
||
283 | * Initialize zonekeeping. |
||
284 | */ |
||
285 | void zone_init(void) |
||
286 | { |
||
287 | spinlock_initialize(&zone_head_lock); |
||
288 | list_initialize(&zone_head); |
||
289 | } |
||
290 | |||
291 | /** Create frame zone |
||
292 | * |
||
293 | * Create new frame zone. |
||
294 | * |
||
295 | * @param start Physical address of the first frame within the zone. |
||
296 | * @param size Size of the zone. Must be a multiple of FRAME_SIZE. |
||
297 | * @param flags Zone flags. |
||
298 | * |
||
299 | * @return Initialized zone. |
||
300 | */ |
||
301 | zone_t *zone_create(__address start, size_t size, int flags) |
||
302 | { |
||
303 | zone_t *z; |
||
304 | count_t cnt; |
||
305 | int i; |
||
479 | bondari | 306 | __u8 max_order; |
367 | jermar | 307 | |
308 | ASSERT(start % FRAME_SIZE == 0); |
||
309 | ASSERT(size % FRAME_SIZE == 0); |
||
310 | |||
311 | cnt = size / FRAME_SIZE; |
||
312 | |||
374 | jermar | 313 | z = (zone_t *) early_malloc(sizeof(zone_t)); |
367 | jermar | 314 | if (z) { |
315 | link_initialize(&z->link); |
||
316 | spinlock_initialize(&z->lock); |
||
317 | |||
318 | z->base = start; |
||
319 | z->flags = flags; |
||
320 | |||
321 | z->free_count = cnt; |
||
322 | list_initialize(&z->free_head); |
||
323 | |||
324 | z->busy_count = 0; |
||
325 | |||
374 | jermar | 326 | z->frames = (frame_t *) early_malloc(cnt * sizeof(frame_t)); |
367 | jermar | 327 | if (!z->frames) { |
375 | jermar | 328 | early_free(z); |
367 | jermar | 329 | return NULL; |
330 | } |
||
331 | |||
332 | for (i = 0; i<cnt; i++) { |
||
333 | frame_initialize(&z->frames[i], z); |
||
334 | list_append(&z->frames[i].link, &z->free_head); |
||
335 | } |
||
336 | |||
479 | bondari | 337 | /* |
338 | * Create buddy system for the zone |
||
339 | */ |
||
340 | for (max_order = 0; cnt >> max_order; max_order++); |
||
341 | z->buddy_system = buddy_system_create(max_order, &zone_buddy_system_operations); |
||
367 | jermar | 342 | } |
343 | |||
344 | return z; |
||
345 | } |
||
346 | |||
347 | /** Attach frame zone |
||
348 | * |
||
349 | * Attach frame zone to zone list. |
||
350 | * |
||
351 | * @param zone Zone to be attached. |
||
352 | */ |
||
353 | void zone_attach(zone_t *zone) |
||
354 | { |
||
413 | jermar | 355 | ipl_t ipl; |
367 | jermar | 356 | |
413 | jermar | 357 | ipl = interrupts_disable(); |
367 | jermar | 358 | spinlock_lock(&zone_head_lock); |
359 | |||
360 | list_append(&zone->link, &zone_head); |
||
361 | |||
362 | spinlock_unlock(&zone_head_lock); |
||
413 | jermar | 363 | interrupts_restore(ipl); |
367 | jermar | 364 | } |
365 | |||
366 | /** Initialize frame structure |
||
367 | * |
||
368 | * Initialize frame structure. |
||
369 | * |
||
370 | * @param frame Frame structure to be initialized. |
||
371 | * @param zone Host frame zone. |
||
372 | */ |
||
373 | void frame_initialize(frame_t *frame, zone_t *zone) |
||
374 | { |
||
375 | frame->refcount = 0; |
||
376 | link_initialize(&frame->link); |
||
377 | } |
||
479 | bondari | 378 | |
379 | |||
380 | |||
381 | /* |
||
382 | * buddy system functions (under construction) |
||
383 | * |
||
384 | */ |
||
385 | |||
386 | |||
387 | /** Allocate 2^order frames |
||
388 | * |
||
389 | */ |
||
390 | __address zone_buddy_frame_alloc(int flags, __u8 order) { |
||
391 | ipl_t ipl; |
||
392 | link_t *cur, *tmp; |
||
393 | zone_t *z; |
||
394 | zone_t *zone = NULL; |
||
395 | frame_t *frame = NULL; |
||
396 | __address v; |
||
397 | |||
398 | loop: |
||
399 | ipl = interrupts_disable(); |
||
400 | spinlock_lock(&zone_head_lock); |
||
401 | |||
402 | /* |
||
403 | * First, find suitable frame zone. |
||
404 | */ |
||
405 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
||
406 | z = list_get_instance(cur, zone_t, link); |
||
407 | |||
408 | spinlock_lock(&z->lock); |
||
409 | /* |
||
410 | * Check if the zone has 2^order frames area available |
||
411 | * TODO: Must check if buddy system has at least block in order >= given order |
||
412 | */ |
||
413 | if (z->free_count == (1 >> order)) { |
||
414 | zone = z; |
||
415 | break; |
||
416 | } |
||
417 | |||
418 | spinlock_unlock(&z->lock); |
||
419 | } |
||
420 | |||
421 | if (!zone) { |
||
422 | if (flags & FRAME_PANIC) |
||
423 | panic("Can't allocate frame.\n"); |
||
424 | |||
425 | /* |
||
426 | * TODO: Sleep until frames are available again. |
||
427 | */ |
||
428 | spinlock_unlock(&zone_head_lock); |
||
429 | interrupts_restore(ipl); |
||
430 | |||
431 | panic("Sleep not implemented.\n"); |
||
432 | goto loop; |
||
433 | } |
||
434 | |||
435 | |||
436 | /* Allocate frames from zone buddy system */ |
||
437 | cur = buddy_system_alloc(zone->buddy_system, order); |
||
438 | |||
439 | /* frame will be actually a first frame of the block */ |
||
440 | frame = list_get_instance(cur, frame_t, buddy_link); |
||
441 | |||
442 | /* get frame address */ |
||
443 | v = FRAME2ADDR(zone, frame); |
||
444 | |||
445 | if (flags & FRAME_KA) |
||
446 | v = PA2KA(v); |
||
447 | |||
448 | spinlock_unlock(&zone->lock); |
||
449 | spinlock_unlock(&zone_head_lock); |
||
450 | interrupts_restore(ipl); |
||
451 | |||
452 | return v; |
||
453 | } |
||
454 | |||
455 | |||
456 | /** Free frame(s) |
||
457 | * |
||
458 | * @param addr Address of the frame(s) to be freed. It must be a multiple of FRAME_SIZE. |
||
459 | */ |
||
460 | void zone_buddy_frame_free(__address addr) |
||
461 | { |
||
462 | ipl_t ipl; |
||
463 | link_t *cur; |
||
464 | zone_t *z; |
||
465 | zone_t *zone = NULL; |
||
466 | frame_t *frame; |
||
467 | |||
468 | ASSERT(addr % FRAME_SIZE == 0); |
||
469 | |||
470 | ipl = interrupts_disable(); |
||
471 | spinlock_lock(&zone_head_lock); |
||
472 | |||
473 | /* |
||
474 | * First, find host frame zone for addr. |
||
475 | */ |
||
476 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
||
477 | z = list_get_instance(cur, zone_t, link); |
||
478 | |||
479 | spinlock_lock(&z->lock); |
||
480 | |||
481 | if (IS_KA(addr)) |
||
482 | addr = KA2PA(addr); |
||
483 | |||
484 | /* |
||
485 | * Check if addr belongs to z. |
||
486 | */ |
||
487 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
||
488 | zone = z; |
||
489 | break; |
||
490 | } |
||
491 | spinlock_unlock(&z->lock); |
||
492 | } |
||
493 | |||
494 | ASSERT(zone != NULL); |
||
495 | |||
496 | frame = ADDR2FRAME(zone, addr); |
||
497 | |||
498 | ASSERT(frame->refcount); |
||
499 | |||
500 | if (!--frame->refcount) { |
||
501 | buddy_system_free(zone->buddy_system, &frame->buddy_link); |
||
502 | } |
||
503 | |||
504 | spinlock_unlock(&zone->lock); |
||
505 | |||
506 | spinlock_unlock(&zone_head_lock); |
||
507 | interrupts_restore(ipl); |
||
508 | } |
||
509 | |||
480 | bondari | 510 | /** Guess zone by frame instance address |
511 | * |
||
512 | * @param frame Frame |
||
513 | * |
||
514 | * @return Zone of given frame |
||
515 | */ |
||
516 | zone_t * get_zone_by_frame(frame_t * frame) { |
||
517 | link_t * cur; |
||
518 | zone_t * zone, *z; |
||
479 | bondari | 519 | |
480 | bondari | 520 | ASSERT(frame); |
521 | /* |
||
522 | * First, find host frame zone for addr. |
||
523 | */ |
||
524 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
||
525 | z = list_get_instance(cur, zone_t, link); |
||
526 | |||
527 | spinlock_lock(&z->lock); |
||
528 | |||
529 | /* |
||
530 | * Check if frame address belongs to z. |
||
531 | */ |
||
532 | if ((frame >= z->frames) && (frame <= z->frames + (z->free_count + z->busy_count))) { |
||
533 | zone = z; |
||
534 | break; |
||
535 | } |
||
536 | spinlock_unlock(&z->lock); |
||
537 | } |
||
538 | ASSERT(zone); |
||
539 | |||
540 | return zone; |
||
541 | |||
542 | |||
543 | } |
||
544 | |||
479 | bondari | 545 | /** Buddy system find_buddy implementation |
480 | bondari | 546 | * @param block Block for which buddy should be found |
479 | bondari | 547 | * |
480 | bondari | 548 | * @return Buddy for given block if found |
479 | bondari | 549 | */ |
480 | bondari | 550 | link_t * zone_buddy_find_buddy(link_t * block) { |
551 | frame_t * frame, * f; |
||
552 | zone_t * zone; |
||
553 | link_t * cur; |
||
554 | bool is_left, is_right; |
||
479 | bondari | 555 | |
480 | bondari | 556 | frame = list_get_instance(block, frame_t, buddy_link); |
557 | zone = get_zone_by_frame(frame); |
||
558 | |||
559 | |||
560 | /* |
||
561 | * (FRAME_INDEX % 2^(ORDER+1)) == 0 ===> LEFT BUDDY |
||
562 | * (FRAME_INDEX % 2^(ORDER+1)) == 2^(ORDER) ===> RIGHT BUDDY |
||
563 | */ |
||
564 | |||
565 | is_left = IS_BUDDY_LEFT_BLOCK(zone, frame); |
||
566 | is_right = IS_BUDDY_RIGHT_BLOCK(zone, frame); |
||
567 | |||
568 | ASSERT((is_left || is_right) && (!is_left || !is_right)); |
||
569 | |||
570 | for (cur = &zone->buddy_system->order[frame->buddy_order]; cur; cur = cur->next) { |
||
571 | f = list_get_instance(cur, frame_t, buddy_link); |
||
572 | |||
573 | ASSERT(f->buddy_order == frame->buddy_order); |
||
574 | |||
575 | /* |
||
576 | * if found frame is coherent with our frame from the left |
||
577 | */ |
||
578 | if ((FRAME_INDEX(zone, f) + 1 >> frame->buddy_order == FRAME_INDEX(zone, frame)) && is_right) { |
||
579 | return cur; |
||
580 | } |
||
581 | |||
582 | /* |
||
583 | * if found frame is coherent with our frame from the right |
||
584 | */ |
||
585 | if ((FRAME_INDEX(zone,f) - 1 >> frame->buddy_order == FRAME_INDEX(zone, frame)) && is_left) { |
||
586 | return cur; |
||
587 | } |
||
588 | |||
589 | } |
||
590 | |||
591 | return NULL; |
||
592 | |||
593 | |||
479 | bondari | 594 | } |
595 | |||
596 | /** Buddy system bisect implementation |
||
597 | * |
||
480 | bondari | 598 | * @param block Block to bisect |
599 | * |
||
600 | * @return right block |
||
479 | bondari | 601 | */ |
602 | link_t * zone_buddy_bisect(link_t * block) { |
||
480 | bondari | 603 | frame_t * frame_l, * frame_r; |
604 | zone_t * zone; |
||
605 | |||
606 | frame_l = list_get_instance(block, frame_t, buddy_link); |
||
479 | bondari | 607 | |
480 | bondari | 608 | zone = get_zone_by_frame(frame_l); |
609 | |||
610 | frame_r = &zone->frames[FRAME_INDEX(zone, frame_l) + 1>>(frame_l->buddy_order-1)]; |
||
611 | |||
612 | |||
613 | return &frame_r->buddy_link; |
||
614 | |||
479 | bondari | 615 | } |
616 | |||
617 | /** Buddy system coalesce implementation |
||
618 | * |
||
480 | bondari | 619 | * @param block_1 First block |
620 | * @param block_2 First block's buddy |
||
621 | * |
||
622 | * @return Coalesced block (actually block that represents lower address) |
||
479 | bondari | 623 | */ |
480 | bondari | 624 | link_t * zone_buddy_coalesce(link_t * block_1, link_t * block_2) { |
625 | frame_t * frame1, * frame2; |
||
626 | zone_t * zone; |
||
627 | |||
628 | frame1 = list_get_instance(block_1, frame_t, buddy_link); |
||
629 | frame2 = list_get_instance(block_2, frame_t, buddy_link); |
||
630 | |||
631 | zone = get_zone_by_frame(frame1); |
||
632 | |||
633 | return FRAME_INDEX(zone, frame1) < FRAME_INDEX(zone, frame2) ? block_1 : block_2; |
||
479 | bondari | 634 | |
635 | } |
||
636 | |||
637 | /** Buddy system set_order implementation |
||
480 | bondari | 638 | * @param block Buddy system block |
639 | * @param order Order to set |
||
479 | bondari | 640 | */ |
641 | void zone_buddy_set_order(link_t * block, __u8 order) { |
||
480 | bondari | 642 | frame_t * frame; |
643 | frame = list_get_instance(block, frame_t, buddy_link); |
||
644 | frame->buddy_order = order; |
||
479 | bondari | 645 | } |
646 | |||
647 | /** Buddy system get_order implementation |
||
480 | bondari | 648 | * @param block Buddy system block |
479 | bondari | 649 | * |
480 | bondari | 650 | * @return Order of block |
479 | bondari | 651 | */ |
652 | __u8 zone_buddy_get_order(link_t * block) { |
||
480 | bondari | 653 | frame_t * frame; |
654 | frame = list_get_instance(block, frame_t, buddy_link); |
||
655 | return frame->buddy_order; |
||
479 | bondari | 656 | } |