The call relationship between Linux memory release functions is shown in. the result is the _ free_pages () function, the following figure shows the workflow of the function execution. the code [cpp] void _ free_pages (structpage * page ,...
The call relationship between Linux memory release functions is shown in. the result is the _ free_pages () function. the execution workflow is shown in.
The following code shows the function: [cpp] void _ free_pages (struct page * page, unsigned int order) {if (put_page_testzero (page )) {/* The judgment page is not used */trace_mm_page_free_direct (page, order); if (order = 0) /* a single page is released to the cache of each CPU page */free_hot_page (page); www.2cto.com else/* multiple pages are released to the partner system */_ free_pages_ OK (page, order) ;}} first, this function checks whether the page is idle by reference counting the page descriptor, and then determines the number of pages to be released, if it is a single page, the page will be released as a hot page to pcp, if it is a multi-page, it will be released to the partner system [cpp] void free_hot_page (stru Ct page * page) {struct (page, 0); free_hot_cold_page (page, 0);} free_hot_page is the encapsulation of free_hot_cold_page [cpp] static void free_hot_cold_page (struct page * page, int cold) {struct zone * zone = page_zone (page); struct per_cpu_pages * pcp; unsigned long flags; int migratetype; int wasMlocked = _ TestClearPageMlocked (page ); www.2cto.com kmemcheck_free_shadow (page, 0); if (PageAnon (page)) Page-> mapping = NULL; if (free_pages_check (page) return; if (! PageHighMem (page) {debug_check_no_locks_freed (page_address (page), PAGE_SIZE); aggregate (page_address (page), PAGE_SIZE);} arch_free_page (page, 0); kernel_map_pages (page, 1, 0);/* obtain the corresponding pcp structure */pcp = & zone_pcp (zone, get_cpu ()-> pcp; /* obtain the migration type */migratetype = get_pageblock_migratetype (page); set_page_private (page, migratetype); local_irq_save (flags); if (unlikely (wasMlocked) free_page _ Mlock (page); _ count_vm_event (PGFREE);/** We only track unmovable, reclaimable and movable on pcp lists. * Free ISOLATE pages back to the allocator because they are being * offlined but treat RESERVE as movable pages so we can get those * areas back if necessary. otherwise, we may have to free * excessively into the page allocator * // * only the pages that can be recycled and moved can be placed in the cache of each CPU page box, if the migration type does not belong to this range, release the page back to the partner system. System */if (migratetype> = MIGRATE_PCPTYPES) {if (unlikely (migratetype = MIGRATE_ISOLATE) {free_one_page (zone, page, 0, migratetype); goto out ;} migratetype = MIGRATE_MOVABLE;} if (cold)/* insert the end of the cold page */list_add_tail (& page-> lru, & pcp-> lists [migratetype]); else/* hot page insert header */www.2cto.com list_add (& page-> lru, & pcp-> lists [migratetype]); pcp-> count ++; /* if the number of pages in pcp exceeds high, Release 2 ^ batch single page to partner system */if (pcp-> count> = Pcp-> high) {free_pcppages_bulk (zone, pcp-> batch, pcp); pcp-> count-= pcp-> batch;} out: local_irq_restore (flags ); put_cpu ();} the branch of the partner system _ free_pages_ OK () first checks the released page, and then calls free_one_page () -- >__ free_one_page () to [cpp] static inline void _ free_one_page (struct page * page, struct zone * zone, unsigned int order, int migratetype) {unsigned long page_idx; if (unlikely (PageCompound (page) if (unli Kely (destroy_compound_page (page, order) return; VM_BUG_ON (migratetype =-1);/* get the offset of the page box in the largest block */page_idx = page_to_pfn (page) & (1 <MAX_ORDER)-1); VM_BUG_ON (page_idx & (1 <order)-1); VM_BUG_ON (bad_range (zone, page )); /* as long as the order is smaller than the MAX_ORDER-1, there is a chance to merge */while (order <MAX_ORDER-1) {unsigned long combined_idx; struct page * buddy; /* find the partner block corresponding to the page block */buddy = _ page_find_buddy (page, page_idx, o Rder);/* if the partner block is not idle, do not perform the following merge operations */if (! Page_is_buddy (page, buddy, order) break;/* Our buddy is free, merge with it and move up one order. */list_del (& buddy-> lru);/* delete the partner block from the block linked list */zone-> free_area [order]. nr_free --; rmv_page_order (buddy);/* calculate the offset of the start page of the merged block */combined_idx = _ find_combined_index (page_idx, order ); /* get the start page descriptor of the merged block */page = page + (combined_idx-page_idx); page_idx = combined_idx;/* modify the start page offset of the block */order ++; /* order addition 1 indicates that the merge is completed */} www. 2CT O.com/* reset the order of the block */set_page_order (page, order);/* Add the new block to the corresponding linked list */list_add (& page-> lru, & zone-> free_area [order]. free_list [migratetype]); zone-> free_area [order]. nr_free ++;} two helper functions are involved here. _ page_find_buddy () is used to find the partner who releases the block. if a free partner block is found, the _ find_combined_index () it is used to locate the start page of the merged block, because the partner block of a block may be in front of the block or behind the block. the implementation of these two functions is very concise and clever, [cpp] static inline struct page * _ page_find_buddy (struct page * page, unsigne D long page_idx, unsigned int order) {unsigned long buddy_idx = page_idx ^ (1 <order); return page + (buddy_idx-page_idx );} [cpp] static inline unsigned long _ find_combined_index (unsigned long page_idx, unsigned int order) {return (page_idx &~ (1 <order);} we can simulate this process in a simple case. suppose there is a page to be released, and its order is 0, if page_idx is 10 www.2cto.com, calculate its partner 10 ^ (1 <0) = 11, and then calculate the offset of the merged start page as 10 &~ (1 <0) = 10, now we get a block with an order of 1. the start page offset is 10, and its partner is 10 ^ (1 <1) = 8, the offset of the merged start page is 10 &~ (1 <1) = 8. in this derivation, we can analyze the process in a clearer way than the following table. pi represents page_idx, and ci represents combined_idx, author vanbreaker.
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.