Skip to content

Latest commit

 

History

History
730 lines (625 loc) · 29.3 KB

a10c_81.md

File metadata and controls

730 lines (625 loc) · 29.3 KB

ARM10C 81주차 후기

일시 : 2014.12.06 (81주차)
모임명 : NAVER개발자커뮤니티지원_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 2명

============

81주차 진도

  • start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()

main.c::start_kernel()

asmlinkage void __init start_kernel(void)
{
...
	setup_arch(&command_line);
...
	mm_init();
	// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
	// pcpu 메모리, vmlist 는 slab으로 이관
...
	rcu_init();
	// rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
...
	/* init some links before init_ISA_irqs() */
	early_irq_init();
	// irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
	// allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가

	init_IRQ();
  • call: start_kernel()->init_IRQ()
  • init_IRQ();

irq.c::init_IRQ()

  • called: start_kernel()->init_IRQ()
  • init_IRQ();
// ARM10C 20141004
void __init init_IRQ(void)
{
	// CONFIG_OF=y, machine_desc->init_irq: __mach_desc_EXYNOS5_DT.init_irq: 0
	if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
		irqchip_init();
	else
		machine_desc->init_irq();
}
  • call: start_kernel()->init_IRQ()->irqchip_init()
  • irqchip_init();

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()
  • irqchip_init();
// ARM10C 20141004
extern struct of_device_id __irqchip_begin[];

// ARM10C 20141004
void __init irqchip_init(void)
{
	// exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
	// __irqchip_begin: irqchip_of_match_exynos4210_combiner
	of_irq_init(__irqchip_begin);
}
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
  • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
  • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
  • of_irq_init(__irqchip_begin);

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
  • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
  • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
  • of_irq_init(__irqchip_begin);
void __init of_irq_init(const struct of_device_id *matches)
{
	struct device_node *np, *parent = NULL;
	// parent: NULL
	struct intc_desc *desc, *temp_desc;
	struct list_head intc_desc_list, intc_parent_list;

	INIT_LIST_HEAD(&intc_desc_list);
	// intc_desc_list 리스트 초기화 수행

	INIT_LIST_HEAD(&intc_parent_list);
	// intc_parent_list 리스트 초기화 수행

	// matches: irqchip_of_match_exynos4210_combiner
	for_each_matching_node(np, matches) {
	// for (np = of_find_matching_node(NULL, matches); np; np = of_find_matching_node(np, matches))

		// np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
		// of_find_property(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, "interrupt-controller", NULL):
		// combiner node의 "interrupt-controller" property의 주소
		// np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
		// of_find_property(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, "interrupt-controller", NULL):
		// gic node의 "interrupt-controller" property의 주소
		if (!of_find_property(np, "interrupt-controller", NULL))
			continue;
		/*
		 * Here, we allocate and populate an intc_desc with the node
		 * pointer, interrupt-parent device_node etc.
		 */
		// sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
		// kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o10
		// sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
		// kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o11
		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
		// desc: kmem_cache#30-o10
		// desc: kmem_cache#30-o11

		// desc: kmem_cache#30-o10
		// desc: kmem_cache#30-o11
		if (WARN_ON(!desc))
			goto err;

		// desc->dev: (kmem_cache#30-o10)->dev, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
		// desc->dev: (kmem_cache#30-o11)->dev, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
		desc->dev = np;
		// desc->dev: (kmem_cache#30-o10)->dev: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
		// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

		// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
		// of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소): gic node 주소
		// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
		// of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소): gic node 주소
		desc->interrupt_parent = of_irq_find_parent(np);
		// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
		// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소

		// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
		// np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
		// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
		// np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
		if (desc->interrupt_parent == np)
			// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
			desc->interrupt_parent = NULL;
			// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL

		// &desc->list: &(kmem_cache#30-o10)->list
		// &desc->list: &(kmem_cache#30-o11)->list
		list_add_tail(&desc->list, &intc_desc_list);
		// intc_desc_list에 (kmem_cache#30-o10)->list를 tail에 추가
		// intc_desc_list에 (kmem_cache#30-o11)->list를 tail에 추가
	}

	// irqchip_of_match_exynos4210_combiner, irqchip_of_match_cortex_a15_gic 의
	// struct intc_desc 메모리 할당, intc_desc 맴버가 초기화 된 값이 intc_desc_list list의 tail로 추가됨

	// list_empty(&intc_desc_list): 0
	while (!list_empty(&intc_desc_list)) {
		list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
		// for (desc = list_first_entry(&intc_desc_list, typeof(*desc), list),
		// 	temp_desc = list_next_entry(desc, list);
		//      &desc->list != (&intc_desc_list);
		//      desc = temp_desc, temp_desc = list_next_entry(temp_desc, list))

			// desc: kmem_cache#30-o10 (exynos4210_combiner), temp_desc: kmem_cache#30-o11 (cortex_a15_gic)
			// desc: kmem_cache#30-o11 (cortex_a15_gic), temp_desc: NULL

			const struct of_device_id *match;
			int ret;
			of_irq_init_cb_t irq_init_cb;

			// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소, parent: NULL
			// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL, parent: NULL
			if (desc->interrupt_parent != parent)
				continue;
				// continue 수행 (exynos4210_combiner)

			// &desc->list: (kmem_cache#30-o11)->list
			list_del(&desc->list);
			// intc_desc_list에서 (kmem_cache#30-o11)->list를 삭제

			// matches: irqchip_of_match_cortex_a15_gic,
			// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
			// of_match_node(cortex_a15_gic, devtree에서 allnext로 순회 하면서 찾은 gic node의 주소):
			// irqchip_of_match_cortex_a15_gic
			match = of_match_node(matches, desc->dev);
			// match: irqchip_of_match_cortex_a15_gic

			// match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
			if (WARN(!match->data,
			    "of_irq_init: no init function for %s\n",
			    match->compatible)) {
				kfree(desc);
				continue;
			}

			// match->compatible: irqchip_of_match_cortex_a15_gic.compatible: "arm,cortex-a15-gic",
			// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
			// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
			pr_debug("of_irq_init: init %s @ %p, parent %p\n",
				 match->compatible,
				 desc->dev, desc->interrupt_parent);
			// "of_irq_init: init arm,cortex-a15-gic @ 0x(gic node의 주소), parent 0\n"

			// match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
			irq_init_cb = (of_irq_init_cb_t)match->data;
			// irq_init_cb: gic_of_init

			// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소,
			// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
			// gic_of_init(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, NULL):
			ret = irq_init_cb(desc->dev, desc->interrupt_parent);

			// ret: 0
			if (ret) {
				kfree(desc);
				continue;
			}
			/*
			 * This one is now set up; add it to the parent list so
			 * its children can get processed in a subsequent pass.
			 */
			// &desc->list: &(kmem_cache#30-o11)->list
			list_add_tail(&desc->list, &intc_parent_list);
			// intc_parent_list에 tail로 &(kmem_cache#30-o11)->list를 추가
		}
		// &desc->list: &intc_desc_list 이므로  loop 탈출

		/* Get the next pending parent that might have children */
		// typeof(*desc): struct intc_desc
		// list_first_entry_or_null(&intc_parent_list, struct intc_desc, list):
		// (!list_empty(&intc_parent_list) ? list_first_entry(&intc_parent_list, struct intc_desc, list) : NULL)
		// list_first_entry(&intc_parent_list, struct intc_desc, list): kmem_cache#30-o11 (cortex_a15_gic)
		desc = list_first_entry_or_null(&intc_parent_list,
						typeof(*desc), list);
		// desc: kmem_cache#30-o11 (cortex_a15_gic)

		// desc: kmem_cache#30-o11 (cortex_a15_gic)
		if (!desc) {
			pr_err("of_irq_init: children remain, but no parents\n");
			break;
		}

		// &desc->list: &(kmem_cache#30-o11 (cortex_a15_gic))->list
		list_del(&desc->list);
		// &(kmem_cache#30-o11 (cortex_a15_gic))->list에 연결된 list 삭제

		// parent: NULL
		// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
		parent = desc->dev;
		// parent: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

		// desc: kmem_cache#30-o11 (cortex_a15_gic)
		kfree(desc);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()
  • // desc: kmem_cache#30-o11 (cortex_a15_gic)
  • kfree(desc);

kmem.h::kfree()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()
  • // desc: kmem_cache#30-o11 (cortex_a15_gic)
  • kfree(desc);
// ARM10C 20141129
// _RET_IP_: __builtin_return_address(0), object: kmem_cache#30-o11
DEFINE_EVENT(kmem_free, kfree,

	TP_PROTO(unsigned long call_site, const void *ptr),

	TP_ARGS(call_site, ptr)
);
// ARM10C 20141129
// desc: kmem_cache#30-o11 (cortex_a15_gic)
void kfree(const void *x)
{
	struct page *page;

	// x: kmem_cache#30-o11
	void *object = (void *)x;
	// object: kmem_cache#30-o11

	// _RET_IP_: __builtin_return_address(0), object: kmem_cache#30-o11
	trace_kfree(_RET_IP_, x);

	// x: kmem_cache#30-o11, ZERO_OR_NULL_PTR(kmem_cache#30-o11): 0
	if (unlikely(ZERO_OR_NULL_PTR(x)))
		return;

	// x: kmem_cache#30-o11
	// virt_to_head_page(kmem_cache#30-o11): kmem_cache#30-o11의 page 주소
	page = virt_to_head_page(x);
	// page: kmem_cache#30-o11의 page 주소

	// page: kmem_cache#30-o11의 page 주소
	// PageSlab(kmem_cache#30-o11의 page 주소): 1
	if (unlikely(!PageSlab(page))) {
		BUG_ON(!PageCompound(page));
		kfree_hook(x);
		__free_memcg_kmem_pages(page, compound_order(page));
		return;
	}

	// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
	// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
	slab_free(page->slab_cache, page, object, _RET_IP_);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
  • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
  • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
  • slab_free(page->slab_cache, page, object, RET_IP);

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
  • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
  • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
  • slab_free(page->slab_cache, page, object, RET_IP);
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
			struct page *page, void *x, unsigned long addr)
{
	// x: kmem_cache#30-o11
	void **object = (void *)x;
	// object: kmem_cache#30-o11

	struct kmem_cache_cpu *c;
	unsigned long tid;

	// s: kmem_cache#30, x: kmem_cache#30-o11
	slab_free_hook(s, x);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->slab_free_hook()
  • // s: kmem_cache#30, x: kmem_cache#30-o11
  • slab_free_hook(s, x);

slub.c::slab_free_hook()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->slab_free_hook()
  • // s: kmem_cache#30, x: kmem_cache#30-o11
  • slab_free_hook(s, x);
// ARM10C 20141206
// s: kmem_cache#30, x: kmem_cache#30-o11
static inline void slab_free_hook(struct kmem_cache *s, void *x)
{
	// x: kmem_cache#30-o11, s->flags: (kmem_cache#30)->flags
	kmemleak_free_recursive(x, s->flags); // null function

	/*
	 * Trouble is that we may no longer disable interrupts in the fast path
	 * So in order to make the debug calls that expect irqs to be
	 * disabled we need to disable interrupts temporarily.
	 */
#if defined(CONFIG_KMEMCHECK) || defined(CONFIG_LOCKDEP) // CONFIG_KMEMCHECK=n, CONFIG_LOCKDEP=n
	{
		unsigned long flags;

		local_irq_save(flags);
		kmemcheck_slab_free(s, x, s->object_size);
		debug_check_no_locks_freed(x, s->object_size);
		local_irq_restore(flags);
	}
#endif
	// s->flags: (kmem_cache#30)->flags: 0, SLAB_DEBUG_OBJECTS: 0x00000000UL
	if (!(s->flags & SLAB_DEBUG_OBJECTS))
		// x: kmem_cache#30-o11, s->object_size: (kmem_cache#30)->object_size
		debug_check_no_obj_freed(x, s->object_size); // null function
}
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
  • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
  • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
  • slab_free(page->slab_cache, page, object, RET_IP);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
			struct page *page, void *x, unsigned long addr)
{
...
	// s: kmem_cache#30, x: kmem_cache#30-o11
	slab_free_hook(s, x);
redo:
	/*
	 * Determine the currently cpus per cpu slab.
	 * The cpu may change afterward. However that does not matter since
	 * data is retrieved via this pointer. If we are on the same cpu
	 * during the cmpxchg then the free will succedd.
	 */
	preempt_disable();
	// 선점 비활성화 수행

	// NOTE:
	// s->cpu_slab: (kmem_cache#30)->cpu_slab:
	// struct kmem_cache_cpu 자료구조를 사용하기 위해 할당받은 pcp 16 byte 메모리 공간

	// s->cpu_slab: (kmem_cache#30)->cpu_slab
	// __this_cpu_ptr((kmem_cache#30)->cpu_slab):
	// (kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋
	c = __this_cpu_ptr(s->cpu_slab);
	// c: (kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋

	// c->tid: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->tid
	tid = c->tid;
	// tid: XX (추적불가)

	preempt_enable();
	// 선점 활성화 수행

	// NOTE:
	// likely(page == c->page)는 likely로 싸여 있는 것으로 보아
	// page == c->page 가 같을 확율이 높다고 판단됨. page, c->page 값이 같다고 보고 코드 분석 진행

	// page: kmem_cache#30-o11의 page 주소,
	// c->page: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->page
	if (likely(page == c->page)) {
		// s: kmem_cache#30, object: kmem_cache#30-o11,
		// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
		set_freepointer(s, object, c->freelist);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->set_freepointer()
  • // s: kmem_cache#30, object: kmem_cache#30-o11,
  • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
  • set_freepointer(s, object, c->freelist);

slub.c::set_freepointer()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->set_freepointer()
  • // s: kmem_cache#30, object: kmem_cache#30-o11,
  • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
  • set_freepointer(s, object, c->freelist);
// ARM10C 20141206
// s: kmem_cache#30, object: kmem_cache#30-o11,
// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
{
	// object: UNMOVABLE인 page 의 virtual address
	// s->offset: (&boot_kmem_cache_node)->offset: 0
	// fp: UNMOVABLE인 page 의 virtual address
	// object: UNMOVABLE인 page 의 virtual address(boot_kmem_cache)
	// s->offset: (&boot_kmem_cache_node)->offset: 0
	// fp: UNMOVABLE인 page 의 virtual address(boot_kmem_cache)
	*(void **)(object + s->offset) = fp;
	// object: UNMOVABLE인 page 의 virtual address(boot_kmem_cache)
}
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
  • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
  • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
  • slab_free(page->slab_cache, page, object, RET_IP);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
			struct page *page, void *x, unsigned long addr)
{
...
	// s: kmem_cache#30, x: kmem_cache#30-o11
	slab_free_hook(s, x);
redo:
...
	// page: kmem_cache#30-o11의 page 주소,
	// c->page: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->page
	if (likely(page == c->page)) {
		// s: kmem_cache#30, object: kmem_cache#30-o11,
		// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
		set_freepointer(s, object, c->freelist);
		// kmem_cache#30-o11의 freepointer의 값을
		// ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅

		// s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
		// s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
		// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
		// tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
		// this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
		// ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
		// XX, kmem_cache#30-o11, XX): 1
		if (unlikely(!this_cpu_cmpxchg_double(
				s->cpu_slab->freelist, s->cpu_slab->tid,
				c->freelist, tid,
				object, next_tid(tid)))) {

			note_cmpxchg_failure("slab_free", s, tid);
			goto redo;
		}
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->this_cpu_cmpxchg_double()
  • // s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
  • // s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
  • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
  • // tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
  • // this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
  • // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
  • // XX, kmem_cache#30-o11, XX): 1
  • if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,c->freelist, tid,object, next_tid(tid))))

percpu.h::this_cpu_cmpxchg_double()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->this_cpu_cmpxchg_double()
  • // s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
  • // s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
  • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
  • // tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
  • // this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
  • // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
  • // XX, kmem_cache#30-o11, XX): 1
  • if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,c->freelist, tid,object, next_tid(tid))))
// ARM10C 20141206
// s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
// s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
// tid: XX (추적불가), object: kmem_cache#30-o11, next_tid(tid): XX
# define this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
	__pcpu_double_call_return_bool(this_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
#endif

percpu.h::__pcpu_double_call_return_bool()

#define __pcpu_double_call_return_bool(stem, pcp1, pcp2, ...)		\
({									\
	bool pdcrb_ret__;						\
	__verify_pcpu_ptr(&pcp1);					\
	BUILD_BUG_ON(sizeof(pcp1) != sizeof(pcp2));			\
	VM_BUG_ON((unsigned long)(&pcp1) % (2 * sizeof(pcp1)));		\
	VM_BUG_ON((unsigned long)(&pcp2) !=				\
		  (unsigned long)(&pcp1) + sizeof(pcp1));		\
	switch(sizeof(pcp1)) {						\
	case 1: pdcrb_ret__ = stem##1(pcp1, pcp2, __VA_ARGS__); break;	\
	case 2: pdcrb_ret__ = stem##2(pcp1, pcp2, __VA_ARGS__); break;	\
	case 4: pdcrb_ret__ = stem##4(pcp1, pcp2, __VA_ARGS__); break;	\
	case 8: pdcrb_ret__ = stem##8(pcp1, pcp2, __VA_ARGS__); break;	\
	default:							\
		__bad_size_call_parameter(); break;			\
	}								\
	pdcrb_ret__;							\
})
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
  • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
  • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
  • slab_free(page->slab_cache, page, object, RET_IP);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->this_cpu_cmpxchg_double()
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
			struct page *page, void *x, unsigned long addr)
{
...
	// s: kmem_cache#30, x: kmem_cache#30-o11
	slab_free_hook(s, x);
redo:
...
	// page: kmem_cache#30-o11의 page 주소,
	// c->page: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->page
	if (likely(page == c->page)) {
		// s: kmem_cache#30, object: kmem_cache#30-o11,
		// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
		set_freepointer(s, object, c->freelist);
		// kmem_cache#30-o11의 freepointer의 값을
		// ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅

		// s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
		// s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
		// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
		// tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
		// this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
		// ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
		// XX, kmem_cache#30-o11, XX): 1
		if (unlikely(!this_cpu_cmpxchg_double(
				s->cpu_slab->freelist, s->cpu_slab->tid,
				c->freelist, tid,
				object, next_tid(tid)))) {

			note_cmpxchg_failure("slab_free", s, tid);
			goto redo;
		}
		// this_cpu_cmpxchg_double에서 한일:
		// 값 s->cpu_slab->freelist와 c->freelist를 비교, 값 s->cpu_slab->tid와 tid을 비교 하여
		// 같을 경우에 s->cpu_slab->freelist와 s->cpu_slab->tid을 각각 object, next_tid(tid) 값으로 갱신하여
		// freelist와 tid 값을 변경함

		// s: kmem_cache#30, FREE_FASTPATH: 2
		stat(s, FREE_FASTPATH); // null function
	} else
		__slab_free(s, page, x, addr);

}
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()

kfree()에서 한일:

// (kmem_cache#30)->cpu_slab: struct kmem_cache_cpu 자료구조를 사용하기 위해 할당받은 pcp 16 byte 메모리 공간을 구하여 // kmem_cache#30-o11의 freepointer의 값을 // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅 // 값 s->cpu_slab->freelist와 c->freelist를 비교, 값 s->cpu_slab->tid와 tid을 비교 하여 // 같을 경우에 s->cpu_slab->freelist와 s->cpu_slab->tid을 각각 object, next_tid(tid) 값으로 갱신하여 // freelist와 tid 값을 변경함 // kmem_cache_cpu의 freelist, tid 의 값을 변경함

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
  • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
  • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
  • of_irq_init(__irqchip_begin);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()
void __init of_irq_init(const struct of_device_id *matches)
{
...
	// list_empty(&intc_desc_list): 0
	while (!list_empty(&intc_desc_list)) {
		list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
		// for (desc = list_first_entry(&intc_desc_list, typeof(*desc), list),
		// 	temp_desc = list_next_entry(desc, list);
		//      &desc->list != (&intc_desc_list);
		//      desc = temp_desc, temp_desc = list_next_entry(temp_desc, list))

...
		// desc: kmem_cache#30-o11 (cortex_a15_gic)
		kfree(desc);
	}

	list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
		list_del(&desc->list);
		kfree(desc);
	}
err:
	list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
		list_del(&desc->list);
		kfree(desc);
	}
}

log

  • 1st log
   691ad42..e884ca4  master     -> origin/master
Updating 691ad42..e884ca4
Fast-forward
arch/arm/include/asm/bitops.h     |   2 +
arch/arm/include/asm/io.h         |   2 +
arch/arm/mm/ioremap.c             | 110 +++++++++++++++++-
drivers/irqchip/exynos-combiner.c |  42 ++++++-
drivers/of/address.c              |  16 +++
drivers/of/base.c                 |  13 +++
drivers/of/irq.c                  |  79 +++++++++----
include/asm-generic/percpu.h      |   1 +
include/linux/debugobjects.h      |   3 +-
include/linux/gfp.h               |   2 +
include/linux/irqdomain.h         |   1 +
include/linux/kernel.h            |   1 +
include/linux/kmemleak.h          |   1 +
include/linux/list.h              |   9 +-
include/linux/of.h                |   4 +
include/linux/percpu.h            |   5 +
include/linux/preempt.h           |   2 +
include/linux/rbtree.h            |  17 +--
include/linux/rculist.h           |   2 +
include/linux/slab.h              |  44 ++++++++
include/linux/slub_def.h          |   3 +
kernel/irq/irqdomain.c            |  64 +++++++++++
lib/ioremap.c                     |   3 +
lib/rbtree.c                      |  12 +-
mm/slab_common.c                  |   9 ++
mm/slub.c                         |  91 ++++++++++++++-
mm/vmalloc.c                      | 230 ++++++++++++++++++++++++++++++++++++--
27 files changed, 713 insertions(+), 55 deletions(-)
  • 2nd log
   e884ca4..2ed370b  master     -> origin/master
Updating e884ca4..2ed370b
Fast-forward
drivers/irqchip/exynos-combiner.c |  64 ++++++++++++++++++++++++++++++++++++--
drivers/of/base.c                 |   4 +--
drivers/of/irq.c                  | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------------------------------------
3 files changed, 185 insertions(+), 116 deletions(-)