Changeset 328f2934 in mainline for generic/src/mm/frame.c
- Timestamp:
- 2005-12-04T19:37:13Z (20 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- cf585c9
- Parents:
- d7ac642
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/frame.c
rd7ac642 r328f2934 38 38 #include <arch/asm.h> 39 39 #include <arch.h> 40 #include <print.h> 40 41 41 42 spinlock_t zone_head_lock; /**< this lock protects zone_head list */ 42 43 link_t zone_head; /**< list of all zones in the system */ 44 45 region_t zone_blacklist[ZONE_BLACKLIST_SIZE]; 46 count_t zone_blacklist_count = 0; 43 47 44 48 static struct buddy_system_operations zone_buddy_system_operations = { … … 48 52 .set_order = zone_buddy_set_order, 49 53 .get_order = zone_buddy_get_order, 54 .mark_busy = zone_buddy_mark_busy, 50 55 }; 51 56 … … 58 63 if (config.cpu_active == 1) { 59 64 zone_init(); 65 frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE); 60 66 } 61 67 62 68 frame_arch_init(); 63 64 if (config.cpu_active == 1) {65 frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE);66 }67 69 } 68 70 … … 75 77 * @return Allocated frame. 76 78 */ 77 __address frame_alloc(int flags )79 __address frame_alloc(int flags, __u8 order) 78 80 { 79 81 ipl_t ipl; … … 87 89 ipl = interrupts_disable(); 88 90 spinlock_lock(&zone_head_lock); 89 91 90 92 /* 91 93 * First, find suitable frame zone. … … 95 97 96 98 spinlock_lock(&z->lock); 97 /* 98 * Check if the zone has any free frames. 99 */ 100 if (z->free_count) { 99 100 /* Check if the zone has 2^order frames area available */ 101 if (buddy_system_can_alloc(z->buddy_system, order)) { 101 102 zone = z; 102 103 break; 103 104 } 105 104 106 spinlock_unlock(&z->lock); 105 107 } … … 119 121 } 120 122 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++; 128 129 //v = zone->base + (frame - zone->frames) * FRAME_SIZE; 123 124 /* Allocate frames from zone buddy system */ 125 cur = buddy_system_alloc(zone->buddy_system, order); 126 127 /* frame will be actually a first frame of the block */ 128 frame = list_get_instance(cur, frame_t, buddy_link); 129 130 /* get frame address */ 130 131 v = FRAME2ADDR(zone, frame); 131 132 132 133 if (flags & FRAME_KA) 133 134 v = PA2KA(v); 134 135 135 136 spinlock_unlock(&zone->lock); 136 137 137 spinlock_unlock(&zone_head_lock); 138 138 interrupts_restore(ipl); 139 140 139 return v; 140 141 141 } 142 142 … … 156 156 zone_t *zone = NULL; 157 157 frame_t *frame; 158 159 158 ASSERT(addr % FRAME_SIZE == 0); 160 159 … … 186 185 187 186 frame = ADDR2FRAME(zone, addr); 188 // frame = &zone->frames[(addr - zone->base)/FRAME_SIZE]; 187 189 188 ASSERT(frame->refcount); 190 189 191 190 if (!--frame->refcount) { 192 list_append(&frame->link, &zone->free_head); /* append frame to free_head */ 193 zone->free_count++; 194 zone->busy_count--; 191 buddy_system_free(zone->buddy_system, &frame->buddy_link); 195 192 } 196 193 … … 201 198 } 202 199 203 /** Mark frame not free.204 *205 * Find respective frame structrue for supplied addr.206 * Increment frame reference count and remove the frame structure from free list.207 *208 * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE.209 */210 void frame_not_free(__address addr)211 {212 ipl_t ipl;213 link_t *cur;214 zone_t *z;215 zone_t *zone = NULL;216 frame_t *frame;217 218 ASSERT(addr % FRAME_SIZE == 0);219 220 ipl = interrupts_disable();221 spinlock_lock(&zone_head_lock);222 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;240 }241 spinlock_unlock(&z->lock);242 }243 244 ASSERT(zone != NULL);245 246 //frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];247 frame = ADDR2FRAME(zone, addr);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);260 interrupts_restore(ipl);261 }262 263 200 /** Mark frame region not free. 264 201 * … … 268 205 * @param stop Last address. 269 206 */ 270 void frame_region_not_free(__address start, __address stop) 271 { 272 __address a; 273 274 start /= FRAME_SIZE; 275 stop /= FRAME_SIZE; 276 for (a = start; a <= stop; a++) 277 frame_not_free(a * FRAME_SIZE); 207 void frame_region_not_free(__address base, size_t size) 208 { 209 count_t index; 210 index = zone_blacklist_count++; 211 ASSERT(base % FRAME_SIZE == 0); 212 213 if (size % FRAME_SIZE != 0) { 214 size = size + (FRAME_SIZE - size % FRAME_SIZE); 215 } 216 ASSERT(size % FRAME_SIZE == 0); 217 ASSERT(zone_blacklist_count <= ZONE_BLACKLIST_SIZE); 218 zone_blacklist[index].base = base; 219 zone_blacklist[index].size = size; 278 220 } 279 221 … … 288 230 list_initialize(&zone_head); 289 231 } 232 233 234 void zone_create_in_region(__address base, size_t size) { 235 int i; 236 zone_t * z; 237 __address s; size_t sz; 238 239 ASSERT(base % FRAME_SIZE == 0); 240 ASSERT(size % FRAME_SIZE == 0); 241 242 if (!size) return; 243 244 for (i = 0; i < zone_blacklist_count; i++) { 245 if (zone_blacklist[i].base >= base && zone_blacklist[i].base < base + size) { 246 s = base; sz = zone_blacklist[i].base - base; 247 ASSERT(base != s || sz != size); 248 zone_create_in_region(s, sz); 249 250 s = zone_blacklist[i].base + zone_blacklist[i].size; 251 sz = (base + size) - (zone_blacklist[i].base + zone_blacklist[i].size); 252 ASSERT(base != s || sz != size); 253 zone_create_in_region(s, sz); 254 return; 255 256 } 257 } 258 259 z = zone_create(base, size, 0); 260 261 if (!z) { 262 panic("Cannot allocate zone (%dB).\n", size); 263 } 264 265 zone_attach(z); 266 } 267 268 290 269 291 270 /** Create frame zone … … 299 278 * @return Initialized zone. 300 279 */ 301 zone_t * zone_create(__address start, size_t size, int flags)280 zone_t * zone_create(__address start, size_t size, int flags) 302 281 { 303 282 zone_t *z; … … 305 284 int i; 306 285 __u8 max_order; 307 286 287 /* hack for bug #10 */ 288 // if (start == 0x100000) size -= (FRAME_SIZE * 256); 289 290 // printf("ZONE_CREATE() %X - %X (%d kbytes) \n", start, start+size, size/1024); 308 291 ASSERT(start % FRAME_SIZE == 0); 309 292 ASSERT(size % FRAME_SIZE == 0); … … 340 323 for (max_order = 0; cnt >> max_order; max_order++); 341 324 z->buddy_system = buddy_system_create(max_order, &zone_buddy_system_operations, (void *) z); 342 } 343 325 326 /* Stuffing frames */ 327 for (i = 0; i<cnt; i++) { 328 z->frames[i].refcount = 0; 329 buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); 330 } 331 } 344 332 return z; 345 333 } … … 373 361 void frame_initialize(frame_t *frame, zone_t *zone) 374 362 { 375 frame->refcount = 0; 363 frame->refcount = 1; 364 frame->buddy_order = 0; 376 365 link_initialize(&frame->link); 377 366 } 378 367 379 380 381 /*382 * buddy system functions (under construction)383 *384 */385 386 387 /** Allocate 2^order frames388 *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 available411 * TODO: Must check if buddy system has at least block in order >= given order412 */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 510 /** Guess zone by frame instance address511 *512 * @param frame Frame513 *514 * @return Zone of given frame515 */516 zone_t * get_zone_by_frame(frame_t * frame) {517 link_t * cur;518 zone_t * zone, *z;519 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 368 545 369 /** Buddy system find_buddy implementation … … 554 378 zone_t * zone; 555 379 link_t * cur; 380 count_t index; 556 381 bool is_left, is_right; 557 382 558 383 frame = list_get_instance(block, frame_t, buddy_link); 559 zone = get_zone_by_frame(frame); 560 384 zone = (zone_t *) b->data; 561 385 562 386 /* … … 564 388 * (FRAME_INDEX % 2^(ORDER+1)) == 2^(ORDER) ===> RIGHT BUDDY 565 389 */ 566 390 567 391 is_left = IS_BUDDY_LEFT_BLOCK(zone, frame); 568 392 is_right = IS_BUDDY_RIGHT_BLOCK(zone, frame); … … 570 394 ASSERT((is_left || is_right) && (!is_left || !is_right)); 571 395 572 for (cur = &zone->buddy_system->order[frame->buddy_order]; cur; cur = cur->next) { 573 f = list_get_instance(cur, frame_t, buddy_link); 574 575 ASSERT(f->buddy_order == frame->buddy_order); 576 577 /* 578 * if found frame is coherent with our frame from the left 579 */ 580 if ((FRAME_INDEX(zone, f) + 1 >> frame->buddy_order == FRAME_INDEX(zone, frame)) && is_right) { 581 return cur; 582 } 583 584 /* 585 * if found frame is coherent with our frame from the right 586 */ 587 if ((FRAME_INDEX(zone,f) - 1 >> frame->buddy_order == FRAME_INDEX(zone, frame)) && is_left) { 588 return cur; 589 } 590 396 /* 397 * test left buddy 398 */ 399 if (is_left) { 400 index = (FRAME_INDEX(zone, frame)) + (1 << frame->buddy_order); 401 } else if (is_right) { 402 index = (FRAME_INDEX(zone, frame)) - (1 << frame->buddy_order); 403 } 404 405 if (FRAME_INDEX_VALID(zone, index)) { 406 if ( zone->frames[index].buddy_order == frame->buddy_order && 407 zone->frames[index].refcount == 0) { 408 return &zone->frames[index].buddy_link; 409 } 591 410 } 592 411 593 412 return NULL; 594 595 413 596 414 } … … 605 423 link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) { 606 424 frame_t * frame_l, * frame_r; 607 608 425 frame_l = list_get_instance(block, frame_t, buddy_link); 609 610 frame_r = (frame_t *) (&frame_l + (1>>frame_l->buddy_order-1)); 611 426 frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); 612 427 return &frame_r->buddy_link; 613 614 428 } 615 429 … … 624 438 link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, link_t * block_2) { 625 439 frame_t * frame1, * frame2; 626 627 440 frame1 = list_get_instance(block_1, frame_t, buddy_link); 628 441 frame2 = list_get_instance(block_2, frame_t, buddy_link); 629 630 return &frame1 < &frame2 ? block_1 : block_2; 442 return frame1 < frame2 ? block_1 : block_2; 631 443 } 632 444 … … 655 467 return frame->buddy_order; 656 468 } 469 470 /** Buddy system mark_busy implementation 471 * 472 * @param b Buddy system 473 * @param block Buddy system block 474 * 475 */ 476 void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { 477 frame_t * frame; 478 frame = list_get_instance(block, frame_t, buddy_link); 479 frame->refcount = 1; 480 }
Note:
See TracChangeset
for help on using the changeset viewer.