日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

baddy:核心函数入口

發(fā)布時(shí)間:2023/12/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 baddy:核心函数入口 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上一篇<<baddy:初始化內(nèi)存域>>分析了內(nèi)存域的初始化過(guò)程,及擴(kuò)展內(nèi)容cpu熱插拔函數(shù)的注冊(cè)及熱插拔線程的作用等等。UMA下只有一個(gè)pglist_data對(duì)象也就是對(duì)應(yīng)一個(gè)內(nèi)存域,而NUMA下最多擁有5個(gè)內(nèi)存域(zone), ZONE_DMA、ZONE_DMA32、ZONE_NORMAL、ZONE_HIGHMEM、ZONE_MOVABLE等等,內(nèi)存域類型根據(jù)具體硬件來(lái)決定。

baddy系統(tǒng)的入口(核心)函數(shù)為_(kāi)_alloc_pages,經(jīng)典調(diào)用可以追溯到slub分配器的kmalloc函數(shù),參考<<slub構(gòu)建過(guò)程>>。


__alloc_pages

? __alloc_pages函數(shù)實(shí)現(xiàn)在mm/page_alloc.c文件:

struct page *__alloc_pages(gfp_t gfp, unsigned int order, int preferred_nid,nodemask_t *nodemask) {struct page *page;unsigned int alloc_flags = ALLOC_WMARK_LOW; // 默認(rèn)低水位線// #define ALLOC_WMARK_MIN WMARK_MIN // 最低水位線// #define ALLOC_WMARK_LOW WMARK_LOW // 低水位線// #define ALLOC_WMARK_HIGH WMARK_HIGH // 高水位線// #define ALLOC_NO_WATERMARKS 0x04 // 不檢查水位線// enum zone_watermarks {// WMARK_MIN, // 內(nèi)存區(qū)域的空閑頁(yè)面最低水位線,說(shuō)明本區(qū)域的內(nèi)存嚴(yán)重不足// WMARK_LOW, // 內(nèi)存區(qū)域的空閑頁(yè)面低水位線,說(shuō)明本區(qū)域的內(nèi)存輕微不足,默認(rèn)值為WMARK_MIN的125%// WMARK_HIGH, // 內(nèi)存區(qū)域的空閑頁(yè)數(shù)高水位線,說(shuō)明本區(qū)域內(nèi)存充足,默認(rèn)值為WMARK_MAX的150%// WMARK_PROMO, // 內(nèi)存區(qū)域的空閑頁(yè)面大于高水位線;當(dāng)內(nèi)存需要回收時(shí),對(duì)快速內(nèi)存節(jié)點(diǎn)通過(guò)kswapd以回收頁(yè)面,至空閑頁(yè)面略高于WMARK_PROMO水位線// NR_WMARK // unsigned long _watermark[NR_WMARK]; 表示區(qū)域(zone)水平線,由WMARK_MIN... WMARK_PROMO索引// };gfp_t alloc_gfp; /* The gfp_t that was actually used for allocation */struct alloc_context ac = { };/** There are several places where we assume that the order value is sane* so bail out early if the request is out of bound.*/if (WARN_ON_ONCE_GFP(order >= MAX_ORDER, gfp)) // 調(diào)用dump_stack,打印堆棧信息,指定__GFP_NOWARN標(biāo)志時(shí),不輸出警告信息return NULL;gfp &= gfp_allowed_mask;// 在早期引導(dǎo)期間,gfp_allowed_mask被設(shè)置為GFP_BOOT_MASK,// 以限制在啟用中斷之前使用的GFP標(biāo)志// 一旦啟用了中斷,在系統(tǒng)運(yùn)行時(shí)將其設(shè)置為_(kāi)_GFP_BITS_MASK// 在休眠期間,PM使用它來(lái)避免設(shè)備掛起時(shí)內(nèi)存分配期間的I/O/* 應(yīng)用作用域分配約束。這主要是關(guān)于GFP_NOFS的。GFP_NOIO必須從一個(gè)特定的上下文繼承所有的分配請(qǐng)求,該上下文被標(biāo)記為memalloc_no{fs,io}_{save,restore}。PF_MEMALLOC_PIN確保在分配時(shí)不使用可移動(dòng)區(qū)域 */gfp = current_gfp_context(gfp);alloc_gfp = gfp;if (!prepare_alloc_pages(gfp, order, preferred_nid, nodemask, &ac,&alloc_gfp, &alloc_flags))return NULL;

? 進(jìn)入prepare_alloc_pages函數(shù):

static inline bool prepare_alloc_pages(gfp_t gfp_mask, unsigned int order,int preferred_nid, nodemask_t *nodemask,struct alloc_context *ac, gfp_t *alloc_gfp,unsigned int *alloc_flags) {ac->highest_zoneidx = gfp_zone(gfp_mask); // highest_zoneidx表示分配請(qǐng)求的最高可用區(qū)域索引// 由于分區(qū)的性質(zhì),低于highest_zoneidx的分區(qū)上的內(nèi)存將受到lowmem_reserve[highest_zoneidx]的保護(hù)// 回收/壓縮也使用最高的zoneidx來(lái)限制目標(biāo)區(qū)域// 因?yàn)楦哂诖怂饕膮^(qū)域不能用于此分配請(qǐng)求ac->zonelist = node_zonelist(preferred_nid, gfp_mask); // 獲取區(qū)域列表ac->nodemask = nodemask;ac->migratetype = gfp_migratetype(gfp_mask); // 將GFP標(biāo)志轉(zhuǎn)換為其相應(yīng)的遷移類型if (cpusets_enabled()) { // cpusets有效*alloc_gfp |= __GFP_HARDWALL; // __GFP_HARDWALL 強(qiáng)制執(zhí)行cpuset內(nèi)存分配策略/** When we are in the interrupt context, it is irrelevant* to the current task context. It means that any node ok.*/if (in_task() && !ac->nodemask) // 在任務(wù)上下文中并且nodemask為NULLac->nodemask = &cpuset_current_mems_allowed;// #define cpuset_current_mems_allowed (current->mems_allowed)else*alloc_flags |= ALLOC_CPUSET; // 檢查cpuset是否正確}fs_reclaim_acquire(gfp_mask); // 檢查(符合)/增加頁(yè)面回收獨(dú)占鎖fs_reclaim_release(gfp_mask); // 釋放鎖might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM); // 可以回收的情況下,主動(dòng)觸發(fā)一次調(diào)度if (should_fail_alloc_page(gfp_mask, order)) // should_fail_alloc_page做一些預(yù)檢查, 一些無(wú)法分配的條件會(huì)直接報(bào)錯(cuò)return false;*alloc_flags = gfp_to_alloc_flags_cma(gfp_mask, *alloc_flags); // 允許來(lái)自CMA區(qū)域的分配 ?ac->spread_dirty_pages = (gfp_mask & __GFP_WRITE);// __GFP_WRITE表示調(diào)用者允許獲取臟頁(yè)面// 在可能的情況下,這些頁(yè)面將分布在本地區(qū)域之間// 以避免所有臟頁(yè)面位于一個(gè)區(qū)域中(公平區(qū)域分配策略)ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,ac->highest_zoneidx, ac->nodemask); // 首選區(qū)域用于統(tǒng)計(jì),它也用作zonelist迭代器的起點(diǎn)// 返回位于或低于允許節(jié)點(diǎn)掩碼內(nèi)給定區(qū)域索引的第一個(gè)區(qū)域return true; }

? 繼續(xù)看__alloc_pages函數(shù):

alloc_flags |= alloc_flags_nofragment(ac.preferred_zoneref->zone, gfp); // 計(jì)算分配標(biāo)志page = get_page_from_freelist(alloc_gfp, order, alloc_flags, &ac); // 從足夠空閑的區(qū)域中分配頁(yè) || \/ static struct page * get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,const struct alloc_context *ac) {...no_fallback = alloc_flags & ALLOC_NOFRAGMENT;z = ac->preferred_zoneref;for_next_zone_zonelist_nodemask(zone, z, ac->highest_zoneidx,ac->nodemask) { // 掃描區(qū)域列表,尋找一個(gè)有足夠空閑的區(qū)域if (cpusets_enabled() &&(alloc_flags & ALLOC_CPUSET) &&!__cpuset_zone_allowed(zone, gfp_mask))// cpusets有效并且已設(shè)置ALLOC_CPUSET標(biāo)志,在符合條件的區(qū)域中尋找continue;if (ac->spread_dirty_pages) { // 允許獲取臟頁(yè)面if (last_pgdat != zone->zone_pgdat) { 如果區(qū)域的zone_pgdat節(jié)點(diǎn)不等于 last_pgdat節(jié)點(diǎn)last_pgdat = zone->zone_pgdat; // 賦給last_pgdatlast_pgdat_dirty_ok = node_dirty_ok(zone->zone_pgdat);}if (!last_pgdat_dirty_ok)continue;}if (no_fallback && nr_online_nodes > 1 &&zone != ac->preferred_zoneref->zone) {// 避免混合頁(yè)面塊類型 并且 NUMA節(jié)點(diǎn)數(shù)量大于1 并且 當(dāng)前遍歷到的區(qū)域不是起點(diǎn)區(qū)域int local_nid;/** If moving to a remote node, retry but allow* fragmenting fallbacks. Locality is more important* than fragmentation avoidance.*/local_nid = zone_to_nid(ac->preferred_zoneref->zone);if (zone_to_nid(zone) != local_nid) { // 如果不是本地節(jié)點(diǎn)alloc_flags &= ~ALLOC_NOFRAGMENT; // 取消ALLOC_NOFRAGMENT標(biāo)志goto retry;}}mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK); // 如果分配標(biāo)志為低水位線(默認(rèn)值)if (!zone_watermark_fast(zone, order, mark,ac->highest_zoneidx, alloc_flags,gfp_mask)) { // 區(qū)域水位線是否符合分配int ret;...ret = node_reclaim(zone->zone_pgdat, gfp_mask, order); // 回收未映射(使用)的文件備份頁(yè)面switch (ret) {case NODE_RECLAIM_NOSCAN:/* did not scan */continue;case NODE_RECLAIM_FULL:/* scanned but unreclaimable */continue;default:/* did we reclaim enough */if (zone_watermark_ok(zone, order, mark,ac->highest_zoneidx, alloc_flags)) // 當(dāng)前內(nèi)存區(qū)中的頁(yè)面是否在水位線以上goto try_this_zone;continue;}}try_this_zone: page = rmqueue(ac->preferred_zoneref->zone, zone, order,gfp_mask, alloc_flags, ac->migratetype); // 遷移到指定類型,合并成連續(xù)的頁(yè),喚醒kswapd

? rmqueue函數(shù)分析,繼續(xù)看__alloc_pages函數(shù):

if (page) {prep_new_page(page, order, gfp_mask, alloc_flags); // 準(zhǔn)備分配頁(yè),lru.next = 1 ?0/** If this is a high-order atomic allocation then check* if the pageblock should be reserved for the future*/if (unlikely(order && (alloc_flags & ALLOC_HARDER)))reserve_highatomic_pageblock(page, zone, order); // 保留pageblock以獨(dú)占使用高階原子分配return page;}...if (no_fallback) {alloc_flags &= ~ALLOC_NOFRAGMENT; // 去除避免混合頁(yè)面塊類型標(biāo)志goto retry;}return NULL; }

? 繼續(xù)看__alloc_pages函數(shù):

alloc_gfp = gfp; ac.spread_dirty_pages = false; ac.nodemask = nodemask; page = __alloc_pages_slowpath(alloc_gfp, order, &ac);

? __alloc_pages_slowpath函數(shù)分析,繼續(xù)看__alloc_pages函數(shù):

out:if (memcg_kmem_enabled() && (gfp & __GFP_ACCOUNT) && page &&unlikely(__memcg_kmem_charge_page(page, gfp, order) != 0)) {// mem_cgroup開(kāi)啟 并且 頁(yè)分配在mem_cgroup 并且 頁(yè)有效 并且 mem_cgroup不能控制頁(yè)__free_pages(page, order); // 釋放頁(yè)page = NULL;}trace_mm_page_alloc(page, order, alloc_gfp, ac.migratetype); // 增加trace打印頁(yè)相關(guān)信息return page; } EXPORT_SYMBOL(__alloc_pages);

? 到這里頁(yè)分配核心函數(shù)流程分析完成了,? 查看trace_mm_page_alloc函數(shù)分析。


rmqueue

static inline struct page *rmqueue(struct zone *preferred_zone,struct zone *zone, unsigned int order,gfp_t gfp_flags, unsigned int alloc_flags,int migratetype) {unsigned long flags;struct page *page;if (likely(pcp_allowed_order(order))) { // 檢查是否符合order標(biāo)準(zhǔn),普通頁(yè)order <= 3,32KB或以內(nèi)// 大頁(yè)order <= 9,2MB或以內(nèi)if (!IS_ENABLED(CONFIG_CMA) || alloc_flags & ALLOC_CMA ||migratetype != MIGRATE_MOVABLE) { // 如果支持CMA內(nèi)存分配器(分配大塊連續(xù)物理內(nèi)存)page = rmqueue_pcplist(preferred_zone, zone, order,gfp_flags, migratetype, alloc_flags);// 從每cpu列表中取出page(釋放lru)goto out;}}/* 我們絕對(duì)不希望調(diào)用方使用__GFP_NOFAIL分配大于order-1的頁(yè)面單元 */WARN_ON_ONCE((gfp_flags & __GFP_NOFAIL) && (order > 1));do {page = NULL;spin_lock_irqsave(&zone->lock, flags);/* 當(dāng)由于非cma分配上下文跳過(guò)pcplist時(shí),order-0請(qǐng)求可以到達(dá)這里。*//* HIGHATOMIC區(qū)域是為高階原子分配保留的,因此order-0請(qǐng)求應(yīng)該跳過(guò)它 */if (order > 0 && alloc_flags & ALLOC_HARDER)page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);// 遍歷指定的migratetype的空閑列表,并從空閑列表中刪除最小的可用頁(yè)面 zone->free_area[order].nr_free--;// 合并到連續(xù)的頁(yè)面 free_area->free_listif (!page) {page = __rmqueue(zone, order, migratetype, alloc_flags);// 合并到連續(xù)的(CMA)頁(yè)面 if (!page)goto failed;}__mod_zone_freepage_state(zone, -(1 << order),get_pcppage_migratetype(page)); // 修改頁(yè)狀態(tài)spin_unlock_irqrestore(&zone->lock, flags);} while (check_new_pages(page, order));__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order); // 更新每cpu狀態(tài)zone_statistics(preferred_zone, zone, 1); // 更新當(dāng)前zone的統(tǒng)計(jì)信息out:/* Separate test+clear to avoid unnecessary atomics */if (test_bit(ZONE_BOOSTED_WATERMARK, &zone->flags)) {clear_bit(ZONE_BOOSTED_WATERMARK, &zone->flags); // 清除ZONE_BOOSTED_WATERMARK標(biāo)志wakeup_kswapd(zone, 0, 0, zone_idx(zone)); // 喚醒kswapd// 如果區(qū)域具有由伙伴分配器管理的頁(yè)面,則返回true// 所有回收決策都必須使用此函數(shù)}VM_BUG_ON_PAGE(page && bad_range(zone, page), page);return page;failed:spin_unlock_irqrestore(&zone->lock, flags);return NULL; }

__alloc_pages_slowpath

static inline struct page * __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,struct alloc_context *ac){bool can_direct_reclaim = gfp_mask & __GFP_DIRECT_RECLAIM;const bool costly_order = order > PAGE_ALLOC_COSTLY_ORDER;...if (WARN_ON_ONCE((gfp_mask & (__GFP_ATOMIC|__GFP_DIRECT_RECLAIM)) ==(__GFP_ATOMIC|__GFP_DIRECT_RECLAIM)))// 如果gfp_mask包含__GFP_ATOMIC和__GFP_DIRECT_RECLAIM標(biāo)志,輸出一次警告// %__GFP_ATOMIC表示調(diào)用者不能回收或休眠// %__GFP_DIRECT_RECLAIM表示調(diào)用者可以直接回收gfp_mask &= ~__GFP_ATOMIC; // 去除__GFP_ATOMIC標(biāo)志.../* 快速路徑僅在需要喚醒kswapd之前使用alloc_flags */alloc_flags = gfp_to_alloc_flags(gfp_mask);/* 我們需要重新計(jì)算區(qū)域列表迭代器的起點(diǎn),因?yàn)槲覀兛赡茉诳焖俾窂街惺褂昧瞬煌墓?jié)點(diǎn)掩碼,或者有一個(gè)cpuset修改,我們正在重試,否則我們可能會(huì)在不合格的區(qū)域上無(wú)休止地迭代 */ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,ac->highest_zoneidx, ac->nodemask);// 首選區(qū)域用于統(tǒng)計(jì),它也用作zonelist迭代器的起點(diǎn)// 返回位于或低于允許節(jié)點(diǎn)掩碼內(nèi)給定區(qū)域索引的第一個(gè)區(qū)域if (!ac->preferred_zoneref->zone)goto nopage;...if (alloc_flags & ALLOC_KSWAPD) wake_all_kswapds(order, gfp_mask, ac); // 喚醒所有kswapd線程page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac); // 從足夠空閑的區(qū)域中分配頁(yè)if (page)goto got_pg;/* 對(duì)于開(kāi)銷較大的分配,請(qǐng)先嘗試直接壓縮,因?yàn)楹芸赡芪覀冇凶銐虻幕?yè),不需要回收。對(duì)于不可移動(dòng)的高順序分配,也要這樣做,因?yàn)閴嚎s將嘗試通過(guò)從相同migratetype的塊遷移來(lái)防止永久碎片。對(duì)于允許忽略水印的分配,不要嘗試這樣做,因?yàn)檫€沒(méi)有試過(guò)alloc_no_watermark(可以測(cè)試一下) */if (can_direct_reclaim &&(costly_order ||(order > 0 && ac->migratetype != MIGRATE_MOVABLE))&& !gfp_pfmemalloc_allowed(gfp_mask)) {page = __alloc_pages_direct_compact(gfp_mask, order,alloc_flags, ac,INIT_COMPACT_PRIORITY,&compact_result); // 在回收之前,嘗試對(duì)高階分配進(jìn)行內(nèi)存壓縮 if (page)goto got_pg;/* 使用__GFP_NORETRY檢查昂貴的分配,其中包括一些THP頁(yè)面錯(cuò)誤分配 */ if (costly_order && (gfp_mask & __GFP_NORETRY)) {if (compact_result == COMPACT_SKIPPED ||compact_result == COMPACT_DEFERRED) // 內(nèi)存無(wú)法壓縮或壓縮失敗goto nopage;/* 看起來(lái)回收/壓縮值得一試,但同步壓縮可能非常昂貴,所以請(qǐng)繼續(xù)使用異步壓縮 */compact_priority = INIT_COMPACT_PRIORITY;}} retry:/* Ensure kswapd doesn't accidentally go to sleep as long as we loop */if (alloc_flags & ALLOC_KSWAPD)wake_all_kswapds(order, gfp_mask, ac); // 喚醒所有kswapd線程reserve_flags = __gfp_pfmemalloc_flags(gfp_mask);// 區(qū)分真正需要訪問(wèn)全部?jī)?nèi)存儲(chǔ)備的請(qǐng)求和可以接受部分內(nèi)存的請(qǐng)求if (reserve_flags)alloc_flags = gfp_to_alloc_flags_cma(gfp_mask, reserve_flags); // 允許來(lái)自CMA區(qū)域的分配 ?/* 如果可以忽略內(nèi)存策略,請(qǐng)重置nodemask和zonelist迭代器這些分配具有高優(yōu)先級(jí)和系統(tǒng)性,而不是面向用戶 */if (!(alloc_flags & ALLOC_CPUSET) || reserve_flags) {ac->nodemask = NULL;ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,ac->highest_zoneidx, ac->nodemask);}/* 嘗試使用可能已經(jīng)調(diào)整的區(qū)域列表和alloc_flags */page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);if (page)goto got_pg;/* 調(diào)用者不愿意回收頁(yè)(頁(yè)標(biāo)識(shí)沒(méi)有設(shè)置),我們無(wú)法平衡任何事情if (!can_direct_reclaim)goto nopage;/* 避免遞歸回收 */if (current->flags & PF_MEMALLOC)goto nopage;/* 嘗試直接壓縮,然后分配 */page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,&did_some_progress);if (page)goto got_pg;// __GFP_NORETRY 嘗試輕量級(jí)的回收,避免循環(huán),避免oom killer那樣直接破壞if (gfp_mask & __GFP_NORETRY)goto nopage;// 如果有跡象表明在其他地方取得了進(jìn)展,// 虛擬機(jī)實(shí)現(xiàn)將重試以前失敗的內(nèi)存回收過(guò)程// 它可以等待其他任務(wù)嘗試高級(jí)方法來(lái)釋放內(nèi)存,例如壓縮(消除碎片)和分頁(yè)if (costly_order && !(gfp_mask & __GFP_RETRY_MAYFAIL))goto nopage;// 檢查重試回收以向前推進(jìn)給定的分配請(qǐng)求是否有意義// 如果我們連續(xù)嘗試MAX_RECLAIM_RETRIES次重試均未成功,// 或者如果我們回收LRU列表上的所有剩余頁(yè)面,// 甚至無(wú)法滿足水印要求,我們就會(huì)放棄if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,did_some_progress > 0, &no_progress_loops))goto retry;// 如果order-0回收無(wú)法取得任何進(jìn)展,// 則重試壓縮沒(méi)有任何意義,因?yàn)閴嚎s的當(dāng)前實(shí)現(xiàn)取決于足夠的可用內(nèi)存量if (did_some_progress > 0 &&should_compact_retry(ac, order, alloc_flags,compact_result, &compact_priority,&compaction_retries))goto retry;// 在我們開(kāi)始OOM殺死之前,處理可能的cpuset更新競(jìng)爭(zhēng)if (check_retry_cpuset(cpuset_mems_cookie, ac))goto retry_cpuset;// 回收失敗,開(kāi)始o(jì)om killerpage = __alloc_pages_may_oom(gfp_mask, order, ac, &did_some_progress);if (page)goto got_pg;// 避免無(wú)水線的分配無(wú)限循環(huán)if (tsk_is_oom_victim(current) &&(alloc_flags & ALLOC_OOM ||(gfp_mask & __GFP_NOMEMALLOC)))// 當(dāng)前線程被oom killer ?// oom 異步回收// __GFP_NOMEMALLOC被用來(lái)明確禁止進(jìn)入緊急儲(chǔ)備goto nopage;/* 只要oom 有進(jìn)展,就重試 */if (did_some_progress) {no_progress_loops = 0;goto retry;}nopage:/* 在失敗之前處理可能的cpuset更新競(jìng)爭(zhēng) */if (check_retry_cpuset(cpuset_mems_cookie, ac))goto retry_cpuset;/* 確保__GFP_NOFAIL請(qǐng)求不會(huì)泄漏,并確保我們總是重試 */if (gfp_mask & __GFP_NOFAIL) {/ * __GFP_NOFAIL的所有現(xiàn)有用戶都是可阻塞的,因此如果有任何新用戶實(shí)際需要GFP_NOWAIT,就會(huì)發(fā)出警告 */if (WARN_ON_ONCE_GFP(!can_direct_reclaim, gfp_mask))goto fail;/* 來(lái)自這個(gè)上下文的PF_MEMALLOC請(qǐng)求是相當(dāng)奇怪的,因?yàn)槲覀儾荒芑厥杖魏螙|西,只能循環(huán)等待某人(線程)為我們做一個(gè)工作 */WARN_ON_ONCE_GFP(current->flags & PF_MEMALLOC, gfp_mask);/* 不失敗的昂貴orders是一項(xiàng)艱巨的要求,我們對(duì)此沒(méi)有太多準(zhǔn)備,因此讓我們警告這些用戶,以便我們能夠識(shí)別他們并將其轉(zhuǎn)換為其他產(chǎn)品 */WARN_ON_ONCE_GFP(order > PAGE_ALLOC_COSTLY_ORDER, gfp_mask);/* 通過(guò)允許它們?cè)L問(wèn)內(nèi)存儲(chǔ)備來(lái)幫助非失敗的分配,但不要使用ALLOC_NO_WATERMARKS,因?yàn)檫@可能會(huì)耗盡整個(gè)內(nèi)存儲(chǔ)備,這只會(huì)使情況變得更糟 */page = __alloc_pages_cpuset_fallback(gfp_mask, order, ALLOC_HARDER, ac);if (page)goto got_pg;// 主動(dòng)放權(quán),等待下一次的調(diào)度運(yùn)行cond_resched();goto retry;} fail:// 輸出警告信息warn_alloc(gfp_mask, ac->nodemask,"page allocation failure: order:%u", order); got_pg:return page; }

trace_mm_page_alloc

? trace用于跟蹤打印信息,俗稱“插樁”,通過(guò)定義類型、變量和結(jié)構(gòu),輸出相關(guān)信息。

TRACE_EVENT(mm_page_alloc,TP_PROTO(struct page *page, unsigned int order,gfp_t gfp_flags, int migratetype), TP_ARGS(page, order, gfp_flags, migratetype), TP_STRUCT__entry(__field( unsigned long, pfn )__field( unsigned int, order )__field( unsigned long, gfp_flags )__field( int, migratetype )),TP_fast_assign(__entry->pfn = page ? page_to_pfn(page) : -1UL;__entry->order = order;__entry->gfp_flags = (__force unsigned long)gfp_flags;__entry->migratetype = migratetype;),TP_printk("page=%p pfn=0x%lx order=%d migratetype=%d gfp_flags=%s",__entry->pfn != -1UL ? pfn_to_page(__entry->pfn) : NULL,__entry->pfn != -1UL ? __entry->pfn : 0,__entry->order,__entry->migratetype,show_gfp_flags(__entry->gfp_flags)) );

目錄預(yù)覽


<<baddy:初始化內(nèi)存域>>

總結(jié)

以上是生活随笔為你收集整理的baddy:核心函数入口的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。