ARM10C 70주차 후기
일시 : 2014.09.20 (70주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_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
- raw_spin_lock_init(&rq->lock);
- 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->curr: &init_task
- // pcpu0->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->curr: &init_task
- // pcpu0->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 종료
댓글 없음:
댓글 쓰기