Skip to content

Latest commit

 

History

History
245 lines (208 loc) · 7.86 KB

a10c_55.md

File metadata and controls

245 lines (208 loc) · 7.86 KB

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(-)