• 关于page type MIGRATE_HIGHATOMIC枚举的理解


    为什么会有MIGRATE_PCPTYPES

    在分析per cpu page的时候无疑看到MIGRATE_PCPTYPES和MIGRATE_HIGHATOMIC相等,感觉挺奇怪的,花点时间分析了下。

     在分析这些特性的时候,个人还是比较喜欢追根溯源,看了下社区提交的patch记录,大致了解了设计page属性的目的。

    https://lwn.net/Articles/658081/

    There is still value in reserving blocks of memory for high-order allocations, though; fragmentation is still a concern in current kernels. So another part of Mel's patch set creates a new MIGRATE_HIGHATOMIC reserve that serves this purpose, but in a different way. Initially, this reserve contains no page blocks at all. If a high-order allocation cannot be satisfied without breaking up a previously whole page block, that block will be marked as being part of the high-order atomic reserve; thereafter, only higher-order allocations (and only high-priority ones at that) can be satisfied from that page block.

    从介绍来看,针对高阶page的申请导致的碎片一直以来就是一个令人担忧的问题,所以Mel创建了一个新的page type,MIGRATE_HIGHATOMIC,用于放置碎片化过多的问题,仅仅高阶并且具备同等级别的才能从该pageblock中申请page。

    代码实现

    在mm目录下的代码,我们可以看到少量的关于MIGRATE_HIGHATOMIC的代码

    2634 static void reserve_highatomic_pageblock(struct page *page, struct zone *zone,
    2635                                 unsigned int alloc_order)
    2636 {
    2637         int mt;
    2638         unsigned long max_managed, flags;
    2639
    2640         /*
    2641          * Limit the number reserved to 1 pageblock or roughly 1% of a zone.
    2642          * Check is race-prone but harmless.
    2643          */
    2644         max_managed = (zone_managed_pages(zone) / 100) + pageblock_nr_pages;
    2645         if (zone->nr_reserved_highatomic >= max_managed)
    2646                 return;
    2647
    2648         spin_lock_irqsave(&zone->lock, flags);
    2649
    2650         /* Recheck the nr_reserved_highatomic limit under the lock */
    2651         if (zone->nr_reserved_highatomic >= max_managed)
    2652                 goto out_unlock;
    2653
    2654         /* Yoink! */
    2655         mt = get_pageblock_migratetype(page);
    2656         if (!is_migrate_highatomic(mt) && !is_migrate_isolate(mt)
    2657             && !is_migrate_cma(mt)) {
    2658                 zone->nr_reserved_highatomic += pageblock_nr_pages;
    2659                 set_pageblock_migratetype(page, MIGRATE_HIGHATOMIC);
    2660                 move_freepages_block(zone, page, MIGRATE_HIGHATOMIC, NULL);
    2661         }
    2662
    2663 out_unlock:
    2664         spin_unlock_irqrestore(&zone->lock, flags);
    2665 }
    3788 get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
    3789                                                 const struct alloc_context *ac)
    3790 {
    3791                 page = rmqueue(ac->preferred_zoneref->zone, zone, order,
    3792                                 gfp_mask, alloc_flags, ac->migratetype);
    3793                 if (page) {
    3794                         prep_new_page(page, order, gfp_mask, alloc_flags);
    3795
    3796                         /*
    3797                          * If this is a high-order atomic allocation then check
    3798                          * if the pageblock should be reserved for the future
    3799                          */
    3800                         if (unlikely(order && (alloc_flags & ALLOC_HARDER)))
    3801                                 reserve_highatomic_pageblock(page, zone, order);
    3421 struct page *rmqueue(struct zone *preferred_zone,
    3422                         struct zone *zone, unsigned int order,
    3423                         gfp_t gfp_flags, unsigned int alloc_flags,
    3424                         int migratetype)
    3425 {
    3426         do {
    3427                 page = NULL;
    3428                 /*
    3429                  * order-0 request can reach here when the pcplist is skipped
    3430                  * due to non-CMA allocation context. HIGHATOMIC area is
    3431                  * reserved for high-order atomic allocation, so order-0
    3432                  * request should skip it.
    3433                  */
    3434                 if (order > 0 && alloceflags & ALLOC_HARDER) {
    3435                         page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);
    3436                         if (page)
    3437                                 trace_mm_page_alloc_zone_locked(page, order, migratetype);
    3438                 }
    3439                 if (!page)
    3440                         page = __rmqueue(zone, order, migratetype, alloc_flags);
    3441         } while (page && check_new_pages(page, order));
    3442 }

    从上面代码可以看到,在申请page的时候,会通过判定该page申请时的一些flags配置,例如属于ALLOC_HARDER,表明该页申请时无低阶page申请时

    从高阶获取,并且order,可以认为该page是从high order分配下来的,所以将该页加入到highatomic_pageblock中,但是该类型的页又不能无限多,否则

    后面内存紧张的时候,就无法申请page了。

    所以尽量设置该pageblock的数目小于zone里面page的1/100。

    max_managed = (zone_managed_pages(zone) / 100) + pageblock_nr_pages;

    最终会调用move_freepages_block函数将该页移动到highatomic_pageblock中去。

    cat /proc/pagetypeinfo  | grep  HighAtomic
    Node    0, zone    DMA32, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
    Node    0, zone   Normal, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
    Number of blocks type     Unmovable      Movable  Reclaimable   HighAtomic          CMA      Isolate
    Node    1, zone   Normal, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
    Number of blocks type     Unmovable      Movable  Reclaimable   HighAtomic          CMA      Isolate
    Node    2, zone   Normal, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
    Number of blocks type     Unmovable      Movable  Reclaimable   HighAtomic          CMA      Isolate
    Node    3, zone   Normal, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
    Number of blocks type     Unmovable      Movable  Reclaimable   HighAtomic          CMA      Isolate

    可以通过pagetypeinfo查看MIGRATE_HIGHATOMIC数量,在本人机器上看到HighAtomic类型的page数量为0。

    关于MIGRATE_HIGHATOMIC的释放

    内核函数往往体现这对称性,将page加入到highatomic_pageblock中去采用的reserve_highatomic_pageblock函数,而将page从

    该highatomic_pageblock移除,则调用的unreserve_highatomic_pageblock函数, 此处不再做过多的解释,大体意思如下,当alloc_page

    slow申请page的时候失败,会从该highatomic_pageblock中申请page。

    4344 __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
    4345                 unsigned int alloc_flags, const struct alloc_context *ac,
    4346                 unsigned long *did_some_progress)
    4347 {
    4348         struct page *page = NULL;
    4349         bool drained = false;
    4350
    4351         *did_some_progress = __perform_reclaim(gfp_mask, order, ac);
    4352         if (unlikely(!(*did_some_progress)))
    4353                 return NULL;
    4354
    4355 retry:
    4356         page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
    4357
    4358         /*
    4359          * If an allocation failed after direct reclaim, it could be because
    4360          * pages are pinned on the per-cpu lists or in high alloc reserves.
    4361          * Shrink them and try again
    4362          */
    4363         if (!page && !drained) {
    4364                 unreserve_highatomic_pageblock(ac, false);
    4365                 drain_all_pages(NULL);
    4366                 drained = true;
    4367                 goto retry;
    4368         }
    4369
    4370         return page;
    4371 }
    是时候好好总结下自己走过的路。
  • 相关阅读:
    AndroidStudio修改程序的包名,可以修改com.example.xxx之类的详解
    【Android】Android开发点击查看手机电量的小功能。学习广播的一个小技能小Demo
    linux系统工程师修改打开文件数限制代码教程。服务器运维技术
    修改linux操作系统的时间可以使用date指令 运维系统工程师必会技术
    MySQL常用指令,java,php程序员,数据库工程师必备。程序员小冰常用资料整理
    android开发之java代码中字符串对比忽略大小写。java程序员必回,可用来比对验证码等问题
    android开发之使edittext输入弹出数字软键盘。亲测可用。手机号登陆注册常用。
    java工具类去掉字符串String中的.点。android开发java程序员常用工具类
    JS——tab函数封装
    JS——样式类的添加
  • 原文地址:https://www.cnblogs.com/haoxing990/p/14495719.html
Copyright © 2020-2023  润新知