// print buddy system status //void dump_print(struct mem_zone * zone); //void dump_print_dot(struct mem_zone * zone); //---###--- public static void buddy_system_init(mem_zone *zone, page *start_page, uint start_addr, uint page_num) { uint i; page * page = null; free_area *area = null; // init memory zone zone->page_num = page_num; zone->page_size = BUDDY_PAGE_SIZE; zone->first_page = start_page; zone->start_addr = start_addr; zone->end_addr = start_addr + (page_num * BUDDY_PAGE_SIZE); // TODO: init zone->lock // init each area for (i = 0; i < BUDDY_MAX_ORDER; i++) { area = zone->free_area + i; INIT_LIST_HEAD(&area->free_list); area->nr_free = 0; } memset((byte *)start_page, 0, page_num * (uint)sizeof(page)); // init and free each page for (i = 0; i < page_num; i++) { page = zone->first_page + i; INIT_LIST_HEAD(&page->lru); // TODO: init page->lock buddy_free_pages(zone, page); } }
static page *expand(zone *zone, page *page, int low, int high, free_area *area) { uint size = (uint)1 << (byte)high; while (high > low) { area--; high--; size >>= 1; //BUG_ON(bad_range(zone, &page[size])); list_add(&page[size].Lru, &area->Free_list); area->Nr_free++; set_page_order(&page[size], high); } return(page); }
/// <summary> /// Split the combined page to get the page of the desired size /// </summary> static void expand(mem_zone *zone, page *page, byte low_order, byte high_order, free_area *area) { uint size = (1U << high_order); while (high_order > low_order) { area--; high_order--; size >>= 1; list_add(&page[size].lru, &area->free_list); area->nr_free++; // set page order set_page_order_buddy(&page[size], high_order); } }
static page *__alloc_page(byte order, mem_zone *zone) { page * page = null; free_area *area = null; byte current_order = 0; for (current_order = order; current_order < BUDDY_MAX_ORDER; current_order++) { area = zone->free_area + current_order; if (list_empty(&area->free_list)) { continue; } // remove closest size page //page = list_entry(area->free_list.next, struct page, lru); page = (page *)&((page *)area->free_list.next)->lru; list_del(&page->lru); rmv_page_order_buddy(page); area->nr_free--; // expand to lower order expand(zone, page, order, current_order, area); // compound page if (order > 0) { prepare_compound_pages(page, order); } else // single page { page->order = 0; } return(page); } return(null); }