[커널 18차] 66주차
2022.08.27 22:21
clocksource, clockevents, timercounter, sched clock진행
git : https://github.com/iamroot18/5.10/commit/332a9ab0dc00a1bc2a967538827c1cb0260e624c
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index ae651007eca4..4dbb6c27703d 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -166,6 +166,10 @@ static inline u32 arch_timer_get_cntfrq(void)
return read_sysreg(cntfrq_el0);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - read cntkctl_el1
+ */
static inline u32 arch_timer_get_cntkctl(void)
{
return read_sysreg(cntkctl_el1);
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 2b7de75a00e3..7d91d73c6166 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -71,6 +71,10 @@
OUTPUT_ARCH(aarch64)
ENTRY(_text)
+/*
+ * IAMROOT, 2022.08.27:
+ * - jiffes 정의.
+ */
jiffies = jiffies_64;
#define HYPERVISOR_TEXT \
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 41815b33fdb5..4ade2757d06d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -112,6 +112,11 @@ static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_NONE;
#endif /* CONFIG_GENERIC_GETTIMEOFDAY */
static cpumask_t evtstrm_available = CPU_MASK_NONE;
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - config, early
+ */
static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
static int __init early_evtstrm_cfg(char *buf)
@@ -180,6 +185,11 @@ u32 arch_timer_reg_read(int access, enum arch_timer_reg reg,
break;
}
} else {
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - CP15
+ */
val = arch_timer_reg_read_cp15(access, reg);
}
@@ -680,6 +690,10 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t
local ? "local" : "global", wa->desc);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - read cntvct_el0
+ */
static bool arch_timer_this_cpu_has_cntvct_wa(void)
{
return has_erratum_handler(read_cntvct_el0);
@@ -739,6 +753,10 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - @access timer regiser 직접제어. disable.
+ */
static __always_inline int timer_shutdown(const int access,
struct clock_event_device *clk)
{
@@ -751,11 +769,19 @@ static __always_inline int timer_shutdown(const int access,
return 0;
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - virt timer regiser 직접제어. disable.
+ */
static int arch_timer_shutdown_virt(struct clock_event_device *clk)
{
return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - phy timer regiser 직접제어. disable.
+ */
static int arch_timer_shutdown_phys(struct clock_event_device *clk)
{
return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
@@ -810,6 +836,10 @@ static int arch_timer_set_next_event_phys_mem(unsigned long evt,
return 0;
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - @clk를 @type에 따라 초기화한다.
+ */
static void __arch_timer_setup(unsigned type,
struct clock_event_device *clk)
{
@@ -826,6 +856,11 @@ static void __arch_timer_setup(unsigned type,
clk->rating = 450;
clk->cpumask = cpumask_of(smp_processor_id());
clk->irq = arch_timer_ppi[arch_timer_uses_ppi];
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - guest os일경우, virt 그외에 phy로 callback 함수를 등록한다.
+ */
switch (arch_timer_uses_ppi) {
case ARCH_TIMER_VIRT_PPI:
clk->set_state_shutdown = arch_timer_shutdown_virt;
@@ -862,11 +897,28 @@ static void __arch_timer_setup(unsigned type,
}
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - timer stop
+ */
clk->set_state_shutdown(clk);
+/*
+ * IAMROOT, 2022.08.27:
+ * - 15tick , 31bit로 clockevents의 최소 최대값을 설정한다.
+ * (programming이 가능한 최소, 최대 틱)
+ */
clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - divider를 EVNTI위치에 set. evt enable도 set한다.
+ * - ex) 19.2MHZ에서, eventi가 13일때(0b1101) 1초에 발생하는 event 횟수.
+ * 19200000 / 0x1000 = 4580
+ * pulse가 raising edge에서만 동작한다고 했을때 4580 / 2 = 2343.
+ * 1초에 1171번 발생한다.
+ */
static void arch_timer_evtstrm_enable(int divider)
{
u32 cntkctl = arch_timer_get_cntkctl();
@@ -880,6 +932,10 @@ static void arch_timer_evtstrm_enable(int divider)
cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - evt stream을 설정하고 enable한다.(wfe를 위한것.)
+ */
static void arch_timer_configure_evtstream(void)
{
int evt_stream_div, lsb;
@@ -888,20 +944,44 @@ static void arch_timer_configure_evtstream(void)
* As the event stream can at most be generated at half the frequency
* of the counter, use half the frequency when computing the divider.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - evt_stream_div = arch_timer_rate / 2000
+ * arch_timer_rate = 19.2M이라고 했을대
+ * evt_stream_div = 19200000 / 2000 = 9600
+ */
evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ / 2;
/*
* Find the closest power of two to the divisor. If the adjacent bit
* of lsb (last set bit, starts from 0) is set, then we use (lsb + 1).
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - evt_stream_div & BIT(lsb - 1)
+ * 반올림 여부 판단.
+ *
+ * ex) evt_stream_div = 9600 = 0b10_0101_1000_0000
+ * ^반올림 체크
+ * fls(9600) = 14.
+ * lsb = 13 (반올림 안됨)
+ */
lsb = fls(evt_stream_div) - 1;
if (lsb > 0 && (evt_stream_div & BIT(lsb - 1)))
lsb++;
/* enable event stream */
+/*
+ * IAMROOT, 2022.08.27:
+ * - 최대 15bit까지만 가능.(ARCH_TIMER_EVT_TRIGGER_SHIFT 참고)
+ */
arch_timer_evtstrm_enable(max(0, min(lsb, 15)));
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - ARCH_TIMER_USR_VCT_ACCESS_EN set이 가능한지 여부를 판단해 set한다.
+ */
static void arch_counter_set_user_access(void)
{
u32 cntkctl = arch_timer_get_cntkctl();
@@ -939,6 +1019,10 @@ static bool arch_timer_has_nonsecure_ppi(void)
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - irq의 trigger flags를 얻어온다.
+ */
static u32 check_ppi_trigger(int irq)
{
u32 flags = irq_get_trigger_type(irq);
@@ -952,6 +1036,14 @@ static u32 check_ppi_trigger(int irq)
return flags;
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - arch_timer_register에서 CPUHP_AP_ARM_ARCH_TIMER_STARTING에서
+ * call되는 함수.
+ *
+ * - ARCH_TIMER_TYPE_CP15 설정.
+ * irq 설정.
+ */
static int arch_timer_starting_cpu(unsigned int cpu)
{
struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
@@ -959,9 +1051,19 @@ static int arch_timer_starting_cpu(unsigned int cpu)
__arch_timer_setup(ARCH_TIMER_TYPE_CP15, clk);
+/*
+ * IAMROOT, 2022.08.27:
+ * - arch_timer_uses_ppi에 대한 flags를 가져와서 percpu_irq를 등록한다.
+ */
flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - nonsecure_ppi가 있는경우 nonsecure_pp가 flags를 가져와서
+ * percpu_irq를 등록한다.
+ */
if (arch_timer_has_nonsecure_ppi()) {
flags = check_ppi_trigger(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
enable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI],
@@ -969,6 +1071,10 @@ static int arch_timer_starting_cpu(unsigned int cpu)
}
arch_counter_set_user_access();
+/*
+ * IAMROOT, 2022.08.27:
+ * - default config enable.
+ */
if (evtstrm_enable)
arch_timer_configure_evtstream();
@@ -1080,6 +1186,10 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
/*
* IAMROOT, 2022.08.20:
* @type arch_timers_present
+ * 1. clocksource
+ * 2. clockevents
+ * 3. timercounter
+ * 4. sched clock
*/
static void __init arch_counter_register(unsigned type)
{
@@ -1123,7 +1233,8 @@ static void __init arch_counter_register(unsigned type)
/*
* IAMROOT, 2022.08.20:
- * -
+ * - clocksource_counter에서 구한 mult, shift값으로 cyclecounter에 사용하고,
+ * 만들어진 cyclecounter를 arch_timer_kvm_info의 timecounter로 사용한다.
*/
start_count = arch_timer_read_counter();
clocksource_register_hz(&clocksource_counter, arch_timer_rate);
@@ -1133,6 +1244,10 @@ static void __init arch_counter_register(unsigned type)
&cyclecounter, start_count);
/* 56 bits minimum, so we assume worst case rollover */
+/*
+ * IAMROOT, 2022.08.27:
+ * - arch timer를 sched의 tick으로 사용하겠다는것.
+ */
sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
}
@@ -1386,6 +1501,10 @@ static bool __init arch_timer_needs_of_probing(void)
return needs_probing;
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - timer common init.
+ */
static int __init arch_timer_common_init(void)
{
arch_timer_banner(arch_timers_present);
@@ -1722,6 +1841,10 @@ static int __init arch_timer_mem_of_init(struct device_node *np)
timer_mem->cntctlbase = res.start;
timer_mem->size = resource_size(&res);
+/*
+ * IAMROOT, 2022.08.27:
+ * - dts에서 정의된 frame_number를 가져와 각각의 number로 mem time을 설정한다.
+ */
for_each_available_child_of_node(np, frame_node) {
u32 n;
struct arch_timer_mem_frame *frame;
@@ -1749,9 +1872,20 @@ static int __init arch_timer_mem_of_init(struct device_node *np)
of_node_put(frame_node);
goto out;
}
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - register address 및 size설정
+ */
frame->cntbase = res.start;
frame->size = resource_size(&res);
+/*
+ * IAMROOT, 2022.08.27:
+ * - virt irq, phys irq 설정. pcpu가 아닌 mem time이기 때문에 SPI를
+ * (shared peri interrupt)
+ * 사용하는게 보인다.
+ */
frame->virt_irq = irq_of_parse_and_map(frame_node,
ARCH_TIMER_VIRT_SPI);
frame->phys_irq = irq_of_parse_and_map(frame_node,
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 300020ab4dca..cda340125cd4 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -56,14 +56,36 @@ enum arch_timer_spi_nr {
#define ARCH_TIMER_MEM_MAX_FRAMES 8
#define ARCH_TIMER_USR_PCT_ACCESS_EN (1 << 0) /* physical counter */
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - el0(usere)에서 virtual counter로 직접 access가능하게 한다.
+ */
#define ARCH_TIMER_USR_VCT_ACCESS_EN (1 << 1) /* virtual counter */
#define ARCH_TIMER_VIRT_EVT_EN (1 << 2)
+
+/*
+ * IAMROOT, 2022.08.27:
+ * EVNTI, bits [7:4]
+ * Selects which bit of the counter register CNTVCT_EL0 is the trigger for the
+ * event stream generated from that counter, when that stream is enabled.
+ * If FEAT_ECV is implemented, and CNTKCTL_EL1.EVNTIS is 1, this field selects a
+ * trigger bit in the range 8 to 23 of the counter register CNTVCT_EL0.
+ * Otherwise, this field selects a trigger bit in the range 0 to 15 of
+ * the counter register. The reset behavior of this field is:
+ * On a Warm reset, this field resets to an architecturally UNKNOWN value.
+ */
#define ARCH_TIMER_EVT_TRIGGER_SHIFT (4)
#define ARCH_TIMER_EVT_TRIGGER_MASK (0xF << ARCH_TIMER_EVT_TRIGGER_SHIFT)
#define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */
#define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */
#define ARCH_TIMER_EVT_STREAM_PERIOD_US 100
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - 1000000 / 100 = 1000
+ */
#define ARCH_TIMER_EVT_STREAM_FREQ \
(USEC_PER_SEC / ARCH_TIMER_EVT_STREAM_PERIOD_US)
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 8ae9a95ebf5b..27a4e3e69e12 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -189,6 +189,10 @@ extern void clockevents_config_and_register(struct clock_event_device *dev,
extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
+/*
+ * IAMROOT, 2022.08.27:
+ * - mult, shift를 계산하여 알아온다.
+ */
static inline void
clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 maxsec)
{
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 2b8c839c6768..5ce4c3706d18 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -93,7 +93,16 @@ struct module;
* information you need you should consider to cache line align that
* structure.
*/
+
struct clocksource {
+/*
+ * IAMROOT, 2022.08.27:
+ * - __clocksource_update_freq_scale()에서
+ * mask, mult, shift, max_idle_ns, maxadj, uncertainty_margin, max_cycles
+ * 이 초기화 된다.
+ * - clocks_calc_max_nsecs()를 사용하여 ns값을 계산한다.
+ * ex) clocks_calc_max_nsecs(mult, shift, maxadj, mask, max_cycles)
+ */
u64 (*read)(struct clocksource *cs);
u64 mask;
u32 mult;
@@ -105,6 +114,11 @@ struct clocksource {
struct arch_clocksource_data archdata;
#endif
u64 max_cycles;
+/*
+ * IAMROOT, 2022.08.27:
+ * - struct clocksource정의시, rate, name, id, read, mask, flags등이 미리
+ * 정의된다.(arm_arch_timer.c clocksource_counter 참고)
+ */
const char *name;
struct list_head list;
int rating;
@@ -201,6 +215,11 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
*
* XXX - This could use some mult_lxl_ll() asm optimization
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - (from * mult) >> shift = to
+ * - cycles값을 nanosecond로 치환한다.
+ */
static inline s64 clocksource_cyc2ns(u64 cycles, u32 mult, u32 shift)
{
return ((u64) cycles * mult) >> shift;
@@ -243,7 +262,8 @@ static inline int __clocksource_register(struct clocksource *cs)
/*
* IAMROOT, 2022.08.20:
- * -
+ * - from * factor >> shift = to
+ * to 값을 @hz로 사용해 factor를 구하고 @cs를 초기화한다.
*/
static inline int clocksource_register_hz(struct clocksource *cs, u32 hz)
{
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 5e13f801c902..5d85ffb15800 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -76,6 +76,13 @@ extern int register_refined_jiffies(long clock_tick_rate);
* without sampling the sequence number in jiffies_lock.
* get_jiffies_64() will do this for you as appropriate.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - jiffies : kernel/time/jiffies.c에 export symbol
+ * arm/arm64/kernel/vmlinux.lkds.S에서
+ * jiffies_64를 jiffies로 사용하는것이 확인된다.
+ * - jiffies_64 : kernel/time/timer.c
+ */
extern u64 __cacheline_aligned_in_smp jiffies_64;
extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;
@@ -170,6 +177,10 @@ static inline u64 get_jiffies_64(void)
* Have the 32 bit jiffies value wrap 5 minutes after boot
* so jiffies wrap bugs show up earlier.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - -5분. bug를 찾기 위한 용도.
+ */
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
/*
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 73f20deb497d..27153383448e 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -219,6 +219,10 @@ static inline __must_check bool ktime_to_timespec64_cond(const ktime_t kt,
#include <vdso/ktime.h>
+/*
+ * IAMROOT, 2022.08.27:
+ * - ktime은 ns로 사용하니 즉시 return. 부호 여부.
+ */
static inline ktime_t ns_to_ktime(u64 ns)
{
return ns;
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 749b174ef2f2..ef6f6a293bca 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -692,6 +692,13 @@ typedef struct {
* picking which data copy to read. The full counter must then be checked
* with read_seqcount_latch_retry().
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - papgo
+ * 시퀀스 카운터 원시 값. 읽을 데이터 복사본을 선택하기 위한 인덱스로
+ * 가장 낮은 비트를 사용합니다. 그런 다음 전체 카운터를
+ * read_seqcount_latch_retry()로 확인해야 합니다
+ */
static inline unsigned raw_read_seqcount_latch(const seqcount_latch_t *s)
{
/*
@@ -795,6 +802,82 @@ read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start)
* When data is a dynamic data structure; one should use regular RCU
* patterns to manage the lifetimes of the objects within.
*/
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - papgo
+ * aw_write_seqcount_latch() - 래치 판독기를 짝수/홀수 사본 @s로 리디렉션:
+ * seqcount_latch_t에 대한 포인터 래치 기술은 원자가 아닌 수정 중에
+ * 쿼리를 허용하는 다중 버전 동시성 제어 방법입니다. 쿼리가 수정을
+ * 중단하지 않도록 보장할 수 있다면 -- 예를 들어 동시성은 CPU 간에
+ * 엄격하게 이루어지므로 필요하지 않을 가능성이 큽니다.
+ *
+ * 기존의 RCU/잠금 없는 데이터 구조가 원자적 수정에 의존하여 쿼리가 이전
+ * 또는 새 상태를 관찰하도록 보장하는 경우 래치가 비원자 업데이트에 대해
+ * 동일한 것을 허용합니다. 절충안은 스토리지 비용을 두 배로 늘립니다.
+ * 전체 데이터 구조의 두 복사본을 유지해야 합니다.
+ *
+ * 아주 간단히 말해서:
+ * 먼저 한 사본을 수정한 다음 다른 사본을 수정합니다. 이것은 우리에게
+ * 답을 줄 준비가 된 안정적인 상태의 사본이 항상 하나 있음을 보장합니다.
+ *
+ * 기본 형식은 다음과 같은 데이터 구조입니다.
+ * struct latch_struct {
+ * seqcount_latch_t seq;
+ * struct data_struct data[2];
+ * };
+ *
+ * 외부 직렬화를 전제로 하는 수정 사항은 다음과 같습니다::
+ *
+ * void latch_modify(struct latch_struct *latch, ...)
+ * {
+ * smp_wmb(); // Ensure that the last data[1] update is visible
+ * latch->seq.sequence++;
+ * smp_wmb(); // Ensure that the seqcount update is visible
+ *
+ * modify(latch->data[0], ...);
+ *
+ * smp_wmb(); // Ensure that the data[0] update is visible
+ * latch->seq.sequence++;
+ * smp_wmb(); // Ensure that the seqcount update is visible
+ *
+ * modify(latch->data[1], ...);
+ * }
+ *
+ * The query will have a form like::
+ *
+ * struct entry *latch_query(struct latch_struct *latch, ...)
+ * {
+ * struct entry *entry;
+ * unsigned seq, idx;
+ *
+ * do {
+ * seq = raw_read_seqcount_latch(&latch->seq);
+ *
+ * idx = seq & 0x01;
+ * entry = data_query(latch->data[idx], ...);
+ *
+ * // This includes needed smp_rmb()
+ * } while (read_seqcount_latch_retry(&latch->seq, seq));
+ *
+ * return entry;
+ * }
+ *
+ * 따라서 수정하는 동안 쿼리는 먼저 data[1]로 리디렉션됩니다. 그런 다음
+ * 데이터[0]을 수정합니다. 완료되면 쿼리를 다시 data[0]으로 리디렉션하고
+ * data[1]을 수정할 수 있습니다.
+ *
+ * 노트:
+ * 원자적 수정에 대한 비요구 사항은 데이터가 동적 데이터 구조인 경우
+ * 새 항목의 게시를 포함하지 않는다.
+ *
+ * 반복은 data[0]에서 시작하고 전체 수정 시퀀스를 놓칠 만큼 충분히
+ * 오래 일시 중단될 수 있습니다. 다시 시작하면 새 항목이 관찰될 수
+ * 있습니다.
+ *
+ * 노트 2: 데이터가 동적 데이터 구조인 경우 내부 개체의 수명을 관리하려면
+ * 일반 RCU 패턴을 사용해야 합니다.
+ */
static inline void raw_write_seqcount_latch(seqcount_latch_t *s)
{
smp_wmb(); /* prior stores before incrementing "sequence" */
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 003ccf338d20..61eb67d4fd16 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -29,20 +29,47 @@ struct ce_unbind {
int res;
};
+/*
+ * IAMROOT, 2022.08.27:
+ * @return 최솟값이 1000ns이상인 latch -> ns 변환값.
+ * - @evt의 mult, shift값을 사용해 latch의 ns를 구해온다.
+ * - ex) mult = 0xdd2_f1aa, shift = 32
+ * 1. latch = 0xf = > 숫자가 작기때문에 1000
+ * 2. latch = 0x7fffffff
+ * clc = 0x7fffffff = 0x7fffffff_0000_0000
+ * rnd = mult - 1 = 0xdd2_f1a9
+ * clc += rnd ==> clc = 0x7fffffff_0dd2_f1a9
+ * clc = clc / 0xdd2_f1a9
+ * = 39768215854 (ns)
+ * = 39 (sec)
+ */
static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
bool ismax)
{
+/*
+ * IAMROOT, 2022.08.27:
+ * - clc = (정확도가 고려된 cycle)
+ * mult = (정확도가 고려된 1 ns당 cycle 개수)
+ */
u64 clc = (u64) latch << evt->shift;
u64 rnd;
if (WARN_ON(!evt->mult))
evt->mult = 1;
+/*
+ * IAMROOT, 2022.08.27:
+ * - 반올 손상 보정.
+ */
rnd = (u64) evt->mult - 1;
/*
* Upper bound sanity check. If the backwards conversion is
* not equal latch, we know that the above shift overflowed.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - overflow check.
+ */
if ((clc >> evt->shift) != (u64)latch)
clc = ~0ULL;
@@ -65,6 +92,26 @@ static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
*
* Also omit the add if it would overflow the u64 boundary.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - papago
+ * 스케일링된 수학 기이함:
+ * mult <= (1 << shift)의 경우 정수 반올림 손실을 방지하기 위해 mult - 1을
+ * 안전하게 추가할 수 있습니다. 따라서 nsec에서 장치 틱으로의 역변환은
+ * 정확할 것입니다.
+ *
+ * mult > (1 << shift), 즉 장치 주파수가 > 1GHz인 경우 주의해야 합니다.
+ * mult - 1을 추가하면 장치 틱으로 다시 변환될 때 최대
+ * (mult - 1) >> shift만큼 래치보다 클 수 있는 값이 생성됩니다. min_delta
+ * 계산의 경우 최소 장치 틱 제한 이상을 유지하기 위해 여전히 이를 적용하려고
+ * 합니다. 상한선의 경우 장치의 상한선보다 큰 래치 값으로 끝나므로 장치
+ * 상한선 아래에 머물기 위해 추가를 생략합니다.
+ *
+ * 또한 u64 경계를 넘을 경우 추가를 생략합니다.
+ *
+ * - 반올림을 계산한다. 이 계산으로 인한 상한값 overflow가 발생안하게 하기위한
+ * 예외처리.
+ */
if ((~0ULL - clc > rnd) &&
(!ismax || evt->mult <= (1ULL << evt->shift)))
clc += rnd;
@@ -340,6 +387,10 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
* Called after a notify add to make devices available which were
* released from the notifier call.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - TODO
+ */
static void clockevents_notify_released(void)
{
struct clock_event_device *dev;
@@ -440,6 +491,10 @@ EXPORT_SYMBOL_GPL(clockevents_unbind_device);
* clockevents_register_device - register a clock event device
* @dev: device to register
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - cpumask 검사, state 변경. clock event 등록
+ */
void clockevents_register_device(struct clock_event_device *dev)
{
unsigned long flags;
@@ -447,6 +502,10 @@ void clockevents_register_device(struct clock_event_device *dev)
/* Initialize state to DETACHED */
clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED);
+/*
+ * IAMROOT, 2022.08.27:
+ * - cpumask가 지정이 안되있으면 현재 cpu만. all cpu면 possible로 지정한다.
+ */
if (!dev->cpumask) {
WARN_ON(num_possible_cpus() > 1);
dev->cpumask = cpumask_of(smp_processor_id());
@@ -468,6 +527,10 @@ void clockevents_register_device(struct clock_event_device *dev)
}
EXPORT_SYMBOL_GPL(clockevents_register_device);
+/*
+ * IAMROOT, 2022.08.27:
+ * - @dev가 @freq로 지원하는 min / max nsec를 구한다.
+ */
static void clockevents_config(struct clock_event_device *dev, u32 freq)
{
u64 sec;
@@ -487,7 +550,16 @@ static void clockevents_config(struct clock_event_device *dev, u32 freq)
else if (sec > 600 && dev->max_delta_ticks > UINT_MAX)
sec = 600;
+/*
+ * IAMROOT, 2022.08.27:
+ * - @dev의 mult, shift값을 계산해온다.
+ */
clockevents_calc_mult_shift(dev, freq, sec);
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - min, max tick을 가지고 nsec를 구한다.
+ */
dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false);
dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true);
}
@@ -501,6 +573,11 @@ static void clockevents_config(struct clock_event_device *dev, u32 freq)
*
* min/max_delta can be 0 for devices which do not support oneshot mode.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - clockevents의 @freq, 최대최소 nsec를 설정하고 시슷템에 clock event를
+ * 등록한다.
+ */
void clockevents_config_and_register(struct clock_event_device *dev,
u32 freq, unsigned long min_delta,
unsigned long max_delta)
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index d7082bc17fc4..fab45863c9d1 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -49,6 +49,8 @@
* - sftacc 계산
* 600 * 19200000 = 0x2_AEA5_4000 => shift32 => 0x2
* 두번 loop를 돌면 sftacc = 30가 된다.
+ *
+ * - 이진화 정수화.
*/
void
clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec)
@@ -56,7 +58,7 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec)
u64 tmp;
/*
* IAMROOT, 2022.08.20:
- * - 정확도는 최대 32bit.
+ * - 이진화 정확도는 최대 32bit.
*/
u32 sft, sftacc= 32;
@@ -113,9 +115,26 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec)
* tmp = do_div(16777216000000000, 19200000) = 873813333 = 0x3415_5555
* tmp >> sftasce = 0x3415_5555 >> 30 == 0
* mult = 0x3415_5555, shift = 24가 된다.
+ *
+ * - ex) 0.1을 이진화 정수화.
+ *
+ * 0 | (0.1에 대한 값)
+ *
+ * 0.1 * 2 = 0.2 -> 0
+ * 0.2 * 2 = 0.4 -> 0
+ * 0.4 * 2 = 0.8 -> 0
+ * 0.8 * 2 = 1.6 -> 1
+ * .------- 0.6
+ * 0.6 * 2 = 1.2 -> 1
+ * 0.2 * 2 = 0.4 -> 0
*/
for (sft = 32; sft > 0; sft--) {
tmp = (u64) to << sft;
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - round up
+ */
tmp += from / 2;
do_div(tmp, from);
if ((tmp >> sftacc) == 0)
@@ -869,6 +888,10 @@ void clocksource_touch_watchdog(void)
* @cs: Pointer to clocksource
*
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - mult의 0.11배값을 return.
+ */
static u32 clocksource_max_adjustment(struct clocksource *cs)
{
u64 ret;
@@ -895,6 +918,20 @@ static u32 clocksource_max_adjustment(struct clocksource *cs)
* delayed timers or bad hardware, which might result in time intervals that
* are larger than what the math used can handle without overflows.
*/
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - papago
+ * 이 함수에는 50%의 safety margin가 포함됩니다. 즉, 하드웨어 카운터가 기술적으로
+ * 처리할 수 있는 나노초 수의 절반을 반환합니다. 이는 지연된 타이머 또는 잘못된
+ * 하드웨어로 인해 발생하는 문제를 잠재적으로 감지할 수 있도록 하기 위해 수행되며,
+ * 이로 인해 사용된 수학이 오버플로 없이 처리할 수 있는 것보다 더 큰 시간 간격이
+ * 발생할 수 있습니다.
+ */
+/*
+ * IAMROOT, 2022.08.27:
+ * - overlfow가 발생할수있는 제한을 구한다.
+ */
u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cyc)
{
u64 max_nsecs, max_cycles;
@@ -903,6 +940,10 @@ u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cy
* Calculate the maximum number of cycles that we can pass to the
* cyc2ns() function without overflowing a 64-bit result.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - max_cycles = UNLLONG_MAX / (mult + maxadj)
+ */
max_cycles = ULLONG_MAX;
do_div(max_cycles, mult+maxadj);
@@ -912,7 +953,24 @@ u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cy
* Note: Here we subtract the maxadj to make sure we don't sleep for
* too long if there's a large negative adjustment.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - papago
+ * 클럭 소스를 연기할 수 있는 실제 최대 사이클 수는 max_cycles와
+ * 마스크의 최소값에 의해 결정됩니다.
+ * note:
+ * 여기서 우리는 큰 음수 조정이 있는 경우 너무 오랫동안 잠을 자지
+ * 않도록 maxadj를 뺍니다.
+ *
+ * - mask값(ex. arm arch timer CLOCKSOURCE_MASK(56)과 min 비교를 한다.
+ * 즉 mask값보다 높은 값을 사용하지 않겟다는것.
+ */
max_cycles = min(max_cycles, mask);
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - max_cyc값에 해당하는 max_nsecs값을 구한다
+ */
max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift);
/* return the max_cycles value as well if requested */
@@ -930,6 +988,10 @@ u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cy
* @cs: Pointer to clocksource to be updated
*
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - overflow당하지 않을 cycle값과 ns값을 구한다.
+ */
static inline void clocksource_update_max_deferment(struct clocksource *cs)
{
cs->max_idle_ns = clocks_calc_max_nsecs(cs->mult, cs->shift,
@@ -1079,6 +1141,11 @@ static void clocksource_enqueue(struct clocksource *cs)
* __clocksource_update_freq_hz() or __clocksource_update_freq_khz() helper
* functions.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - @cs에 대한 mult, shift값을 구하고 margin, adj, max_idle_ns,
+ * max_cycles 값을 구한다.
+ */
void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq)
{
u64 sec;
@@ -1142,6 +1209,22 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
* to be specified by the caller for testing purposes, but warn
* to discourage production use of this capability.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - papgo
+ * 불확실성 마진이 지정되지 않은 경우 계산합니다. scale과 freq가 모두 0이 아닌 경우 클록 주기를
+ * 계산하지만 2*WATCHDOG_MAX_SKEW에서 아래로 제한됩니다. 그러나 scale 또는 freq 중 하나가 0이면
+ * 매우 보수적이며 불확실성 마진에 대해 수십 밀리초 WATCHDOG_THRESHOLD 값을 사용합니다. 테스트
+ * 목적으로 호출자가 지정하는 어리석게 작은 불확실성 마진을 허용하지만 이 기능의 프로덕션
+ * 사용을 권장하지 않도록 경고합니다.
+ */
+/*
+ * IAMROOT, 2022.08.27:
+ * - cs->uncertainty_margin이 0인 경우
+ * scale, freq둘다 0이 아니면 계산. 그렇지 않은경우 고정값 사용.
+ * - 1초에대한 margin값을 정의 하는것.
+ * ex) margin이 0.1이라고 하면 0.9 ~ 1.1 사이값이 오면 1초라고 생각한다는것.
+ */
if (scale && freq && !cs->uncertainty_margin) {
cs->uncertainty_margin = NSEC_PER_SEC / (scale * freq);
if (cs->uncertainty_margin < 2 * WATCHDOG_MAX_SKEW)
@@ -1156,6 +1239,11 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
* when adjusted.
*/
cs->maxadj = clocksource_max_adjustment(cs);
+/*
+ * IAMROOT, 2022.08.27:
+ * - adj값을 계산하고 계산된 mult에 적용해봐서 overflow, underflow가 안될때까지
+ * 재조정한다.
+ */
while (freq && ((cs->mult + cs->maxadj < cs->mult)
|| (cs->mult - cs->maxadj > cs->mult))) {
cs->mult >>= 1;
@@ -1171,8 +1259,23 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
"timekeeping: Clocksource %s might overflow on 11%% adjustment\n",
cs->name);
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - overflow당하지 않은 제한값(cs->max_idle_ns)을 구한다.
+ */
clocksource_update_max_deferment(cs);
+/*
+ * IAMROOT, 2022.08.27:
+ * - ex) x64 ubuntu
+ * clocksource: tsc: mask: 0xffffffffffffffff
+ * max_cycles: 0x6d581b92771, max_idle_ns: 881590605997 ns
+ * - 위 예제로 봤을때 600초를 제한으로 했지만, 881초까지 여유를 두는것이
+ * 확인된다.
+ * 881초도 50%줄인 숫자(max_idle_ns)이고, 실제로는 max_cycles에 있는
+ * 881 * 2초 만큼 버티게된다.
+ */
pr_info("%s: mask: 0x%llx max_cycles: 0x%llx, max_idle_ns: %lld ns\n",
cs->name, cs->mask, cs->max_cycles, cs->max_idle_ns);
}
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index bc4db9e5ab70..c073ad67d6d4 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -59,6 +59,12 @@ u64 get_jiffies_64(void)
EXPORT_SYMBOL(get_jiffies_64);
#endif
+/*
+ * IAMROOT, 2022.08.27:
+ * - jiffes를 export symbol한다.
+ * jiffes는 arch/arm64/kernel/vmlinux.lds.S.
+ * 실제 위치는 kernel/time/jiffies.c
+ */
EXPORT_SYMBOL(jiffies);
static int __init init_jiffies_clocksource(void)
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index b1b9b12899f5..a7d203537bea 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -36,6 +36,10 @@
*/
struct clock_data {
seqcount_latch_t seq;
+/*
+ * IAMROOT, 2022.08.27:
+ * - update_clock_read_data() 주석참고
+ */
struct clock_read_data read_data[2];
ktime_t wrap_kt;
unsigned long rate;
@@ -48,16 +52,28 @@ static int irqtime = -1;
core_param(irqtime, irqtime, int, 0400);
+/*
+ * IAMROOT, 2022.08.27:
+ * - system에서 사용하는 기본 clock.
+ */
static u64 notrace jiffy_sched_clock_read(void)
{
/*
* We don't need to use get_jiffies_64 on 32-bit arches here
* because we register with BITS_PER_LONG
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - -5분 offset을 원복하는 개념.
+ */
return (u64)(jiffies - INITIAL_JIFFIES);
}
static struct clock_data cd ____cacheline_aligned = {
+/*
+ * IAMROOT, 2022.08.27:
+ * - mult = 1clock당 nanosec
+ */
.read_data[0] = { .mult = NSEC_PER_SEC / HZ,
.read_sched_clock = jiffy_sched_clock_read, },
.actual_read_sched_clock = jiffy_sched_clock_read,
@@ -106,6 +122,42 @@ unsigned long long notrace sched_clock(void)
* as possible the system reverts back to the even copy when the update
* completes; the odd copy is used *only* during an update.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - papago
+ * clock을 읽는 데 필요한 데이터 업데이트.
+ * sched_clock()은 NMI에서 호출되더라도 일치하지 않는 데이터를 관찰하지
+ * 않습니다. 데이터의 홀수/짝수 복사본을 유지하고 시퀀스 카운터를 사용하여
+ * sched_clock()을 하나 또는 다른 것으로 조정하여 이를 수행합니다.
+ * sched_clock()의 데이터 캐시 프로필을 최대한 유지하기 위해 업데이트가
+ * 완료되면 시스템이 짝수 복사본으로 되돌아갑니다. 홀수 복사본은 업데이트
+ * *중*에만 사용됩니다
+ *
+ * - clock이 바뀌고 있는 와중에, 다른 cpu등에서 참조를 할수있다.
+ * 특히 nmi같은 경우엔 lockless가 필수적인데 이러한 상황을 고려하여
+ * seqcount latch방법을 사용한다.
+ *
+ * - ex) seq = 0인 상황
+ *
+ * 1. 평소 상태. seq는 무조건 짝수일것.(seq = 0, 2, 4..)
+ * read_data[0] read_data[1]
+ * ^평소에 읽는 data ^갱신을 할때만 읽게하는 data
+ *
+ * 2. read_data[1]을 write. 시작. (seq = 0, 2, 4..)
+ *
+ * 갱신 진행중
+ * read_data[0] read_data[1]
+ * ^seq&1로 접근.
+ *
+ * 3. read_data[1] 갱신 완료. seq++ (seq = 1, 3, 5..)
+ * read_data[0] 갱신 시작.
+ *
+ * 갱신 진행중 이미 갱신된상태
+ * read_data[0] read_data[1]
+ * ^write중 ^seq&1 로 읽음.
+ *
+ * 4. read_data[0] 갱신완료. seq++ (seq = 0, 2, 4..) 1.번으로 복귀.
+ */
static void update_clock_read_data(struct clock_read_data *rd)
{
/* update the backup (odd) copy with the new data */
@@ -141,6 +193,11 @@ static void update_sched_clock(void)
update_clock_read_data(&rd);
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - clock을 update해주고 다시 timer를 가동한다.
+ * 1시간 주기로 동작을 할것이다.
+ */
static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
{
update_sched_clock();
@@ -149,6 +206,12 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
return HRTIMER_RESTART;
}
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - @cd를 재계산한다. sched에 사용할 clocksource를 갱신한다.
+ * - sche tick은 아주 높은 정밀도는 필요없다.
+ */
void __init
sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
{
@@ -158,6 +221,10 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
char r_unit;
struct clock_read_data rd;
+/*
+ * IAMROOT, 2022.08.27:
+ * - 이 함수는 여러번 call될수있다. 가장 높은 rate로 갱신한다는것.
+ */
if (cd.rate > rate)
return;
@@ -165,12 +232,20 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
local_irq_save(flags);
/* Calculate the mult/shift to convert counter ticks to ns. */
+/*
+ * IAMROOT, 2022.08.27:
+ * - 3600초로 mult shift를 계산한다.
+ */
clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
new_mask = CLOCKSOURCE_MASK(bits);
cd.rate = rate;
/* Calculate how many nanosecs until we risk wrapping */
+/*
+ * IAMROOT, 2022.08.27:
+ * - 1바퀴란 의미의 wrap. 1주기에 대한 시간 계산.
+ */
wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask, NULL);
cd.wrap_kt = ns_to_ktime(wrap);
@@ -179,6 +254,14 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
/* Update epoch for new counter and update 'epoch_ns' from old counter*/
new_epoch = read();
cyc = cd.actual_read_sched_clock();
+
+/*
+ * IAMROOT, 2022.08.27:
+ * - clock 속도는 기본적으로 높고(ex 54000000Hz) sche clck은 1000hz이다.
+ *
+ * - new_epoch = old_epoch_ns + cyc_to_ns(curr_cyc - old_cyc)
+ * - A clock과 B clock간에 격차를 줄이기 위한 작업을 한다.
+ */
ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
cd.actual_read_sched_clock = read;
@@ -189,8 +272,22 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
rd.epoch_cyc = new_epoch;
rd.epoch_ns = ns;
+/*
+ * IAMROOT, 2022.08.27:
+ * - 새로만든 rd를 cd에 update한다.
+ */
update_clock_read_data(&rd);
+/*
+ * IAMROOT, 2022.08.27:
+ * - wrap이 끝나기 전에 wrap_kt시간으로 자동으로 갱신해준다.
+ * - no hz에 대비한 갱신.
+ * 예를들어 cpu0가 잠들어있는 중에 변경이되면 overflow가 발생할수있으므로
+ * 이를 예방하는것이다.
+ * - nohz(sche tick이 필요없는 상태).
+ * nohz idle : task가 절전상태.
+ * nohz full : task가 한개만 동작중.
+ */
if (sched_clock_timer.function != NULL) {
/* update timeout for clock wrap */
hrtimer_start(&sched_clock_timer, cd.wrap_kt,
@@ -213,6 +310,13 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
/* Calculate the ns resolution of this counter */
res = cyc_to_ns(1ULL, new_mult, new_shift);
+/*
+ * IAMROOT, 2022.08.27:
+ * - ex)x64 pc ubuntu에서의 qemu
+ * sched_clock: 56 bits at 62MHz, resolution 16ns,
+ * wraps every 4398 046 511 096ns
+ * 4398초마다 깨어나서 자동 갱신한다는것.
+ */
pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
bits, r, r_unit, res, wrap);
@@ -256,6 +360,17 @@ void __init generic_sched_clock_init(void)
* at the end of the critical section to be sure we observe the
* correct copy of 'epoch_cyc'.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - papago
+ * clock이 정지되었을 때 사용하는 clock 읽기 기능.
+ * 이 함수는 clock이 마지막 업데이트에서 계산을 멈춘 것처럼 sched_clock()에
+ * 표시되도록 합니다.
+ *
+ * 이 함수는 sched_clock()의 크리티컬 섹션에서만 호출해야 합니다.
+ * 'epoch_cyc'의 올바른 복사본을 관찰하기 위해 중요한 섹션 끝에 있는
+ * read_seqcount_retry()에 의존합니다.
+ */
static u64 notrace suspended_sched_clock_read(void)
{
unsigned int seq = raw_read_seqcount_latch(&cd.seq);
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 46789356f856..4d3756a801d3 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -25,6 +25,10 @@
/*
* Tick devices
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - sche tick.
+ */
DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
/*
* Tick next event: keeps track of the tick time. It's updated by the
@@ -338,6 +342,10 @@ bool tick_check_replacement(struct clock_event_device *curdev,
* Check, if the new registered device should be used. Called with
* clockevents_lock held and interrupts disabled.
*/
+/*
+ * IAMROOT, 2022.08.27:
+ * - TODO
+ */
void tick_check_new_device(struct clock_event_device *newdev)
{
struct clock_event_device *curdev;
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 649f2b48e8f0..3a6176519ba3 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -41,6 +41,10 @@ static inline enum clock_event_state clockevent_get_state(struct clock_event_dev
return dev->state_use_accessors;
}
+/*
+ * IAMROOT, 2022.08.27:
+ * - @state로 설정한다.
+ */
static inline void clockevent_set_state(struct clock_event_device *dev,
enum clock_event_state state)
{
diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c
index e6285288d765..802946cd1f75 100644
--- a/kernel/time/timecounter.c
+++ b/kernel/time/timecounter.c
@@ -5,6 +5,10 @@
#include <linux/export.h>
#include <linux/timecounter.h>
+/*
+ * IAMROOT, 2022.08.27:
+ * - @cc로 @tc를 초기화한다.
+ */
void timecounter_init(struct timecounter *tc,
const struct cyclecounter *cc,
u64 start_tstamp)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index e3d2c23c413d..3a68f23b6786 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -56,6 +56,10 @@
#define CREATE_TRACE_POINTS
#include <trace/events/timer.h>
+/*
+ * IAMROOT, 2022.08.27:
+ * - jiffies_64 정의.
+ */
__visible u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
EXPORT_SYMBOL(jiffies_64);
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 626 |
148 | [커널 17차] 103주차 | ㅇㅇㅇ | 2022.08.28 | 35 |
» | [커널 18차] 66주차 | kkr | 2022.08.27 | 76 |
146 | [커널 17차] 101~102주차 | ㅇㅇㅇ | 2022.08.21 | 47 |
145 | [커널 18차] 65주차 | kkr | 2022.08.20 | 28 |
144 | [커널 18차] 64주차 | kkr | 2022.08.13 | 75 |
143 | [커널 17차] 100주차 [1] | ㅇㅇㅇ | 2022.08.06 | 100 |
142 | [커널 18차] 63주차 | kkr | 2022.08.06 | 102 |
141 | [커널 17차] 99주차 | ㅇㅇㅇ | 2022.07.31 | 35 |
140 | [커널 18차] 62주차 | kkr | 2022.07.30 | 26 |
139 | [커널 17차] 97~98주차 | ㅇㅇㅇ | 2022.07.24 | 52 |
138 | [커널 18차] 61주차 | kkr | 2022.07.23 | 113 |
137 | [커널 18차] 60주차 | kkr | 2022.07.16 | 129 |
136 | [커널 17차] 95~96주차 | ㅇㅇㅇ | 2022.07.10 | 105 |
135 | [커널 18차] 59주차 | kkr | 2022.07.09 | 126 |
134 | [커널 19차] 8주차 | kanlee | 2022.07.02 | 160 |
133 | [커널 19차] 7주차 | kanlee | 2022.07.02 | 95 |
132 | [커널 19차] 6주차 | kanlee | 2022.07.02 | 42 |
131 | [커널 19차] 5주차 | kanlee | 2022.07.02 | 38 |
130 | [커널 19차] 4주차 | kanlee | 2022.07.02 | 106 |
129 | [커널 18차] 57주차 | kkr | 2022.06.25 | 129 |
.