ARM10C : 103 주차
일시 : 2015.05.30 (103 주차 스터디 진행)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 2명
103 주차 진도
1 1 start_kernel 1 ~/kernel/iamroot/linux-stable/init/main.c
2 1 time_init 743 ~/kernel/iamroot/linux-stable/init/main.c
3 1 clocksource_of_init 557 ~/kernel/iamroot/linux-stable/arch/arm/kernel/time.c
4 1 mct_init_spi 56 ~/kernel/iamroot/linux-stable/drivers/clocksource/clksrc-of.c
5 1 mct_init_dt 1420 return mct_init_dt(np, MCT_INT_SPI);
6 1 exynos4_clocksource_init 1410 exynos4_clocksource_init();
7 1 exynos4_mct_frc_start 425 exynos4_mct_frc_start(0, 0)
main.c::main.c()
- called: start_kernel()->time_init()
asmlinkage void __init start_kernel(void)
{
...
sched_clock_postinit();
sched_clock.c::sched_clockinit()
- call: start_kernel()->sched_clock_postinit()
void __init sched_clock_postinit(void)
{
/*
* If no sched_clock function has been provided at that point,
* make it the final one one.
*/
if (read_sched_clock == jiffy_sched_clock_read)
sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
- call: start_kernel()->sched_clock_postinit()->sched_clock_register()
sched_clock.c::sched_clock_register()
- called: start_kernel()->sched_clock_postinit()->sched_clock_register()
void __init sched_clock_register(u64 (*read)(void), int bits,
unsigned long rate)
{
unsigned long r;
u64 res, wrap;
char r_unit;
// cd.rate: 0, rate: 100
if (cd.rate > rate)
return;
// irqs_disabled(): 1
WARN_ON(!irqs_disabled());
// read_sched_clock: read: jiffy_sched_clock_read
read_sched_clock = read;
// sched_clock_mask: CLOCKSOURCE_MASK(bits: 32):
// #define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1)
// sched_clock_mask: 0xffffffff
sched_clock_mask = CLOCKSOURCE_MASK(bits);
// cd.rate: rate: 100
cd.rate = rate;
/* calculate the mult/shift to convert counter ticks to ns. */
clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
// clock_calc_mult_shift():
// (&cd)->mult: 0x98968000
// (&cd)->shift: 8
r = rate;
if (r >= 4000000) {
r /= 1000000;
r_unit = 'M';
} else if (r >= 1000) {
r /= 1000;
r_unit = 'k';
} else
r_unit = ' ';
/* calculate how many ns until we wrap */
wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
//
clocksource.cc::clocks_calc_max_nsecs()
u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask)
{
u64 max_nsecs, max_cycles;
/*
* Calculate the maximum number of cycles that we can pass to the
* cyc2ns function without overflowing a 64-bit signed result. The
* maximum number of cycles is equal to ULLONG_MAX/(mult+maxadj)
* which is equivalent to the below.
* max_cycles < (2^63)/(mult + maxadj)
* max_cycles < 2^(log2((2^63)/(mult + maxadj)))
* max_cycles < 2^(log2(2^63) - log2(mult + maxadj))
* max_cycles < 2^(63 - log2(mult + maxadj))
* max_cycles < 1 << (63 - log2(mult + maxadj))
* Please note that we add 1 to the result of the log2 to account for
* any rounding errors, ensure the above inequality is satisfied and
* no overflow will occur.
*/
// mult: 0x98968000, maxadj: 0, ilog2(0x98968000): 31
max_cycles = 1ULL << (63 - (ilog2(mult + maxadj) + 1));
// max_cycles: 0x80000000
/*
* The actual maximum number of cycles we can defer the clocksource is
* determined by the minimum of max_cycles and mask.
* Note: Here we subtract the maxadj to make sure we don't sleep for
* too long if there's a large negative adjustment.
*/
// max_cycles: 0x80000000, 0xFFFFFFFF
max_cycles = min(max_cycles, mask);
// max_cycles: 0x80000000
// max_cycles: 0x80000000, mult: 0x98968000, maxadj: 0x0, shift: 8,
// clocksource_cyc2ns(0x80000000, 0x98968000, 8): 0x4c4b4000 000000
max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift);
// max_nsecs: 0x4c4b400000000
// max_nsecs: 0x4c4b400000000
return max_nsecs;
// return 0x4c4b400000000
}
sched_clock.c::
// ARM10C 20150530
// jiffy_sched_clock_read, BITS_PER_LONG: 32, HZ: 100
void __init sched_clock_register(u64 (*read)(void), int bits,
unsigned long rate)
{
...
/* calculate how many ns until we wrap */
wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
// wrap: 0x4c4b400000000
// wrap: 0x4c4b400000000, 0x9896800000000
// ns_to_ktime(0x42c1d800000000)
cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
ktime.h::ns_to_ktime()
static inline ktime_t ns_to_ktime(u64 ns)
{
static const ktime_t ktime_zero = { .tv64 = 0 };
// ktime_zero.tv64: 0
// ktime_zero: 0x1000000000000000
// ns: 0x42c1d800000000
// ktime_add_ns(ktime_zero, 0x42c1d800000000):
// ({ (ktime_t){ .tv64 = (ktime_zero).tv64 + (0x42c1d800000000) }; })
return ktime_add_ns(ktime_zero, ns);
// return 0x42c1d8389aca00
}
sched_clock.c::sched_clock_register()
// ARM10C 20150530
// jiffy_sched_clock_read, BITS_PER_LONG: 32, HZ: 100
void __init sched_clock_register(u64 (*read)(void), int bits,
unsigned long rate)
{
...
/* calculate how many ns until we wrap */
wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
// wrap: 0x4c4b400000000
// wrap: 0x4c4b400000000, 0x9896800000000
// ns_to_ktime(0x42c1d800000000)
cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
// cd.wrap_kt: 0x42c1d8389aca00
/* calculate the ns resolution of this counter */
res = cyc_to_ns(1ULL, cd.mult, cd.shift);
sched_clock.c::cyc_to_ns()
static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
{
// cyc: 1, mult: 0x98968000, shift: 8
return (cyc * mult) >> shift;
// return 0x989860
}
sched_clock.c::sched_clock_register()
// ARM10C 20150530
// jiffy_sched_clock_read, BITS_PER_LONG: 32, HZ: 100
void __init sched_clock_register(u64 (*read)(void), int bits,
unsigned long rate)
{
...
/* calculate the ns resolution of this counter */
res = cyc_to_ns(1ULL, cd.mult, cd.shift);
// res: 0x989860
pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
bits, r, r_unit, res, wrap);
// bits:32, r: 100, r_unit: ' ' res: 989680, wrap: 0x4c48400000000
// sched_clock: 0x20 bits at 100 hz resolution 10000000ns wraps every 214748364800000ns"
update_sched_clock();
sched_clock.c::update_sched_clock()
static void notrace update_sched_clock(void)
{
unsigned long flags;
u64 cyc;
u64 ns;
// read_sched_clock(): 0
cyc = read_sched_clock();
// cyc: 0
// cd.epoch_ns: 0
// cyc_to_ns((cyc: 0 - cd.epoch_cyc: 0) & sched_clock_mask: 0xffffffff , cd.mult: 0x98968000, cd.shift:0
ns = cd.epoch_ns +
cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
cd.mult, cd.shift);
// ns: 0
raw_local_irq_save(flags);
raw_write_seqcount_begin(&cd.seq);
// static inline void raw_write_seqcount_begin(seqcount_t *s)
// s->sequence++;
// smp_wmb();
// cd.seq: 1
cd.epoch_ns = ns;
// cd.epoch_ns: 0
cd.epoch_cyc = cyc;
// cd.epoch_cyc: 0
raw_write_seqcount_end(&cd.seq);
// static inline void raw_write_seqcount_begin(seqcount_t *s)
// smp_wmb();
// s->sequence++;
// cd.seq: 2
raw_local_irq_restore(flags);
}
sched_clock.c::sched_clock_register()
// ARM10C 20150530
// jiffy_sched_clock_read, BITS_PER_LONG: 32, HZ: 100
void __init sched_clock_register(u64 (*read)(void), int bits,
unsigned long rate)
{
...
update_sched_clock();
// cd.epoch_ns: 0
// cd.epoch_cyc: 0
// (&cd.seq): 2
/*
* Ensure that sched_clock() starts off at 0ns
*/
cd.epoch_ns = 0;
// cd.epoch_ns: 0
/* Enable IRQ time accounting if we have a fast enough sched_clock */
// irqtime: -1
// rate: 100 >= 100000
if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
enable_sched_clock_irqtime();
pr_debug("Registered %pF as sched_clock source\n", read);
// Registered xxx as sched_clock source
}
// 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);
update_sched_clock();
sched_clock.c::update_sched_clock()
static void notrace update_sched_clock(void)
{
unsigned long flags;
u64 cyc;
u64 ns;
// read_sched_clock(): 0
cyc = read_sched_clock();
// cyc: 0
// cd.epoch_ns: 0
// cyc_to_ns((cyc: 0 - cd.epoch_cyc: 0) & sched_clock_mask: 0xffffffff , cd.mult: 0x98968000, cd.shift:0
ns = cd.epoch_ns +
cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
cd.mult, cd.shift);
// ns: 0
raw_local_irq_save(flags);
raw_write_seqcount_begin(&cd.seq);
// static inline void raw_write_seqcount_begin(seqcount_t *s)
// s->sequence++;
// smp_wmb();
// cd.seq: 1
cd.epoch_ns = ns;
// cd.epoch_ns: 0
cd.epoch_cyc = cyc;
// cd.epoch_cyc: 0
raw_write_seqcount_end(&cd.seq);
// static inline void raw_write_seqcount_begin(seqcount_t *s)
// smp_wmb();
// s->sequence++;
// cd.seq: 2
raw_local_irq_restore(flags);
}
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);
update_sched_clock();
hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer.c::hrtimer_init()
void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
enum hrtimer_mode mode)
{
// timer: &(&def_rt_bandwidth)->rt_period_timer, clock_id: 1, mode: 1
// timer: &(&runqueues)->hrtick_timer, clock_id: 1, mode: 1
debug_init(timer, clock_id, mode);
// timer: &(&def_rt_bandwidth)->rt_period_timer, clock_id: 1, mode: 1
// timer: &(&runqueues)->hrtick_timer, clock_id: 1, mode: 1
__hrtimer_init(timer, clock_id, mode);
// __hrtimer_init(rt_period_timer) 한일:
// (&def_rt_bandwidth)->rt_period_timer의 값을 0으로 초기화
// (&(&def_rt_bandwidth)->rt_period_timer)->base: &hrtimer_bases->clock_base[0]
// RB Tree의 (&(&(&def_rt_bandwidth)->rt_period_timer)->node)->node 를 초기화
//
// __hrtimer_init(hrtick_timer) 한일:
// (&runqueues)->hrtick_timer의 값을 0으로 초기화
// (&(&runqueues)->hrtick_timer)->base: &hrtimer_bases->clock_base[0]
// RB Tree의 (&(&(&runqueues)->hrtick_timer)->node)->node 를 초기화
}
EXPORT_SYMBOL_GPL(hrtimer_init);
hrtimer.c::debug_init()
static inline void
debug_init(struct hrtimer *timer, clockid_t clockid,
enum hrtimer_mode mode)
{
// timer: &(&def_rt_bandwidth)->rt_period_timer
// timer: &(&runqueues)->hrtick_timer
debug_hrtimer_init(timer);
// debug_hrtimer_init(): null function
// timer: &(&def_rt_bandwidth)->rt_period_timer, clock_id: 1, mode: 1
// timer: &(&runqueues)->hrtick_timer, clock_id: 1, mode: 1
trace_hrtimer_init(timer, clockid, mode);
}
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);
update_sched_clock();
hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer.c::__hrtimer_init()
static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
enum hrtimer_mode mode)
{
struct hrtimer_cpu_base *cpu_base;
int base;
// timer: &(&def_rt_bandwidth)->rt_period_timer, sizeof(struct hrtimer): 40 bytes
// timer: &(&runqueues)->hrtick_timer, sizeof(struct hrtimer): 40 bytes
memset(timer, 0, sizeof(struct hrtimer));
// (&def_rt_bandwidth)->rt_period_timer의 값을 0으로 초기화
// (&runqueues)->hrtick_timer의 값을 0으로 초기화
// __raw_get_cpu_var(hrtimer_bases):
// *({
// do {
// const void __percpu *__vpp_verify = (typeof((&(hrtimer_bases))))NULL;
// (void)__vpp_verify;
// } while (0)
// &(hrtimer_bases) + __my_cpu_offset;
// })
cpu_base = &__raw_get_cpu_var(hrtimer_bases);
// cpu_base:
// ({
// do {
// const void __percpu *__vpp_verify = (typeof((&(hrtimer_bases))))NULL;
// (void)__vpp_verify;
// } while (0)
// &(hrtimer_bases) + __my_cpu_offset;
// })
// clock_id: 1, CLOCK_REALTIME: 0, mode: 1, HRTIMER_MODE_ABS: 0
// clock_id: 1, CLOCK_REALTIME: 0, mode: 1, HRTIMER_MODE_ABS: 0
if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
clock_id = CLOCK_MONOTONIC;
// clock_id: 1, hrtimer_clockid_to_base(1): 0
// clock_id: 1, hrtimer_clockid_to_base(1): 0
base = hrtimer_clockid_to_base(clock_id);
// base: 0
// base: 0
// timer->base: (&(&def_rt_bandwidth)->rt_period_timer)->base,
// base: 0, &cpu_base->clock_base: &hrtimer_bases->clock_base
// timer->base: (&(&runqueues)->hrtick_timer)->base,
// base: 0, &cpu_base->clock_base: &hrtimer_bases->clock_base
timer->base = &cpu_base->clock_base[base];
// timer->base: (&(&def_rt_bandwidth)->rt_period_timer)->base: &hrtimer_bases->clock_base[0]
// timer->base: (&(&runqueues)->hrtick_timer)->base: &hrtimer_bases->clock_base[0]
// &timer->node: &(&(&def_rt_bandwidth)->rt_period_timer)->node
// &timer->node: &(&(&runqueues)->hrtick_timer)->node
timerqueue_init(&timer->node);
// RB Tree의 (&(&(&def_rt_bandwidth)->rt_period_timer)->node)->node 를 초기화
// RB Tree의 &(&(&runqueues)->hrtick_timer)->node 를 초기화
#ifdef CONFIG_TIMER_STATS // CONFIG_TIMER_STATS=n
timer->start_site = NULL;
timer->start_pid = -1;
memset(timer->start_comm, 0, TASK_COMM_LEN);
#endif
}
log
cf3996e..db7acca master -> origin/master
Updating cf3996e..db7acca
Fast-forward
include/asm-generic/bitsperlong.h | 1 +
include/asm-generic/param.h | 1 +
include/linux/clocksource.h | 2 +
include/linux/irqflags.h | 3 +
include/linux/sched_clock.h | 2 +-
include/linux/time.h | 1 +
init/main.c | 3 +
kernel/time/clocksource.c | 341 +++++++++++++++++++++++++++++---------
kernel/time/sched_clock.c | 26 +++
9 files changed, 302 insertions(+), 78 deletions(-)
db7acca..e6b188d master -> origin/master
Merge made by the 'recursive' strategy.
include/linux/clocksource.h | 4 ++++
include/linux/hrtimer.h | 2 ++
include/linux/irqflags.h | 1 +
include/linux/ktime.h | 16 +++++++++++++---
include/linux/log2.h | 2 ++
include/linux/rbtree.h | 2 ++
include/linux/seqlock.h | 20 ++++++++++++++++++++
include/linux/timerqueue.h | 6 ++++++
include/trace/events/timer.h | 2 ++
include/uapi/linux/time.h | 1 +
kernel/hrtimer.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
kernel/time/clocksource.c | 13 ++++++++++++-
kernel/time/sched_clock.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 223 insertions(+), 6 deletions(-)
댓글 없음:
댓글 쓰기