ARM10C : 106 주차
일시 : 2015.06.20 (106 주차 스터디 진행)
모임명 : NAVER개발자커뮤니티지원_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 2명
106 주차 진도
- start_kernel 1 ~/kernel/iamroot/linux-stable/init/main.c
- sched_clock_postinit 750 ~/kernel/iamroot/linux-stable/init/main.c
- hrtimer_start 364 ~/kernel/iamroot/linux-stable/kernel/time/sched_clock.c
- __hrtimer_start_range_ns 1279 ~/kernel/iamroot/linux-stable/kernel/hrtimer.c
- lock_hrtimer_base 1137 ~/kernel/iamroot/linux-stable/kernel/hrtimer.c
- hrtimer_enqueue_reprogram 1223 ~/kernel/iamroot/linux-stable/kernel/hrtimer.c
- hrtimer_reprogram 789 ~/kernel/iamroot/linux-stable/kernel/hrtimer.c
- tick_program_event 753 ~/kernel/iamroot/linux-stable/kernel/hrtimer.c
main.c::main.c()
asmlinkage void __init start_kernel(void)
{
...
time_init();
// timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
// timer event를 위한 timer irq (MCT) 초기화 수행
sched_clock_postinit();
- call: start_kernel()->sched_clock_postinit()
sched_clock.c::sched_clockinit()
- called: start_kernel()->sched_clock_postinit()
// ARM10C 20150530
void __init sched_clock_postinit(void)
{
/*
* If no sched_clock function has been provided at that point,
* make it the final one one.
*/
// read_sched_clock: jiffy_sched_clock_read
if (read_sched_clock == jiffy_sched_clock_read)
// BITS_PER_LONG: 32, HZ: 100
sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
// sched_clock_register에서 한일:
// read_sched_clock: jiffy_sched_clock_read
// sched_clock_mask: 0xFFFFFFFF
// cd.rate: 100
// cd.epoch_ns: 0
// cd.epoch_cyc: 0
// cd.wrap_kt: 0x42C1D83B9ACA00
// (&cd)->mult: 0x98968000
// (&cd)->shift: 8
// (&cd.seq)->sequence: 2
update_sched_clock();
// update_sched_clock에서 한일:
// cd.epoch_ns: 0
// cd.epoch_cyc: 0
// (&cd.seq)->sequence: 4
/*
* Start the timer to keep sched_clock() properly updated and
* sets the initial epoch.
*/
// CLOCK_MONOTONIC: 1, HRTIMER_MODE_REL: 1
hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
// hrtimer_init에서 한일:
// sched_clock_timer의 값을 0으로 초기화
// (&sched_clock_timer)->base: &hrtimer_bases->clock_base[0]
// RB Tree의 &(&sched_clock_timer)->node 를 초기화
sched_clock_timer.function = sched_clock_poll;
// sched_clock_timer.function: sched_clock_poll
// cd.wrap_kt: 0x42C1D83B9ACA00, HRTIMER_MODE_REL: 1
hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
- call: start_kernel()->sched_clock_postinit()->hrtimer_start()
- hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
sched_clock.c::sched_clock_register()
- call: start_kernel()->sched_clock_postinit()->hrtimer_start()
- hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
// ARM10C 20150530
// &sched_clock_timer, cd.wrap_kt: 0x42C1D83B9ACA00, HRTIMER_MODE_REL: 1
int
hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
{
// timer: &sched_clock_timer, tim: 0x42C1D83B9ACA00, mode: 1
return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
}
EXPORT_SYMBOL_GPL(hrtimer_start);
- call: start_kernel()->sched_clock_postinit()->hrtimer_start()->__hrtimer_start_range_ns()
- return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
hrtimer.c::__hrtimer_start_range_ns()
- called: start_kernel()->sched_clock_postinit()->hrtimer_start()->__hrtimer_start_range_ns()
// ARM10C 20150530
// timer: &sched_clock_timer, tim: 0x42C1D83B9ACA00, 0, mode: 1, 1
int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long delta_ns, const enum hrtimer_mode mode,
int wakeup)
{
struct hrtimer_clock_base *base, *new_base;
unsigned long flags;
int ret, leftmost;
// timer: &sched_clock_timer
// lock_hrtimer_base(&sched_clock_timer, &flags): &hrtimer_bases->clock_base[0]
base = lock_hrtimer_base(timer, &flags);
// base: &hrtimer_bases->clock_base[0]
// lock_hrtimer_base에서 한일:
// (&sched_clock_timer)->base: &hrtimer_bases->clock_base[0] 을 리턴
// flags에 cpsr값을 가져옴
/* Remove an active timer from the queue: */
// timer: &sched_clock_timer, base: &hrtimer_bases->clock_base[0]
// remove_hrtimer(&sched_clock_timer, &hrtimer_bases->clock_base[0]): 0
ret = remove_hrtimer(timer, base);
// ret: 0
/* Switch the timer base, if necessary: */
// timer: &sched_clock_timer, base: &hrtimer_bases->clock_base[0], mode: 1,
// HRTIMER_MODE_PINNED: 0x02
// switch_hrtimer_base(&sched_clock_timer, &hrtimer_bases->clock_base[0], 0):
// [pcp0] &(&hrtimer_bases)->clock_base[0]
new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
// new_base: [pcp0] &(&hrtimer_bases)->clock_base[0]
// mode: 1, HRTIMER_MODE_REL: 1
if (mode & HRTIMER_MODE_REL) {
// tim.tv64: 0x42C1D83B9ACA00,
// new_base->get_time: [pcp0] (&(&hrtimer_bases)->clock_base[0])->get_time: &ktime_get,
// ktime_get(): (ktime_t) { .tv64 = 0}
// ktime_add_safe(0x42C1D83B9ACA00, (ktime_t) { .tv64 = 0}): (ktime_t) { .tv64 = 0x42C1D83B9ACA00}
tim = ktime_add_safe(tim, new_base->get_time());
// tim.tv64: 0x42C1D83B9ACA00
/*
* CONFIG_TIME_LOW_RES is a temporary way for architectures
* to signal that they simply return xtime in
* do_gettimeoffset(). In this case we want to round up by
* resolution when starting a relative timer, to avoid short
* timeouts. This will go away with the GTOD framework.
*/
#ifdef CONFIG_TIME_LOW_RES // CONFIG_TIME_LOW_RES=n
tim = ktime_add_safe(tim, base->resolution);
#endif
}
// timer: &sched_clock_timer, tim: 0x42C1D83B9ACA00, delta_ns: 0
hrtimer_set_expires_range_ns(timer, tim, delta_ns);
// hrtimer_set_expires_range_ns에서 한일:
// timer->_softexpires: (&sched_clock_timer)->_softexpires: 0x42C1D83B9ACA00
// timer->node.expires: (&sched_clock_timer)->node.expires: 0x42C1D83B9ACA00
// timer: &sched_clock_timer
timer_stats_hrtimer_set_start_info(timer); // null function
// timer: &sched_clock_timer, new_base: [pcp0] &(&hrtimer_bases)->clock_base[0]
// enqueue_hrtimer(&sched_clock_timer, [pcp0] &(&hrtimer_bases)->clock_base[0]): 1
leftmost = enqueue_hrtimer(timer, new_base);
// leftmost: 1
// enqueue_hrtimer에서 한일:
// (&(&(&sched_clock_timer)->node)->node)->__rb_parent_color: NULL
// (&(&(&sched_clock_timer)->node)->node)->rb_left: NULL
// (&(&(&sched_clock_timer)->node)->node)->rb_right: NULL
// [pcp0] (&(&(&hrtimer_bases)->clock_base[0])->active)->head.rb_node: &(&(&sched_clock_timer)->node)->node
//
// [pcp0] &(&(&(&hrtimer_bases)->clock_base[0])->active)->head 에 RB Tree 형태로
// &(&(&sched_clock_timer)->node)->node 를 추가함
//
// [pcp0] &(&(&(&hrtimer_bases)->clock_base[0])->active)->next: &(&sched_clock_timer)->node
// [pcp0] (&(&hrtimer_bases)->clock_base[0])->cpu_base->active_bases: 1
//
// (&sched_clock_timer)->state: 0x01
// leftmost: 1, new_base->cpu_base: [pcp0] (&(&hrtimer_bases)->clock_base[0])->cpu_base: [pcp0] &hrtimer_bases,
// &__get_cpu_var(hrtimer_bases): [pcp0] &hrtimer_bases
// timer: &sched_clock_timer, new_base: [pcp0] &(&hrtimer_bases)->clock_base[0]
if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)
&& hrtimer_enqueue_reprogram(timer, new_base)) {
if (wakeup) {
/*
* We need to drop cpu_base->lock to avoid a
* lock ordering issue vs. rq->lock.
*/
raw_spin_unlock(&new_base->cpu_base->lock);
raise_softirq_irqoff(HRTIMER_SOFTIRQ);
local_irq_restore(flags);
return ret;
} else {
__raise_softirq_irqoff(HRTIMER_SOFTIRQ);
}
}
unlock_hrtimer_base(timer, &flags);
// ret: 0
return ret;
// return 0
}
- return: start_kernel()->sched_clock_postinit()
- hrtimer_start()
- __hrtimer_start_range_ns()
- return 0
hrtimer.c::hrtimer_start()
- return: start_kernel()->sched_clock_postinit()
- hrtimer_start()
- __hrtimer_start_range_ns()
- return 0
// ARM10C 20150530
// &sched_clock_timer, cd.wrap_kt: 0x42C1D83B9ACA00, HRTIMER_MODE_REL: 1
int
hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
{
// timer: &sched_clock_timer, tim: 0x42C1D83B9ACA00, mode: 1
return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
}
EXPORT_SYMBOL_GPL(hrtimer_start);
sched_clock.c::sched_clock_postinit()
// ARM10C 20150530
void __init sched_clock_postinit(void)
{
/*
* If no sched_clock function has been provided at that point,
* make it the final one one.
*/
// read_sched_clock: jiffy_sched_clock_read
if (read_sched_clock == jiffy_sched_clock_read)
// BITS_PER_LONG: 32, HZ: 100
sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
// sched_clock_register에서 한일:
// read_sched_clock: jiffy_sched_clock_read
// sched_clock_mask: 0xFFFFFFFF
// cd.rate: 100
// cd.epoch_ns: 0
// cd.epoch_cyc: 0
// cd.wrap_kt: 0x42C1D83B9ACA00
// (&cd)->mult: 0x98968000
// (&cd)->shift: 8
// (&cd.seq)->sequence: 2
update_sched_clock();
// update_sched_clock에서 한일:
// cd.epoch_ns: 0
// cd.epoch_cyc: 0
// (&cd.seq)->sequence: 4
/*
* Start the timer to keep sched_clock() properly updated and
* sets the initial epoch.
*/
// CLOCK_MONOTONIC: 1, HRTIMER_MODE_REL: 1
hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
// hrtimer_init에서 한일:
// sched_clock_timer의 값을 0으로 초기화
// (&sched_clock_timer)->base: &hrtimer_bases->clock_base[0]
// RB Tree의 &(&sched_clock_timer)->node 를 초기화
sched_clock_timer.function = sched_clock_poll;
// sched_clock_timer.function: sched_clock_poll
// cd.wrap_kt: 0x42C1D83B9ACA00, HRTIMER_MODE_REL: 1
hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
}
- sched_clock_postinit(); 에서 한일
- sched_clock_timer을 초기화 수행
main.c::main.c()
- return: start_kernel()->sched_clock_postinit()
asmlinkage void __init start_kernel(void)
{
...
time_init();
// timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
// timer event를 위한 timer irq (MCT) 초기화 수행
sched_clock_postinit();
// sched_clock_timer을 초기화 수행
perf_event_init();
// null function.
profile_init();
// null function.
call_function_init();
- call: start_kernel()->call_function_init()
smp.c::call_function_init()
- called: start_kernel()->call_function_init()
void __init call_function_init(void)
{
void *cpu = (void *)(long)smp_processor_id();
// cpu: NULL
int i;
for_each_possible_cpu(i) {
struct call_single_queue *q = &per_cpu(call_single_queue, i);
raw_spin_lock_init(&q->lock);
INIT_LIST_HEAD(&q->list);
}
// &hotplug_cfd_notifier, CPU_UP_PREPARE: 0x0003, cpu
hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
- call: start_kernel()->call_function_init()->hotplug_cfd()
smp.c::hotplug_cfd()
static int
hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
struct call_function_data *cfd = &per_cpu(cfd_data, cpu);
switch (action) {
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
cpu_to_node(cpu)))
return notifier_from_errno(-ENOMEM);
if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
cpu_to_node(cpu))) {
free_cpumask_var(cfd->cpumask);
return notifier_from_errno(-ENOMEM);
}
cfd->csd = alloc_percpu(struct call_single_data);
if (!cfd->csd) {
free_cpumask_var(cfd->cpumask_ipi);
free_cpumask_var(cfd->cpumask);
return notifier_from_errno(-ENOMEM);
}
break;
#ifdef CONFIG_HOTPLUG_CPU
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
free_cpumask_var(cfd->cpumask);
free_cpumask_var(cfd->cpumask_ipi);
free_percpu(cfd->csd);
break;
#endif
};
return NOTIFY_OK;
}
- return: start_kernel()->call_function_init()->hotplug_cfd()
smp.c::call_function_init()
- return: start_kernel()->call_function_init()->hotplug_cfd()
void __init call_function_init(void)
{
void *cpu = (void *)(long)smp_processor_id();
// cpu: NULL
int i;
for_each_possible_cpu(i) {
struct call_single_queue *q = &per_cpu(call_single_queue, i);
raw_spin_lock_init(&q->lock);
INIT_LIST_HEAD(&q->list);
}
// &hotplug_cfd_notifier, CPU_UP_PREPARE: 0x0003, cpu
hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
register_cpu_notifier(&hotplug_cfd_notifier);
- return: start_kernel()->call_function_init()
main.c::main.c()
- called: start_kernel()->call_function_init()
asmlinkage void __init start_kernel(void)
{
...
time_init();
// timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
// timer event를 위한 timer irq (MCT) 초기화 수행
sched_clock_postinit();
sched_clock_postinit();
// sched_clock_timer을 초기화 수행
perf_event_init();
profile_init();
call_function_init();
// irqs_disabled()
WARN(!irqs_disabled(), "Interrupts were enabled early\n");
early_boot_irqs_disabled = false;
local_irq_enable();
* call: start_kernel()->local_irq_enable()
## irqflags.h::local_irq_enable()
* called: start_kernel()->local_irq_enable()
```irqflags.h
#define local_irq_enable() \
do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
# define trace_hardirqs_on() do { } while (0) // ARM10C this
#define raw_local_irq_enable() arch_local_irq_enable()
- call: start_kernel()->local_irq_enable()->arch_local_irq_enable()
irqflags.h::arch_local_irq_enable()
- call: start_kernel()->local_irq_enable()->arch_local_irq_enable()
static inline void arch_local_irq_enable(void)
{
asm volatile(
" cpsie i @ arch_local_irq_enable"
:
:
: "memory", "cc");
}
- return: start_kernel()->local_irq_enable()->arch_local_irq_enable()
main.c::main.c()
- called: start_kernel()->call_function_init()
asmlinkage void __init start_kernel(void)
{
...
time_init();
// timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
// timer event를 위한 timer irq (MCT) 초기화 수행
sched_clock_postinit();
// sched_clock_timer을 초기화 수행
perf_event_init();
// null funciton
profile_init();
// null funciton
call_function_init();
irqs_disabled()
WARN(!irqs_disabled(), "Interrupts were enabled early\n");
early_boot_irqs_disabled = false;
local_irq_enable();
kmem_cache_init_late();
// null funciton
log
1829c7c..d1c31fb master -> origin/master
Merge made by the 'recursive' strategy.
include/linux/clockchips.h | 4 ++
include/linux/err.h | 1 +
include/linux/hrtimer.h | 10 ++++
include/linux/ktime.h | 6 ++
include/linux/percpu.h | 1 +
include/linux/spinlock.h | 1 +
include/linux/time.h | 1 +
include/uapi/asm-generic/errno.h | 2 +
init/main.c | 2 +
kernel/hrtimer.c | 123 +++++++++++++++++++++++++++------------
kernel/sched/core.c | 17 +++++-
kernel/sched/rt.c | 3 +-
kernel/time/clockevents.c | 15 +++++
kernel/time/sched_clock.c | 19 +++++-
kernel/time/tick-internal.h | 2 +
kernel/time/tick-oneshot.c | 7 +++
kernel/time/timekeeping.c | 1 +
17 files changed, 173 insertions(+), 42 deletions(-)
d1c31fb..4f4095e master -> origin/master
Merge made by the 'recursive' strategy.
arch/arm/include/asm/irqflags.h | 1 +
arch/arm/include/asm/spinlock_types.h | 3 +
include/asm-generic/topology.h | 1 +
include/linux/bitmap.h | 4 ++
include/linux/cpu.h | 22 ++++++++
include/linux/cpumask.h | 21 +++++++
include/linux/gfp.h | 1 +
include/linux/irqflags.h | 3 +
include/linux/list.h | 2 +
include/linux/notifier.h | 2 +
include/linux/percpu-defs.h | 12 ++++
include/linux/percpu.h | 3 +
include/linux/perf_event.h | 3 +-
include/linux/profile.h | 3 +-
include/linux/smp.h | 8 ++-
include/linux/spinlock.h | 5 +-
include/linux/spinlock_types.h | 3 +
init/main.c | 23 ++++++--
kernel/cpu.c | 13 +++++
kernel/locking/spinlock_debug.c | 23 ++++++--
kernel/notifier.c | 11 ++++
kernel/smp.c | 102 +++++++++++++++++++++++++++++++---
mm/percpu.c | 2 +
mm/slub.c | 1 +
24 files changed, 251 insertions(+), 21 deletions(-)
댓글 없음:
댓글 쓰기