Linux 内存管理(2) memblock的黄金时代

1. memblock_alloc分配内存

memblock数据结构初始化结束,memblock_alloc是内核分配内存的主要工具。memblock_alloc的这种核心地位将持续到buddy system的建立。


 793 phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 794 {
 795         return memblock_alloc_base_nid(size, align, max_addr, MAX_NUMNODES);
 796 }
 797
 798 phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 799 {
 800         phys_addr_t alloc;
 801
 802         alloc = __memblock_alloc_base(size, align, max_addr);
 803
 804         if (alloc == 0)
 805                 panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
 806                       (unsigned long long) size, (unsigned long long) max_addr);
 807
 808         return alloc;
 809 }
 810
 811 phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
 812 {
 813         return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 814 }

 769 static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
 770                                         phys_addr_t align, phys_addr_t max_addr,
 771                                         int nid)
 772 {
 773         phys_addr_t found;
 774
 775         if (WARN_ON(!align))
 776                 align = __alignof__(long long);
 777
 778         /* align @size to avoid excessive fragmentation on reserved array */
 779         size = round_up(size, align);
 780
 781         found = memblock_find_in_range_node(0, max_addr, size, align, nid);
 782         if (found && !memblock_reserve(found, size))
 783                 return found;
 784
 785         return 0;
 786 }

  98 phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
  99                                         phys_addr_t end, phys_addr_t size,
 100                                         phys_addr_t align, int nid)
 101 {
 102         phys_addr_t this_start, this_end, cand;
 103         u64 i;
 104
 105         /* pump up @end */
 106         if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
 107                 end = memblock.current_limit;
 108
 109         /* avoid allocating the first page */
 110         start = max_t(phys_addr_t, start, PAGE_SIZE);
 111         end = max(start, end);
 112
 113         for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
 114                 this_start = clamp(this_start, start, end);
 115                 this_end = clamp(this_end, start, end);
 116
 117                 if (this_end < size)
 118                         continue;
 119
 120                 cand = round_down(this_end - size, align);
 121                 if (cand >= this_start)
 122                         return cand;
 123         }
 124         return 0;
 125 }


#define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid)  \
        for (i = (u64)ULLONG_MAX,                                       \
             __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \
             i != (u64)ULLONG_MAX;                                      \
             __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))


 652 void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
 653                                            phys_addr_t *out_start,
 654                                            phys_addr_t *out_end, int *out_nid)
 655 {
 656         struct memblock_type *mem = &memblock.memory;
 657         struct memblock_type *rsv = &memblock.reserved;
 658         int mi = *idx & 0xffffffff;
 659         int ri = *idx >> 32;
 660
 661         if (*idx == (u64)ULLONG_MAX) {
 662                 mi = mem->cnt - 1;
 663                 ri = rsv->cnt;
 664         }
 665
 666         for ( ; mi >= 0; mi--) {
 667                 struct memblock_region *m = &mem->regions[mi];
 668                 phys_addr_t m_start = m->base;
 669                 phys_addr_t m_end = m->base + m->size;
 670
 671                 /* only memory regions are associated with nodes, check it */
 672                 if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m))
 673                         continue;
 674
 675                 /* scan areas before each reservation for intersection */
 676                 for ( ; ri >= 0; ri--) {
 677                         struct memblock_region *r = &rsv->regions[ri];
 678                         phys_addr_t r_start = ri ? r[-1].base + r[-1].size : 0;
 679                         phys_addr_t r_end = ri < rsv->cnt ? r->base : ULLONG_MAX;
 680
 681                         /* if ri advanced past mi, break out to advance mi */
 682                         if (r_end <= m_start)
 683                                 break;
 684                         /* if the two regions intersect, we're done */
 685                         if (m_end > r_start) {
 686                                 if (out_start)
 687                                         *out_start = max(m_start, r_start);
 688                                 if (out_end)
 689                                         *out_end = min(m_end, r_end);
 690                                 if (out_nid)
 691                                         *out_nid = memblock_get_region_node(m);

 692
 693                                 if (m_start >= r_start)
 694                                         mi--;
 695                                 else
 696                                         ri--;
 697                                 *idx = (u32)mi | (u64)ri << 32;
 698                                 return;
 699                         }
 700                 }
 701         }
 702
 703         *idx = ULLONG_MAX;
 704 }



以上为memblock查找内存空间的过程,通过memblock_reserve标志内存已经使用。


2 memblock_reserve

554 int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
 555 {
 556         struct memblock_type *_rgn = &memblock.reserved;
 557
 558         memblock_dbg("memblock_reserve: [%#016llx-%#016llx] %pF\n",
 559                      (unsigned long long)base,
 560                      (unsigned long long)base + size,
 561                      (void *)_RET_IP_);
 562
 563         return memblock_add_region(_rgn, base, size, MAX_NUMNODES);
 564 }
 565

把一段内存放入memblock.reserved内。

563行,在上一文章内有提及。

3. memblock_free

memblock_free比较简单,这里就不再摘录了。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值