arm64内存-build_all_zonelists

上一篇: zone sizes init - free area init

https://www.cnblogs.com/zhangzhiwei122/p/16098846.html

 

start_kernel -> build_all_zonelist(NULL)

 848asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
 849{
 850        char *command_line;
 851        char *after_dashes;

 878        build_all_zonelists(NULL);
 879        page_alloc_init();

 

build_all_zonelist

pglist_data 结构体里面有 node_zonelists 数组,数组中的每个 zoneref 对象 ,指向一个 zone 对象。

build all zonelist 就是初始化 各个 pglist_data 对象(在UMA 下,也就只有 1 个 pglist_data 对象)里面的 node_zonelists 数组。

mm/page_alloc.c

5987void __ref build_all_zonelists(pg_data_t *pgdat)
5988{
5989        unsigned long vm_total_pages;
5990
5991        if (system_state == SYSTEM_BOOTING) {
5992                build_all_zonelists_init();
5993        } else {
5994                __build_all_zonelists(pgdat);
5995                /* cpuset refresh routine should be here */
5996        }
5997        /* Get the number of free pages beyond high watermark in all zones. */
5998        vm_total_pages = nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE));

6006        if (vm_total_pages < (pageblock_nr_pages * MIGRATE_TYPES))
6007                page_group_by_mobility_disabled = 1;
6008        else
6009                page_group_by_mobility_disabled = 0;
6010

6018}

5992 - 在 SYSTEM_BOOTING 阶段,调用 build_all_zonelists_init

5998 ~ 6009 如果 free pages 不够多,就把 page group by mobility 功能给关闭。

 

build_all_zonelists_init

mm/page_alloc.c

5954static noinline void __init
5955build_all_zonelists_init(void)
5956{

5959        __build_all_zonelists(NULL);

5974        for_each_possible_cpu(cpu)
5975                setup_pageset(&per_cpu(boot_pageset, cpu), 0);

5977        mminit_verify_zonelist();
5978        cpuset_init_current_mems_allowed();
5979}

5959 - 调用 __build_all_zonelists - 传入参数为 NULL,表示对所有 online 的 node 的 pglist_data 对象的  node_zonelists 进行初始化。(下面分析)

5974 ~ 5975  对每个 cpu 的 boot_pageset 对象进行初始化,并将他设置到 。 per_cpu_pageset 结构体在 include/linux/mmzone.h (下面分析)

5977  mminit_verify_zonelis 对 初始化后的 zonelists 进行验证,出错打印log 信息。 略

5978 cpuset_init_current_mems_allowed , 将 current->mems_allowed 这个  nodemask 都置位 。 略

 

__build_all_zonelists

5911static void __build_all_zonelists(void *data)
5912{
5915        pg_data_t *self = data;

5928        if (self && !node_online(self->node_id)) {
5929                build_zonelists(self);
5930        } else {
5931                for_each_online_node(nid) {
5932                        pg_data_t *pgdat = NODE_DATA(nid);
5934                        build_zonelists(pgdat);
5935                }
5936

5952}

 传入的 data 为NULL, 则对所有 online 的node 都调用 build_zonelists( pgdat ); 

build_zonelists 在 UMA 和 NUMA 下面有不同实现,只分析 UMA 下的实现。

5853static void build_zonelists(pg_data_t *pgdat)
5854{
5855        int node, local_node;
5856        struct zoneref *zonerefs;
5857        int nr_zones;
5858
5859        local_node = pgdat->node_id;

5861        zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs;
5862        nr_zones = build_zonerefs_node(pgdat, zonerefs);
5863        zonerefs += nr_zones;

5873        for (node = local_node + 1; node < MAX_NUMNODES; node++) {
5874                if (!node_online(node))
5875                        continue;
5876                nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs);
5877                zonerefs += nr_zones;
5878        }
5879        for (node = 0; node < local_node; node++) {
5880                if (!node_online(node))
5881                        continue;
5882                nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs);
5883                zonerefs += nr_zones;
5884        }
5885
5886        zonerefs->zone = NULL;
5887        zonerefs->zone_idx = 0;
5888}

5861 行取得  pgdat 的node_zonelist[ 0 ] 这个对象的 _zonerefs 成员,这个成员是  一个 数组。 所以用指针 struct zoneref * 指针 zonerefs 表示它。

5862 将 pgdat 里面的 zone (地址,idx ) 都 set 到 zonerefs 数组里面。返回 nr_zones 表示 pgdat 里面具有的 zone 个数。

5863  zonerefs 向后跳过  nr_zones 个。

5873 ~ 5884 对其他的  node 的 pgdat 里面的 zone ( 地址 和  idx )也 set 到 zonerefs 数组里面。

 

5886 ~ 5887 zonerefs 最后一个 元素 设置为 空。

 

boot_cpuset 初始化

 319struct per_cpu_pages {
 320        int count;              /* number of pages in the list */
 321        int high;               /* high watermark, emptying needed */
 322        int batch;              /* chunk size for buddy add/remove */
 323
 324        /* Lists of pages, one per migrate type stored on the pcp-lists */
 325        struct list_head lists[MIGRATE_PCPTYPES];
 326};
  
 328struct per_cpu_pageset {
 329        struct per_cpu_pages pcp;

 335        s8 stat_threshold;
 336        s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS];

 338};
  

boot_pageset 对象在 mm/page_alloc.c

5908static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset);
5909static DEFINE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);

setup_pageset - 根据 batch 初始化 给定的  per_cpu_pageset 对象。 batch 给定为0 , 则 pcp 对象的 batch 为 1, high 为 0 ;

6302static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
6303{
6304        pageset_init(p);
6305        pageset_set_batch(p, batch);
6306}

 

posted @ 2022-04-04 15:57  张志伟122  阅读(210)  评论(0编辑  收藏  举报