2014년 5월 27일 화요일

[Linux Kernel] 55주차(2014.05.24) 후기

ARM10C 55주차 후기

일시 : 2014.05.24 (55주차)

모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C

장소 : 토즈 타워점

장소지원 : NAVER 개발자 커뮤니티 지원 프로그램

참여인원 : 5명

스터디 진도 :

  • 지난 스터디에 이어서 mem_init()을 계속 분석합니다.
  • start_kernel()-> mm_init()->kmem_cache_init()->create_boot_cache() 분석중
  • kmem_cache_init()이 분석 중이어서 이번 후기는 내용이 짧습니다.
    • 내용이 복잡해서 slub()이 끝나는 시점에서 내용 정리를 함께 다시 하기로 했습니다.
    • 자세한 후기도 그때 다시 정리하려고 합니다.

스터디 주요 내용

  • __mod_zone_page_state()가 여러번 반복 호출 되는데, 이 중요한 함수를 복습하자.

buffered_rmqueue()

  • __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order));
  • __count_zone_vm_events(PGALLOC, zone, 1 << order);
    //
  • zone_statistics(preferred_zone, zone, gfp_flags);
    // NULL function
  • local_irq_restore(flags);
    // cpsr 복원
  • VM_BUG_ON(bad_range(zone, page));
    // return 0; VM_BUG_ON : 부정되어 패스
  • if (prep_new_page(page, order, gfp_flags))
    • prep_new_page(page, order, gfp_flags)
      // page migratetype이 MIGRATE_UNMOVABLE인 page, order:0, gfp_flags: 0x221200
static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
{
    int i;

    for (i = 0; i < (1 << order); i++) {
        struct page *p = page + i;
        if (unlikely(check_new_page(p)))
            return 1;
    }

    set_page_private(page, 0);
    set_page_refcounted(page);

    arch_alloc_page(page, order);
    kernel_map_pages(page, 1 << order, 1);

    if (gfp_flags & __GFP_ZERO)
        prep_zero_page(page, order, gfp_flags);

    if (order && (gfp_flags & __GFP_COMP))
        prep_compound_page(page, order);

    return 0;
}

if (unlikely(check_new_page(p)))

static inline int check_new_page(struct page *page)
{
    if (unlikely(page_mapcount(page) |
        (page->mapping != NULL)  |
        (atomic_read(&page->_count) != 0)  |
        (page->flags & PAGE_FLAGS_CHECK_AT_PREP) |
        (mem_cgroup_bad_page_check(page)))) {
        bad_page(page);
        // page->mapping != NULL :
        // atomic_read(&page->_count) != 0
        // page->flags & PAGE_FLAGS_CHECK_AT_PREP :
        // mem_cgroup_bad_page_check : FALSE
        return 1;
    }
    return 0;
}
  • // page->mapping != NULL :
    • _mapcount : to show when pag is mapped & limit reverse map searches
      • -127 초기화는
      • -1 사용하려고 할당받았지만, 참조는 되지 않음 (-1) : 0xffff ffff, 1111 …. 1111
    • mapping
  • // atomic_read(&page->_count) != 0
    • __free_pages_bootmem()->set_page_count(p,0);
    • free_pages->put_pagetestzero(page)
      // page->count: 0
      이값은 buddy초기화(
      free_pages()에서 0으로 초기화를 했다.
  • // page->flags & PAGE_FLAGS_CHECK_AT_PREP :
  • // mem_cgroup_bad_page_check : FALSE
    • check_new_page()
  • 이 의미가 bad pages가 되지 조건이다.
    // page->_mapcount : - 1 사용하기 위해 할당받았지만 참조되어 사용하지는 않음
    // page->mapping 할당 받았으면 NULL로 디, 사용중인 page는 vam, inode등의 address apace로 매핑된다.
    // page->_count :

set_page_private(page, 0);

  • page : migragtetype이 MIGRATE_UNMOVEABLE인 page
  • page->private: 0
  • 왜 private : order값을 0으로 했을까? FIX me!

set_page_refcounted(page);

  • page->_count를 1로 set

arch_alloc_page(page, order);

  • null function

kernel_map_pages(page, 1 << order, 1);

  • null function

if (gfp_flags & __GFP_ZERO) prep_zero_page(page, order, gfp_flags);

  • gfp_flags : 0x221200
  • __GFP_ZERO : 0x 8000
  • gfp_flags & __GFP_ZERO : 0

if (order && (gfp_flags & __GFP_COMP)) prep_compound_page(page, order);

  • order : 0

return 0;

  • 이것으로 get_page_from_freelist() 함수의
    this_zone_full: 의 조건인 함수의
    if(page) break;를 통해서 loop를 빠져 나옴.get_page_from_freelist()
  • alloc_pages_nodemask()->
    page = get_page_from_freelist(gfp_mask|
    GFP_HARDWALL, nodemask, order,
          zonelist, high_zoneidx, alloc_flags,
          preferred_zone, migratetype);
    

__alloc_pages_nodemask()

  • if (unlikely(!page)) // false
  • out : if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) goto retry_cpuset;
    // cpuset_mems_cookie : 0
  • put_mems_allowed(0) // true
  • memcg_kmem_commit_charge(page, memcg, order);
    // * page : migragtetype이 MIGRATE_UNMOVEABLE인 page , memcg : null , order : 0
    // memcg_kme_commit_charge () // null function
  • return * page
    // migragtetype이 MIGRATE_UNMOVEABLE인 page로 할당 받음

    alloc_pages_exact_node()

    // return * page : migragtetype이 MIGRATE_UNMOVEABLE인 page

alloc_slab_page()

// return * page : migragtetype이 MIGRATE_UNMOVEABLE인 page

allocate_slab()

page = alloc_slab_page(alloc_gfp, node, oo);
// return * page : migragtetype이 MIGRATE_UNMOVEABLE인 page
if (unlikely(!page))
// faluse
if (kmemcheck_enabled && page && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS)))
// kmemcheck_enabled: 0, page: migratetype이 MIGRAT_UNMOVEABLE으로 할당 받은 page
// s->flags : SLAB_HWCACHE_ALIGN : 0x00002000
// SLAB_NOTRACK : 0x000000000UL
// #define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \
SLAB_POISON | SLAB_STORE_USER)
// SLAB_DEBUG_FREE 0x00000100UL
// SLAB_RED_ZONE 0x00000400UL
// SLAB_POISON 0x00000800UL
// SLAB_STORE_USER 0x00010000UL
// 0x00010d00 : 0x00000100UL | 0x00000400UL | 0x00000800UL | 0x00010000UL
if (flags & __GFP_WAIT)
local_irq_disable();
// (flags : 0 & GRP_WAIT : 0x10 ) : false
if (!page)
return NULL;
page->objects = oo_objects(oo);
// oo: boot_mem_cache_node.oo
// oo_objects(oo) : 64
// page->objects : 64
// page-> union struct { //slub :
inuse : 16;
object : 15;
frozen : 1;
// page->_mapcount : 0x0040 00000
  • object의 의미는 무엇일까?
    4k안에 64짜리 object가 64개 있다.
mod_zone_page_state(page_zone(page),
(s->flags & SLAB_RECLAIM_ACCOUNT) ?
NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
1 << oo_order(oo));
// page_zone(page) : &(&contig_page_data)->node_zones[ZONE_NORMAL]
// s->flags : (&boot_kmem_cache_node)->flags: SLAB_HWCACHE_ALIGN: 0x00002000
// NR_SLAB_RECLIMABLE : 13, NR_SLAB_UNRECLAIMABLE : 14
// oo_order(boot_kmem_cache_node.oo) : 0
// 따라서 &(&contig_page_data)->node_zones[ZONE_NORMAL],NR_SLAB_UNRECLAIMABLE : 14, 0
// __mod_zone_page_state()를 호출
// zone->vm_stat[14] : (&contig_page_data)->node_zones[ZONE_NORMAL].vm_stat[14]:1
// NR_SLAB_UNRECLAIMABLE : 14, vm_stat[14]:1

new_slab()

order = compound_order(page);
// page->flags
// compound가 접착이라는 의미이므로 page가 붙여서 할당 받았는지 여부를 나타내는 것으로 추정된다.
// 우리는 작은 것을 받았으므로 0일것이다. 하지만 의미는 분명하게 확인해 보자.
// free_pages_check에서 버디를 활성화하기 전에 모두 0으로 초기화 하고 왔다.
// page->flags의 NR_PAGEFLAGS 만큼의 하위 비트를 전부 지워줌.
static inline int compound_order(struct page *page)
{
    // PageHead(page): 0
    if (!PageHead(page))
        return 0;
    return (unsigned long)page[1].lru.prev;
}

git log

Updating d9a9639..f3708db
Fast-forward
include/linux/cpuset.h | 1 +
include/linux/gfp.h | 12 +
include/linux/kmemcheck.h | 1 +
include/linux/memcontrol.h | 2 
include/linux/mm.h | 3 +

include/linux/mmzone.h | 2 
include/linux/page-flags.h | 1 +
include/linux/slab.h | 8 +++
-
include/linux/vmstat.h | 15 ++-
include/trace/events/kmem.h | 1 +
mm/bootmem.c | 2 
mm/internal.h | 3 +

mm/page_alloc.c | 77 ++———
mm/slub.c | 40 +++
mm/vmstat.c | 64 +++—————-
15 files changed, 205 insertions(+), 27 deletions(-)

댓글 없음:

댓글 쓰기