Ejemplo n.º 1
0
        // 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);
            }
        }
Ejemplo n.º 2
0
        static uint buddy_num_free_page(mem_zone *zone)
        {
            byte i;
            uint ret;

            for (i = 0, ret = 0; i < BUDDY_MAX_ORDER; i++)
            {
                ret += zone->free_area[i].nr_free * (1U << i);
            }
            return(ret);
        }
Ejemplo n.º 3
0
        ////////////////////////////////////////////////

        public static void *page_to_virt(mem_zone *zone,
                                         page *page)
        {
            uint page_idx = 0;
            uint address  = 0;

            page_idx = (uint)(page - zone->first_page);
            address  = zone->start_addr + (page_idx * BUDDY_PAGE_SIZE);

            return((void *)address);
        }
Ejemplo n.º 4
0
        public static page *buddy_get_pages(mem_zone *zone,
                                            byte order)
        {
            page *page = null;

            if (order >= BUDDY_MAX_ORDER)
            {
                BUDDY_BUG("error");
                return(null);
            }
            //TODO: lock zone->lock
            page = __alloc_page(order, zone);
            //TODO: unlock zone->lock
            return(page);
        }
Ejemplo n.º 5
0
        /// <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);
            }
        }
Ejemplo n.º 6
0
        public static page *virt_to_page(mem_zone *zone, void *ptr)
        {
            uint  page_idx = 0;
            page *page     = null;
            uint  address  = (uint)ptr;

            if ((address < zone->start_addr) || (address > zone->end_addr))
            {
                //printf("start_addr=0x%lx, end_addr=0x%lx, address=0x%lx\n",
                //        zone->start_addr, zone->end_addr, address);
                BUDDY_BUG("error");
                return(null);
            }
            page_idx = (address - zone->start_addr) >> BUDDY_PAGE_SHIFT;

            page = zone->first_page + page_idx;
            return(page);
        }
Ejemplo n.º 7
0
        public static void buddy_free_pages(mem_zone *zone,
                                            page *page)
        {
            byte order = compound_order(page);
            uint buddy_idx = 0, combinded_idx = 0;
            uint page_idx = (uint)(page - zone->first_page);

            //TODO: lock zone->lock
            if (PageCompound(page))
            {
                if (destroy_compound_pages(page, order))
                {
                    BUDDY_BUG("error");
                }
            }

            while (order < BUDDY_MAX_ORDER - 1)
            {
                page *buddy;
                // find and delete buddy to combine
                buddy_idx = __find_buddy_index(page_idx, order);
                buddy     = page + (buddy_idx - page_idx);
                if (!page_is_buddy(buddy, order))
                {
                    break;
                }
                list_del(&buddy->lru);
                zone->free_area[order].nr_free--;
                // remove buddy's flag and order
                rmv_page_order_buddy(buddy);
                // update page and page_idx after combined
                combinded_idx = __find_combined_index(page_idx, order);
                page          = page + (combinded_idx - page_idx);
                page_idx      = combinded_idx;
                order++;
            }
            set_page_order_buddy(page, order);
            list_add(&page->lru, &zone->free_area[order].free_list);
            zone->free_area[order].nr_free++;
            //TODO: unlock zone->lock
        }
Ejemplo n.º 8
0
        public static Page *buddy_get_pages(mem_zone *zone,
                                            byte order)
        {
            BUDDY_TRACE("buddy_get_pages, Order: {0:X8}", order);

            Page *page = null;

            if (order >= BUDDY_MAX_ORDER)
            {
                BUDDY_BUG("buddy_get_pages: order >= BUDDY_MAX_ORDER, {0}", order);
                return(null);
            }
            //TODO: lock zone->lock
            page = __alloc_page(order, zone);
            //TODO: unlock zone->lock

            if (page == null)
            {
                BUDDY_TRACE("Out of Memory?");
            }

            return(page);
        }
Ejemplo n.º 9
0
        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);
        }