Skip to content

Latest commit

 

History

History
772 lines (655 loc) · 27.6 KB

File metadata and controls

772 lines (655 loc) · 27.6 KB

ARM10C 70주차 후기

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

스터디 진도 :

  • sched_init()

main.c::start_kernel()

  • sched_init()을 분석합니다.
  • start_kernel()부터 sched_init() 전에 어떤 일을 했는지 간추려서 보겠습니다.
asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern const struct kernel_param __start___param[], __stop___param[];

...
	local_irq_disable();
	// IRQ를 disable한다.
	early_boot_irqs_disabled = true;

	boot_cpu_init()
	// 현재 cpu(core id)를 얻어서 cpu_XXX_bits[] 의 cpu를 셋한다.
	
	page_address_init();
	// 128개의 page_address_htable 배열을 초기화
	
	pr_notice("%s", linux_banner);
	// 배너:
	//	Linux version 2.6.37_DM385_IPNC_3.50.00
	// 	(a0875405@bangvideoapps01) (gcc version 4.5.3 20110311 
	// 	(prerelease) (GCC) ) #1 Fri Dec 21 17:27:08 IST 2012

    setup_arch(&command_line);
	// ARM 아키텍쳐에 맞게 초기화한다.

	setup_nr_cpu_ids();
	setup_per_cpu_areas();
	// pcpu 구조체를 만들어 줌 (mm/percpu.c)

	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
	// boot cpu 0의 pcpu 영역의 base주소를 core register에 설정해줌

...
	pidhash_init();
	// pidhash의 크기를 16kB만큼 할당 받고 4096개의 hash list를 만듬

	vfs_caches_init_early();
	// Dentry cache, Inode-cache용 hash를 위한 메모리 공간을 각각 512kB, 256kB만큼 할당 받고,
	// 131072, 65536개 만큼 hash table을 각각 만듬

...
	mm_init();
	// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
	// pcpu 메모리, vmlist 는 slab으로 이관

	sched_init();

mm_init()에서 buddy와 slab을 활성화하고 sched_init()을 실행한다.

core.c::sched_init()

  • CONFIG_xxx에 따라서 Sched는 분기한다.
  • CONFIG_FAIR_GROUP_SCHED
  • CONFIG_RT_GROUP_SCHED
  • CONFIG_CPUMASK_OFFSTACK
  • init_defrootdomain();
  • // def_root_domain의 맴버 값을 초기화 수행
  • // (&(&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 101])->count: 0
  • // (&(&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 101])->mask.bit[0]: 0
  • // (&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 3]: -1
  • // &def_root_domain.refcount: 1
  • init_rt_bandwidth(&def_rt_bandwidth, global_rt_period(), global_rt_runtime());
  • // init_rt_bandwidth에서 한일:
  • // (&def_rt_bandwidth)->rt_period: 1000000000
  • // (&def_rt_bandwidth)->rt_runtime: 950000000
  • // &(&def_rt_bandwidth)->rt_runtime_lock을 사용한 spinlock 초기화
  • // (&def_rt_bandwidth)->rt_period_timer의 값을 0으로 초기화
  • // &(&def_rt_bandwidth)->rt_period_timer)->base: &hrtimer_bases->clock_base[0]
  • // (&(&(&def_rt_bandwidth)->rt_period_timer)->node)->node의 RB Tree의 초기화
  • // &(&def_rt_bandwidth)->rt_period_timer.function: sched_rt_period_timer
  • for_each_possible_cpu(i) {
  • raw_spin_lock_init(&rq->lock);
    • // [pcp0] &rq->lock: &(&runqueues)->lock 을 사용한 spinlock 초기화 수행
  • // [pcp0] rq->nr_running: (&runqueues)->nr_running: 0
  • // [pcp0] rq->calc_load_active: (&runqueues)->calc_load_active: 0
  • // [pcp0] rq->calc_load_update: (&runqueues)->calc_load_update: -29499 (0xFFFFFFFFFFFF8CC5)
  • init_cfs_rq(&rq->cfs);
    • // init_cfs_rq 에서 한일:
    • // (&(&runqueues)->cfs)->tasks_timeline: (struct rb_root) { NULL, }
    • // (&(&runqueues)->cfs)->min_vruntime: 0xFFFFFFFFFFF00000
    • // (&(&runqueues)->cfs)->min_vruntime_copy: 0xFFFFFFFFFFF00000
    • // (&(&runqueues)->cfs)->decay_counter: 1
    • // (&(&runqueues)->cfs)->removed_load: 0
  • init_rt_rq(&rq->rt, rq);
    • // init_rt_rq 에서 한일:
    • // (&(&(&runqueues)->rt)->active)->bitmap의 0 ... 99 bit를 클리어
    • // (&(&(&runqueues)->rt)->active)->queue[0 ... 99] 의 리스트 초기화
    • // (&(&(&runqueues)->rt)->active)->bitmap의 100 bit를 1로 세팅
    • // (&(&runqueues)->rt)->rt_runtime_lock 을 사용한 spinlock 초기화
    • // (&(&runqueues)->rt)->rt_runtime: 0
    • // (&(&runqueues)->rt)->rt_throttled: 0
    • // (&(&runqueues)->rt)->rt_time: 0
    • // (&(&(&runqueues)->rt)->pushable_tasks)->node_list 리스트 초기화
    • // (&(&runqueues)->rt)->overloaded: 0
    • // (&(&runqueues)->rt)->rt_nr_migratory: 0
    • // (&(&runqueues)->rt)->highest_prio.next: 100
    • // (&(&runqueues)->rt)->highest_prio.curr: 100
  • // [pcp0] rq->rt.rt_runtime: (&runqueues)->rt.rt_runtime: 950000000
  • // [pcp0] j: 0, rq->cpu_load[0]: (&runqueues)->cpu_load[0]: 0, 1, 2, 3 실행
  • // [pcp0] rq->last_load_update_tick: (&runqueues)->last_load_update_tick: -30000 (0xFFFFFFFFFFFF8AD0)
  • // [pcp0] rq->sd: (&runqueues)->sd: NULL
  • // [pcp0] rq->rd: (&runqueues)->rd: NULL
  • // [pcp0] rq->cpu_power: (&runqueues)->cpu_power: 0x400
  • // [pcp0] rq->post_schedule: (&runqueues)->post_schedule: 0
  • // [pcp0] rq->active_balance: (&runqueues)->active_balance: 0
  • // [pcp0] rq->next_balance: (&runqueues)->next_balance: -30000 (0xFFFFFFFFFFFF8AD0)
  • // [pcp0] rq->push_cpu: (&runqueues)->push_cpu: 0
  • // [pcp0] rq->cpu: (&runqueues)->cpu: 0
  • // [pcp0] rq->online: (&runqueues)->online: 0
  • // [pcp0] rq->idle_stamp: (&runqueues)->idle_stamp: 0
  • // [pcp0] rq->avg_idle: (&runqueues)->avg_idle: 1000000UL
  • // [pcp0] rq->max_idle_balance_cost: (&runqueues)->max_idle_balance_cost: 500000UL
  • INIT_LIST_HEAD(&rq->cfs_tasks);
    • // [pcp0] &rq->cfs_tasks: &(&runqueues)->cfs_tasks 의 list 초기화 수행
  • rq_attach_root(rq, &def_root_domain);
    • // rq_attach_root에서 한일:
    • // (&def_root_domain)->span: 1
    • // (&runqueues)->rd: &def_root_domain
    • // &(&runqueues)->refcount: 1
  • // [pcp0] rq->nohz_flags: (&runqueues)->nohz_flags: 0
  • init_rq_hrtick(rq);
    • // init_rq_hrtick에서 한일:
    • // (&runqueues)->hrtick_csd_pending: 0
    • // (&runqueues)->hrtick_csd.flags: 0
    • // (&runqueues)->hrtick_csd.func: __hrtick_start
    • // (&runqueues)->hrtick_csd.info: &runqueues
    • // (&runqueues)->hrtick_timer의 값을 0으로 초기화
    • // (&(&runqueues)->hrtick_timer)->base: &hrtimer_bases->clock_base[0]
    • // RB Tree의 (&(&(&runqueues)->hrtick_timer)->node)->node 를 초기화
    • // &rq->hrtick_timer.function: &(&runqueues)->hrtick_timerhrtick_timer.function: hrtick
  • // [pcp0] &rq->nr_iowait: &(&runqueues)->nr_iowait: 0
  • set_load_weight(&init_task);
  • // set_load_weight에서 한일:
  • // (&(&init_task)->se.load)->weight: 1024
  • // (&(&init_task)->se.load)->inv_weight: 4194304
  • plist_head_init(&init_task.pi_waiters);
  • // plist_head_init에서 한일:
  • // (&init_task.pi_waiters)->node_list 리스트 초기화
  • atomic_inc(&init_mm.mm_count);
  • // init_mm.mm_count: 2
  • init_idle(current, smp_processor_id());
  • // init_idle에서 한일:
  • // (&init_task)->on_rq: 0
  • // (&init_task)->se.on_rq: 0
  • // (&init_task)->se.exec_start: 0
  • // (&init_task)->se.sum_exec_runtime: 0
  • // (&init_task)->se.prev_sum_exec_runtime: 0
  • // (&init_task)->se.nr_migrations: 0
  • // (&init_task)->se.vruntime: 0
  • // &(&init_task)->se.group_node의 리스트 초기화
  • // &(&init_task)->rt.run_list의 리스트 초기화
  • // (&init_task)->state: TASK_RUNNING: 0
  • // (&init_task)->se.exec_start: 0
  • // (&init_task)->cpus_allowed->bits[0]: 1
  • // (&init_task)->nr_cpus_allowed: 1
  • // ((struct thread_info *)(&init_task)->stack)->cpu: 0
  • // (&init_task)->wake_cpu: 0
  • // [pcpu0] (&runqueues)->curr: &init_task
  • // [pcpu0] (&runqueues)->idle: &init_task
  • // (&init_task)->on_cpu: 1
  • // ((struct thread_info *)(&init_task)->stack)->preempt_count: PREEMPT_ENABLED: 0
  • // (&init_task)->sched_class: &idle_sched_class
  • // (&init_task)->comm: "swapper/0"
  • calc_load_update = jiffies + LOAD_FREQ;
  • // calc_load_update: -29499 (0xFFFFFFFFFFFF8cc5)
  • // current->sched_class: (&init_task)->sched_class: &fair_sched_class

  • zalloc_cpumask_var(&sched_domains_tmpmask, GFP_NOWAIT);

  • // sched_domains_tmpmask.bits[0]: 0
  • zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
  • // cpu_isolated_map.bits[0]: 0
  • idle_thread_set_boot_cpu();
  • // [pcp0] idle_threads: &init_task
  • init_sched_fair_class();
  • // init_sched_fair_class가 한일:
  • // softirq_vec[7].action: run_rebalance_domains
  • // nohz.next_balance: -30000 (0xFFFFFFFFFFFF8AD0)
  • // nohz.idle_cpus_mask.bits[0]: 0
  • // (&cpu_chain)->head: sched_ilb_notifier_nb 포인터 대입
  • // (&sched_ilb_notifier_nb)->next은 (&slab_notifier)->next로 대입
  • // scheduler_running: 1
// ARM10C 20140830
void __init sched_init(void)
{
	int i, j;
	unsigned long alloc_size = 0, ptr;
	// alloc_size: 0

#ifdef CONFIG_FAIR_GROUP_SCHED // CONFIG_FAIR_GROUP_SCHED=n
	alloc_size += 2 * nr_cpu_ids * sizeof(void **);
#endif
#ifdef CONFIG_RT_GROUP_SCHED // CONFIG_RT_GROUP_SCHED=n
	alloc_size += 2 * nr_cpu_ids * sizeof(void **);
#endif
#ifdef CONFIG_CPUMASK_OFFSTACK // CONFIG_CPUMASK_OFFSTACK=n
	alloc_size += num_possible_cpus() * cpumask_size();
#endif
	// alloc_size: 0
	if (alloc_size) {
		ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT);

#ifdef CONFIG_FAIR_GROUP_SCHED // CONFIG_FAIR_GROUP_SCHED=n
		root_task_group.se = (struct sched_entity **)ptr;
		ptr += nr_cpu_ids * sizeof(void **);

		root_task_group.cfs_rq = (struct cfs_rq **)ptr;
		ptr += nr_cpu_ids * sizeof(void **);

#endif /* CONFIG_FAIR_GROUP_SCHED */
#ifdef CONFIG_RT_GROUP_SCHED // CONFIG_RT_GROUP_SCHED=n
		root_task_group.rt_se = (struct sched_rt_entity **)ptr;
		ptr += nr_cpu_ids * sizeof(void **);

		root_task_group.rt_rq = (struct rt_rq **)ptr;
		ptr += nr_cpu_ids * sizeof(void **);

#endif /* CONFIG_RT_GROUP_SCHED */
#ifdef CONFIG_CPUMASK_OFFSTACK // CONFIG_CPUMASK_OFFSTACK=n
		for_each_possible_cpu(i) {
			per_cpu(load_balance_mask, i) = (void *)ptr;
			ptr += cpumask_size();
		}
#endif /* CONFIG_CPUMASK_OFFSTACK */
	}

#ifdef CONFIG_SMP // CONFIG_SMP=y
	init_defrootdomain();
	// def_root_domain의 맴버 값을 초기화 수행
	// (&(&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 101])->count: 0
	// (&(&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 101])->mask.bit[0]: 0
	// (&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 3]: -1
	// &def_root_domain.refcount: 1
#endif

	// global_rt_period(): 1000000000, global_rt_runtime(): 950000000
	init_rt_bandwidth(&def_rt_bandwidth,
			global_rt_period(), global_rt_runtime());
	// init_rt_bandwidth에서 한일:
	// (&def_rt_bandwidth)->rt_period: 1000000000
	// (&def_rt_bandwidth)->rt_runtime: 950000000
	// &(&def_rt_bandwidth)->rt_runtime_lock을 사용한 spinlock 초기화
	// (&def_rt_bandwidth)->rt_period_timer의 값을 0으로 초기화
	// &(&def_rt_bandwidth)->rt_period_timer)->base: &hrtimer_bases->clock_base[0]
	// (&(&(&def_rt_bandwidth)->rt_period_timer)->node)->node의 RB Tree의 초기화
	// &(&def_rt_bandwidth)->rt_period_timer.function: sched_rt_period_timer

#ifdef CONFIG_RT_GROUP_SCHED // CONFIG_RT_GROUP_SCHED=n
	init_rt_bandwidth(&root_task_group.rt_bandwidth,
			global_rt_period(), global_rt_runtime());
#endif /* CONFIG_RT_GROUP_SCHED */

#ifdef CONFIG_CGROUP_SCHED // CONFIG_CGROUP_SCHED=n
	list_add(&root_task_group.list, &task_groups);
	INIT_LIST_HEAD(&root_task_group.children);
	INIT_LIST_HEAD(&root_task_group.siblings);
	autogroup_init(&init_task);

#endif /* CONFIG_CGROUP_SCHED */

	for_each_possible_cpu(i) {
	// for ((i) = -1; (i) = cpumask_next((i), (cpu_possible_mask)), (i) < nr_cpu_ids; )
		struct rq *rq;

		// i: 0
		// cpu_rq(0):
		// &({
		//  	do {
		// 	 	const void __percpu *__vpp_verify = (typeof(&(runqueues)))NULL;
		// 	 	(void)__vpp_verify;
		//  	} while (0)
		//  	(&(runqueues) + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋);
		// })
		rq = cpu_rq(i);
		// rq: (&(runqueues) + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)

		// NOTE:
		// rq: (&(runqueues) + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)
		// 의 주석을 간결하게 하기 위해 [pcp0] 를 변수 앞에 추가하고 rq: (&runqueue) 로 사용함

		// [pcp0] &rq->lock: &(&runqueues)->lock
		raw_spin_lock_init(&rq->lock);
		// [pcp0] &rq->lock: &(&runqueues)->lock 을 사용한 spinlock 초기화 수행

		// [pcp0] rq->nr_running: (&runqueues)->nr_running
		rq->nr_running = 0;
		// [pcp0] rq->nr_running: (&runqueues)->nr_running: 0

		// [pcp0] rq->calc_load_active: (&runqueues)->calc_load_active
		rq->calc_load_active = 0;
		// [pcp0] rq->calc_load_active: (&runqueues)->calc_load_active: 0

		// [pcp0] rq->calc_load_update: (&runqueues)->calc_load_update,
		// jiffies: -30000 (0xFFFFFFFFFFFF8AD0): vmlinux.lds.S 에 있음, LOAD_FREQ: 501
		rq->calc_load_update = jiffies + LOAD_FREQ;
		// [pcp0] rq->calc_load_update: (&runqueues)->calc_load_update: -29499 (0xFFFFFFFFFFFF8CC5)

		// [pcp0] &rq->cfs: &(&runqueues)->cfs
		init_cfs_rq(&rq->cfs);
		// init_cfs_rq 에서 한일:
		// (&(&runqueues)->cfs)->tasks_timeline: (struct rb_root) { NULL, }
		// (&(&runqueues)->cfs)->min_vruntime: 0xFFFFFFFFFFF00000
		// (&(&runqueues)->cfs)->min_vruntime_copy: 0xFFFFFFFFFFF00000
		// (&(&runqueues)->cfs)->decay_counter: 1
		// (&(&runqueues)->cfs)->removed_load: 0

		// [pcp0] &rq->rt: &(&runqueues)->rt, rq: (&runqueues)
		init_rt_rq(&rq->rt, rq);
		// init_rt_rq 에서 한일:
		// (&(&(&runqueues)->rt)->active)->bitmap의 0 ... 99 bit를 클리어
		// (&(&(&runqueues)->rt)->active)->queue[0 ... 99] 의 리스트 초기화
		// (&(&(&runqueues)->rt)->active)->bitmap의 100 bit를 1로 세팅
		// (&(&runqueues)->rt)->rt_runtime_lock 을 사용한 spinlock 초기화
		// (&(&runqueues)->rt)->rt_runtime: 0
		// (&(&runqueues)->rt)->rt_throttled: 0
		// (&(&runqueues)->rt)->rt_time: 0
		// (&(&(&runqueues)->rt)->pushable_tasks)->node_list 리스트 초기화
		// (&(&runqueues)->rt)->overloaded: 0
		// (&(&runqueues)->rt)->rt_nr_migratory: 0
		// (&(&runqueues)->rt)->highest_prio.next: 100
		// (&(&runqueues)->rt)->highest_prio.curr: 100

// 2014/08/30 종료
// 2014/09/13 시작

#ifdef CONFIG_FAIR_GROUP_SCHED // CONFIG_FAIR_GROUP_SCHED=n
		root_task_group.shares = ROOT_TASK_GROUP_LOAD;
		INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
		/*
		 * How much cpu bandwidth does root_task_group get?
		 *
		 * In case of task-groups formed thr' the cgroup filesystem, it
		 * gets 100% of the cpu resources in the system. This overall
		 * system cpu resource is divided among the tasks of
		 * root_task_group and its child task-groups in a fair manner,
		 * based on each entity's (task or task-group's) weight
		 * (se->load.weight).
		 *
		 * In other words, if root_task_group has 10 tasks of weight
		 * 1024) and two child groups A0 and A1 (of weight 1024 each),
		 * then A0's share of the cpu resource is:
		 *
		 *	A0's bandwidth = 1024 / (10*1024 + 1024 + 1024) = 8.33%
		 *
		 * We achieve this by letting root_task_group's tasks sit
		 * directly in rq->cfs (i.e root_task_group->se[] = NULL).
		 */
		init_cfs_bandwidth(&root_task_group.cfs_bandwidth);
		init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i, NULL);
#endif /* CONFIG_FAIR_GROUP_SCHED */

		// [pcp0] rq->rt.rt_runtime: (&runqueues)->rt.rt_runtime,
		// def_rt_bandwidth.rt_runtime: 950000000
		rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime;
		// [pcp0] rq->rt.rt_runtime: (&runqueues)->rt.rt_runtime: 950000000

#ifdef CONFIG_RT_GROUP_SCHED // CONFIG_RT_GROUP_SCHED=n
		INIT_LIST_HEAD(&rq->leaf_rt_rq_list);
		init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, NULL);
#endif

		// CPU_LOAD_IDX_MAX: 5
		for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
			// [pcp0] j: 0, rq->cpu_load[0]: (&runqueues)->cpu_load[0]
			rq->cpu_load[j] = 0;
			// [pcp0] j: 0, rq->cpu_load[0]: (&runqueues)->cpu_load[0]: 0
			// j: 1 .. 4 까지 수행

		// [pcp0] rq->last_load_update_tick: (&runqueues)->last_load_update_tick
		// jiffies: -30000 (0xFFFFFFFFFFFF8AD0): vmlinux.lds.S 에 있음
		rq->last_load_update_tick = jiffies;
		// [pcp0] rq->last_load_update_tick: (&runqueues)->last_load_update_tick: -30000 (0xFFFFFFFFFFFF8AD0)

#ifdef CONFIG_SMP // CONFIG_SMP=y
		// [pcp0] rq->sd: (&runqueues)->sd
		rq->sd = NULL;
		// [pcp0] rq->sd: (&runqueues)->sd: NULL

		// [pcp0] rq->rd: (&runqueues)->rd
		rq->rd = NULL;
		// [pcp0] rq->rd: (&runqueues)->rd: NULL

		// [pcp0] rq->cpu_power: (&runqueues)->cpu_power, SCHED_POWER_SCALE: 0x400
		rq->cpu_power = SCHED_POWER_SCALE;
		// [pcp0] rq->cpu_power: (&runqueues)->cpu_power: 0x400

		// [pcp0] rq->post_schedule: (&runqueues)->post_schedule
		rq->post_schedule = 0;
		// [pcp0] rq->post_schedule: (&runqueues)->post_schedule: 0

		// [pcp0] rq->active_balance: (&runqueues)->active_balance
		rq->active_balance = 0;
		// [pcp0] rq->active_balance: (&runqueues)->active_balance: 0

		// [pcp0] rq->next_balance: (&runqueues)->next_balance,
		// jiffies: -30000 (0xFFFFFFFFFFFF8AD0): vmlinux.lds.S 에 있음
		rq->next_balance = jiffies;
		// [pcp0] rq->next_balance: (&runqueues)->next_balance: -30000 (0xFFFFFFFFFFFF8AD0)

		// [pcp0] rq->push_cpu: (&runqueues)->push_cpu
		rq->push_cpu = 0;
		// [pcp0] rq->push_cpu: (&runqueues)->push_cpu: 0

		// [pcp0] rq->cpu: (&runqueues)->cpu, i: 0
		rq->cpu = i;
		// [pcp0] rq->cpu: (&runqueues)->cpu: 0

		// [pcp0] rq->online: (&runqueues)->online
		rq->online = 0;
		// [pcp0] rq->online: (&runqueues)->online: 0

		// [pcp0] rq->idle_stamp: (&runqueues)->idle_stamp
		rq->idle_stamp = 0;
		// [pcp0] rq->idle_stamp: (&runqueues)->idle_stamp: 0

		// [pcp0] rq->avg_idle: (&runqueues)->avg_idle,
		// sysctl_sched_migration_cost: 500000UL
		rq->avg_idle = 2*sysctl_sched_migration_cost;
		// [pcp0] rq->avg_idle: (&runqueues)->avg_idle: 1000000UL

		// [pcp0] rq->max_idle_balance_cost: (&runqueues)->max_idle_balance_cost,
		// sysctl_sched_migration_cost: 500000UL
		rq->max_idle_balance_cost = sysctl_sched_migration_cost;
		// [pcp0] rq->max_idle_balance_cost: (&runqueues)->max_idle_balance_cost: 500000UL

		// [pcp0] &rq->cfs_tasks: &(&runqueues)->cfs_tasks
		INIT_LIST_HEAD(&rq->cfs_tasks);
		// [pcp0] &rq->cfs_tasks: &(&runqueues)->cfs_tasks 의 list 초기화 수행

		// [pcp0] rq: &runqueues
		rq_attach_root(rq, &def_root_domain);
		// rq_attach_root에서 한일:
		// (&def_root_domain)->span: 1
		// (&runqueues)->rd: &def_root_domain
		// &(&runqueues)->refcount: 1

#ifdef CONFIG_NO_HZ_COMMON // CONFIG_NO_HZ_COMMON=y
		// [pcp0] rq->nohz_flags: (&runqueues)->nohz_flags
		rq->nohz_flags = 0;
		// [pcp0] rq->nohz_flags: (&runqueues)->nohz_flags: 0
#endif
#ifdef CONFIG_NO_HZ_FULL // CONFIG_NO_HZ_FULL=n
		rq->last_sched_tick = 0;
#endif
#endif
		// [pcp0] rq: &runqueues
		init_rq_hrtick(rq);
		// init_rq_hrtick에서 한일:
		// (&runqueues)->hrtick_csd_pending: 0
		// (&runqueues)->hrtick_csd.flags: 0
		// (&runqueues)->hrtick_csd.func: __hrtick_start
		// (&runqueues)->hrtick_csd.info: &runqueues
		// (&runqueues)->hrtick_timer의 값을 0으로 초기화
		// (&(&runqueues)->hrtick_timer)->base: &hrtimer_bases->clock_base[0]
		// RB Tree의 (&(&(&runqueues)->hrtick_timer)->node)->node 를 초기화
		// &rq->hrtick_timer.function: &(&runqueues)->hrtick_timerhrtick_timer.function: hrtick

		// [pcp0] &rq->nr_iowait: &(&runqueues)->nr_iowait
		atomic_set(&rq->nr_iowait, 0);
		// [pcp0] &rq->nr_iowait: &(&runqueues)->nr_iowait: 0
		
		// i: 1 .. 3 까지 루프 수행
	}

	set_load_weight(&init_task);
	// set_load_weight에서 한일:
	// (&(&init_task)->se.load)->weight: 1024
	// (&(&init_task)->se.load)->inv_weight: 4194304

#ifdef CONFIG_PREEMPT_NOTIFIERS // CONFIG_PREEMPT_NOTIFIERS=n
	INIT_HLIST_HEAD(&init_task.preempt_notifiers);
#endif

#ifdef CONFIG_RT_MUTEXES // CONFIG_RT_MUTEXES=y
	plist_head_init(&init_task.pi_waiters);
	// plist_head_init에서 한일:
	// (&init_task.pi_waiters)->node_list 리스트 초기화
#endif

	/*
	 * The boot idle thread does lazy MMU switching as well:
	 */
	// init_mm.mm_count: 1
	atomic_inc(&init_mm.mm_count);
	// init_mm.mm_count: 2

	// current: init_task
	enter_lazy_tlb(&init_mm, current); // null function

	/*
	 * Make us the idle thread. Technically, schedule() should not be
	 * called from this thread, however somewhere below it might be,
	 * but because we are the idle thread, we just pick up running again
	 * when this runqueue becomes "idle".
	 */
	// current: &init_task, smp_processor_id(): 0
	init_idle(current, smp_processor_id());
	// init_idle에서 한일:
	// (&init_task)->on_rq: 0
	// (&init_task)->se.on_rq: 0
	// (&init_task)->se.exec_start: 0
	// (&init_task)->se.sum_exec_runtime: 0
	// (&init_task)->se.prev_sum_exec_runtime: 0
	// (&init_task)->se.nr_migrations: 0
	// (&init_task)->se.vruntime: 0
	// &(&init_task)->se.group_node의 리스트 초기화
	// &(&init_task)->rt.run_list의 리스트 초기화
	// (&init_task)->state: TASK_RUNNING: 0
	// (&init_task)->se.exec_start: 0
	// (&init_task)->cpus_allowed->bits[0]: 1
	// (&init_task)->nr_cpus_allowed: 1
	// ((struct thread_info *)(&init_task)->stack)->cpu: 0
	// (&init_task)->wake_cpu: 0
	// [pcpu0] (&runqueues)->curr: &init_task
	// [pcpu0] (&runqueues)->idle: &init_task
	// (&init_task)->on_cpu: 1
	// ((struct thread_info *)(&init_task)->stack)->preempt_count: PREEMPT_ENABLED: 0
	// (&init_task)->sched_class: &idle_sched_class
	// (&init_task)->comm: "swapper/0"

	// jiffies: -30000 (0xFFFFFFFFFFFF8AD0): vmlinux.lds.S 에 있음, LOAD_FREQ: 501
	calc_load_update = jiffies + LOAD_FREQ;
	// calc_load_update: -29499 (0xFFFFFFFFFFFF8cc5)

	/*
	 * During early bootup we pretend to be a normal task:
	 */
	// current->sched_class: (&init_task)->sched_class
	current->sched_class = &fair_sched_class;
	// current->sched_class: (&init_task)->sched_class: &fair_sched_class

#ifdef CONFIG_SMP // CONFIG_SMP=y
	// GFP_NOWAIT: 0
	zalloc_cpumask_var(&sched_domains_tmpmask, GFP_NOWAIT);
	// sched_domains_tmpmask.bits[0]: 0

// 2014/09/13 종료
// 2014/09/20 시작

	/* May be allocated at isolcpus cmdline parse time */
	// cpu_isolated_map: NULL
	if (cpu_isolated_map == NULL)
		// cpu_isolated_map: NULL, GFP_NOWAIT: 0
		zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
		// cpu_isolated_map.bits[0]: 0

	idle_thread_set_boot_cpu();
	// [pcp0] idle_threads: &init_task
#endif
	init_sched_fair_class();
	// init_sched_fair_class가 한일:
	// softirq_vec[7].action: run_rebalance_domains
	// nohz.next_balance: -30000 (0xFFFFFFFFFFFF8AD0)
	// nohz.idle_cpus_mask.bits[0]: 0
	// (&cpu_chain)->head: sched_ilb_notifier_nb 포인터 대입
	// (&sched_ilb_notifier_nb)->next은 (&slab_notifier)->next로 대입

	scheduler_running = 1;
	// scheduler_running: 1
}

sched_init()에서 호출하는 주요 서브 함수

  • sched_init()->init_defrootdomain()
  • // def_root_domain의 맴버 값을 초기화 수행
  • // (&(&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 101])->count: 0
  • // (&(&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 101])->mask.bit[0]: 0
  • // (&(&def_root_domain)->cpupri)->pri_to_cpu[0 ... 3]: -1
  • // &def_root_domain.refcount: 1
  • sched_init()->init_rt_bandwidth(&def_rt_bandwidth, global_rt_period(), global_rt_runtime());
  • // init_rt_bandwidth에서 한일:
  • // (&def_rt_bandwidth)->rt_period: 1000000000
  • // (&def_rt_bandwidth)->rt_runtime: 950000000
  • // &(&def_rt_bandwidth)->rt_runtime_lock을 사용한 spinlock 초기화
  • // (&def_rt_bandwidth)->rt_period_timer의 값을 0으로 초기화
  • // &(&def_rt_bandwidth)->rt_period_timer)->base: &hrtimer_bases->clock_base[0]
  • // (&(&(&def_rt_bandwidth)->rt_period_timer)->node)->node의 RB Tree의 초기화
  • // &(&def_rt_bandwidth)->rt_period_timer.function: sched_rt_period_timer
  • sched_init()::for_each_possible_cpu(i) { ... }

  • sched_init()->set_load_weight()

  • // (&(&init_task)->se.load)->weight: 1024
  • // (&(&init_task)->se.load)->inv_weight: 4194304
  • sched_init()->plist_head_init()
  • // (&init_task.pi_waiters)->node_list 리스트 초기화
  • sched_init()->init_idle()
  • // (&init_task)->on_rq: 0
  • // (&init_task)->se.on_rq: 0
  • // (&init_task)->se.exec_start: 0
  • // (&init_task)->se.sum_exec_runtime: 0
  • // (&init_task)->se.prev_sum_exec_runtime: 0
  • // (&init_task)->se.nr_migrations: 0
  • // (&init_task)->se.vruntime: 0
  • // &(&init_task)->se.group_node의 리스트 초기화
  • // &(&init_task)->rt.run_list의 리스트 초기화
  • // (&init_task)->state: TASK_RUNNING: 0
  • // (&init_task)->se.exec_start: 0
  • // (&init_task)->cpus_allowed->bits[0]: 1
  • // (&init_task)->nr_cpus_allowed: 1
  • // ((struct thread_info *)(&init_task)->stack)->cpu: 0
  • // (&init_task)->wake_cpu: 0
  • // [pcpu0] (&runqueues)->curr: &init_task
  • // [pcpu0] (&runqueues)->idle: &init_task
  • // (&init_task)->on_cpu: 1
  • // ((struct thread_info *)(&init_task)->stack)->preempt_count: PREEMPT_ENABLED: 0
  • // (&init_task)->sched_class: &idle_sched_class
  • // (&init_task)->comm: "swapper/0"
  • sched_init()->zalloc_cpumask_var()
  • // sched_domains_tmpmask.bits[0]: 0
  • sched_init()->idle_thread_set_boot_cpu();
  • // [pcp0] idle_threads: &init_task
  • sched_init()->init_sched_fair_class();
  • // softirq_vec[7].action: run_rebalance_domains
  • // nohz.next_balance: -30000 (0xFFFFFFFFFFFF8AD0)
  • // nohz.idle_cpus_mask.bits[0]: 0
  • // (&cpu_chain)->head: sched_ilb_notifier_nb 포인터 대입
  • // (&sched_ilb_notifier_nb)->next은 (&slab_notifier)->next로 대입

cpumask.h::zalloc_cpumask_var()

// ARM10C 20140913
// &sched_domains_tmpmask, GFP_NOWAIT: 0
static inline bool zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
{
	// *mask: sched_domains_tmpmask
	cpumask_clear(*mask);
	// sched_domains_tmpmask.bits[0]: 0

	return true;
}

smpboot.c::idle_thread_set_boot_cpu()

// ARM10C 20140920
void __init idle_thread_set_boot_cpu(void)
{
	// smp_processor_id(): 0,
	// per_cpu(idle_threads, 0):
	// ({
	//  	do {
	// 	 	const void __percpu *__vpp_verify = (typeof(&(idle_threads)))NULL;
	// 	 	(void)__vpp_verify;
	//  	} while (0)
	//  	(&(idle_threads) + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋);
	// }),
	// current: &init_task
	per_cpu(idle_threads, smp_processor_id()) = current;
	// [pcp0] idle_threads: &init_task

}

// NOTE: // 주석의 편의를 위해 // (&(idle_threads) + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋) 를 // [pcp0] idle_threads 로 표시

main.c::start_kernel()

  • sched_init();
  • scheduler가 사용하는 자료 구조 초기화, idle_threads를 init_task로 세팅
  • preempt_disable();
  • preempt count를 증가시켜 preemption 못하도록 막음
  • irqs_disabled(): 1
  • idr_init_cache();
  • integer ID management로 사용하는 idr_layer_cache에 kmem_cache#21 을 생성 및 초기화 후 할당
  • rcu_init();
  • 분석 진행 중
asmlinkage void __init start_kernel(void)
{
...

	sched_init();
	// scheduler가 사용하는 자료 구조 초기화, idle_threads를 init_task로 세팅

	/*
	 * Disable preemption - early bootup scheduling is extremely
	 * fragile until we cpu_idle() for the first time.
	 */
	preempt_disable();
	// preempt count를 증가시켜 preemption 못하도록 막음

	// irqs_disabled(): 1
	if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))
		local_irq_disable();

	idr_init_cache();
	// integer ID management로 사용하는 idr_layer_cache에 kmem_cache#21 을 생성 및 초기화 후 할당

	rcu_init();

preempt.h::preempt_disabled()

#define preempt_disable()/*ARM10C this*/	\
do { \
	preempt_count_inc(); \
	barrier(); \
} while (0)

idr.c::idr_init_cache()

  • idr_layer_cache: kmem_cache#21
// ARM10C 20140920
void __init idr_init_cache(void)
{
	// sizeof(struct idr_layer): 1076 bytes, SLAB_PANIC: 0x00040000UL
	// kmem_cache_create("idr_layer_cache", 1076, 0, SLAB_PANIC: 0x00040000UL, NULL): kmem_cache#21
	idr_layer_cache = kmem_cache_create("idr_layer_cache",
				sizeof(struct idr_layer), 0, SLAB_PANIC, NULL);
	// idr_layer_cache: kmem_cache#21
}

tree.c::rcu_init()

// ARM10C 20140920
void __init rcu_init(void)
{
	int cpu;

	rcu_bootup_announce();
	rcu_init_geometry();
	// rcu_init_geometry에서 한일:
	// jiffies_till_first_fqs: 1
	// jiffies_till_next_fqs: 1

// 2014/09/20 종료