[커널 18차] 80주차

2022.12.03 22:22

kkr 조회 수:156

periodic tick 진행

 

git : https://github.com/iamroot18/5.10/commit/db584c473c5b37e2e74fc3e0b927e9299e94483a

 

diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 27a4e3e69e12..4dc971ea1479 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -45,6 +45,10 @@ enum clock_event_state {
  */
 # define CLOCK_EVT_FEAT_PERIODIC    0x000001
 # define CLOCK_EVT_FEAT_ONESHOT        0x000002
+/*
+ * IAMROOT, 2022.12.03:
+ * - ktime_t로 설정이 가능하다는것.
+ */
 # define CLOCK_EVT_FEAT_KTIME        0x000004
 
 /*
@@ -53,6 +57,11 @@ enum clock_event_state {
  * - Clockevent source stops in C3 State and needs broadcast support.
  * - Local APIC timer is used as a dummy device.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - C3
+ *   clock 절전기능. 전원은 끄지 않고 clock만 멈추는 기능.
+ */
 # define CLOCK_EVT_FEAT_C3STOP        0x000008
 # define CLOCK_EVT_FEAT_DUMMY        0x000010
 
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 5ce4c3706d18..5b3ca379a006 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -150,6 +150,10 @@ struct clocksource {
 #define CLOCK_SOURCE_MUST_VERIFY        0x02
 
 #define CLOCK_SOURCE_WATCHDOG            0x10
+/*
+ * IAMROOT, 2022.12.03:
+ * - HIGH Resolution timer 
+ */
 #define CLOCK_SOURCE_VALID_FOR_HRES        0x20
 #define CLOCK_SOURCE_UNSTABLE            0x40
 #define CLOCK_SOURCE_SUSPEND_NONSTOP        0x80
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 575be407c243..72ab73abd8a4 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -270,6 +270,10 @@ struct hrtimer_cpu_base {
     struct hrtimer_clock_base    clock_base[HRTIMER_MAX_CLOCK_BASES];
 } ____cacheline_aligned;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - @timer에 @time을 set한다.
+ */
 static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
 {
     timer->node.expires = time;
@@ -549,6 +553,10 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);
  * Note: This only updates the timer expiry value and does not requeue
  * the timer.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - 현재 시각을 기준으로 interval후에 expire된다.
+ */
 static inline u64 hrtimer_forward_now(struct hrtimer *timer,
                       ktime_t interval)
 {
diff --git a/include/linux/prandom.h b/include/linux/prandom.h
index 056d31317e49..6de0da0816f9 100644
--- a/include/linux/prandom.h
+++ b/include/linux/prandom.h
@@ -18,6 +18,10 @@ void prandom_reseed_late(void);
 
 DECLARE_PER_CPU(unsigned long, net_rand_noise);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 
+ */
 #define PRANDOM_ADD_NOISE(a, b, c, d) \
     prandom_u32_add_noise((unsigned long)(a), (unsigned long)(b), \
                   (unsigned long)(c), (unsigned long)(d))
@@ -56,6 +60,10 @@ DECLARE_PER_CPU(unsigned long, net_rand_noise);
 #error Unsupported BITS_PER_LONG
 #endif
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 인자를 가지고 pcpu net_rand_noise에 랜덤값을 구해놓는다.
+ */
 static inline void prandom_u32_add_noise(unsigned long a, unsigned long b,
                      unsigned long c, unsigned long d)
 {
diff --git a/include/linux/sched/loadavg.h b/include/linux/sched/loadavg.h
index 9f2a2b4cdc0c..5d8b54854d4f 100644
--- a/include/linux/sched/loadavg.h
+++ b/include/linux/sched/loadavg.h
@@ -16,12 +16,32 @@ extern unsigned long avenrun[];        /* Load averages */
 extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift);
 
 #define FSHIFT        11        /* nr of bits of precision */
+/*
+ * IAMROOT, 2022.12.03:
+ * - 이진화정수화한 정밀도. 2^11 = 2048
+ */
 #define FIXED_1        (1<<FSHIFT)    /* 1.0 as fixed-point */
 /*
  * IAMROOT, 2022.11.26:
  * - 5초지난후 다음 tick.
  */
 #define LOAD_FREQ    (5*HZ+1)    /* 5 sec intervals */
+/*
+ * IAMROOT, 2022.12.03:
+ * - e = 2.718281828459045...
+ *
+ * - new값을 old대비 몇 % 비율을 넣느냐를 이진화정수화 해서 결정한다.
+ *   EXP_1 : 1분은 약 92%
+ *   EXP_5 : 5분은 약 98.35%
+ *   EXP_15 : 15분은 약 99.45%
+ *   이값을 100%를 2048로 이진화정수화 하여 계산한다.
+ *
+ * - e^(-1/12) = 0.9200..
+ *   이값에 이진화정수 정밀도 적용
+ *   0.9200 * 2048 = 1884
+ * - e^(-1/60) = 
+ * - e^(-1/180)
+ */
 #define EXP_1        1884        /* 1/exp(5sec/1min) as fixed-point */
 #define EXP_5        2014        /* 1/exp(5sec/5min) */
 #define EXP_15        2037        /* 1/exp(5sec/15min) */
@@ -29,15 +49,50 @@ extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift);
 /*
  * a1 = a0 * e + a * (1 - e)
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - ex) task1개 만큼 증가한 case.
+ *   load = 1024, exp = 1884, active = 2048
+ *   newload = 1024 * 1884 + 2048 * (2048 - 1884)
+ *           = 2,265,088
+ *   return = (2,265,088 + 2047)/ 2048
+ *          = 1106
+ * - ex) task가 안돌때 감소한 case.
+ *   load = 1024, exp = 1884, active = 0
+ *   newload = 1024 * 1884 + 0 * (2048 - 1884)
+ *           = 1,929,216
+ *   return = 1,929,216 / 2048
+ *          = 942
+ */
 static inline unsigned long
 calc_load(unsigned long load, unsigned long exp, unsigned long active)
 {
     unsigned long newload;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - old * k + new * ( 1 - k)
+ */
     newload = load * exp + active * (FIXED_1 - exp);
+/*
+ * IAMROOT, 2022.12.03:
+ * - new값이 old보다 크거나 같으면 2048 - 1을 더해준다.
+ *   new값이 클경우 올림처리.
+ * - 글로벌 cpu 로드를 처리하는데 장시간 idle 상태인데에도 각 주기별로 0.00, 0.01, 0.05 이하 값이 더 이상 하강하지 않는 버그가 있어 수정하였다.
+ * - 참고)
+ *   https://github.com/torvalds/linux/commit/20878232c52329f92423d27a60e48b6a6389e0dd#diff-3a8f0c7004315fef3f3985bfd1945858*
+ */
     if (active >= load)
         newload += FIXED_1-1;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 100 -> * 10 -> 1000 
+ *   50     * 10  -> 500
+ *   20     * 10  -> 200
+ *
+ *  700 / 10 = 70
+ */
     return newload / FIXED_1;
 }
 
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index db8c248ebc8c..d6165f8cdf95 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -162,6 +162,10 @@ void irq_work_single(void *arg)
     (void)atomic_cmpxchg(&work->node.a_flags, flags, flags & ~IRQ_WORK_BUSY);
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - @list에 있는걸 즉시 수행한다.
+ */
 static void irq_work_run_list(struct llist_head *list)
 {
     struct irq_work *work, *tmp;
@@ -188,12 +192,27 @@ void irq_work_run(void)
 }
 EXPORT_SYMBOL_GPL(irq_work_run);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - irq 내부일경우 irq tick수행.
+ *   arm64의 경우 lazy만 여기서 수행한다.
+ */
 void irq_work_tick(void)
 {
     struct llist_head *raised = this_cpu_ptr(&raised_list);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 조건에 맞으면 이 로직에서 즉시 수행한다.
+ *   arm64는 arch_irq_work_has_interrupt가 true이므로 수행된진않는다.
+ */
     if (!llist_empty(raised) && !arch_irq_work_has_interrupt())
         irq_work_run_list(raised);
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - lazy_list에 있는것만 호출한다.
+ */
     irq_work_run_list(this_cpu_ptr(&lazy_list));
 }
 
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index bfdd5e7307ca..a95e7b288778 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5276,6 +5276,10 @@ static inline u64 cpu_resched_latency(struct rq *rq) { return 0; }
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - TODO
+ */
 void scheduler_tick(void)
 {
     int cpu = smp_processor_id();
@@ -5293,6 +5297,10 @@ void scheduler_tick(void)
     update_rq_clock(rq);
     thermal_pressure = arch_scale_thermal_pressure(cpu_of(rq));
     update_thermal_load_avg(rq_clock_thermal(rq), rq, thermal_pressure);
+/*
+ * IAMROOT, 2022.12.03:
+ * - 현재 진행중인 current task의 scheduler한테 tick공급.
+ */
     curr->sched_class->task_tick(rq, curr, 0);
     if (sched_feat(LATENCY_WARN))
         resched_latency = cpu_resched_latency(rq);
diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c
index 954b229868d9..7723e73a4dc3 100644
--- a/kernel/sched/loadavg.c
+++ b/kernel/sched/loadavg.c
@@ -57,6 +57,11 @@
 
 /* Variables and functions for calc_load */
 atomic_long_t calc_load_tasks;
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - calc_global_load에서 load를 계산해야될 시각.(jiffies)
+ */
 unsigned long calc_load_update;
 unsigned long avenrun[3];
 EXPORT_SYMBOL(avenrun); /* should be removed */
@@ -76,6 +81,10 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
     loads[2] = (avenrun[2] + offset) << shift;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - running + uninterruptible의 변화된값을 return한다.
+ */
 long calc_load_fold_active(struct rq *this_rq, long adjust)
 {
     long nr_active, delta = 0;
@@ -106,6 +115,10 @@ long calc_load_fold_active(struct rq *this_rq, long adjust)
  * of course trivially computable in O(log_2 n), the length of our binary
  * vector.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - e^N의 이진화정수 계산.
+ */
 static unsigned long
 fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n)
 {
@@ -153,6 +166,17 @@ fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n)
  *     S_n := \Sum x^i = -------------
  *             i=0          1 - x
  */
+
+/*
+ * IAMROOT, 2022.12.03:
+ * n = 1 ) x1 = old * e + new * (1 - e)
+ * n = 2 ) x2 = x1 * e + new * (1 - e)
+ * n = 3 ) x3 = x2 * e + new * (1 - e)
+ *
+ * n = N ) x1 = old * e^(N) + new * (1 - e^(N))
+ *
+ * - old * e^n + new * (1 - e^n)
+ */
 unsigned long
 calc_load_n(unsigned long load, unsigned long exp,
         unsigned long active, unsigned int n)
@@ -203,9 +227,33 @@ calc_load_n(unsigned long load, unsigned long exp,
  *
  * When making the ILB scale, we should try to pull this in as well.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - 이전 task개수(running + uninterruptible)와 현재 task개수의 변화값.
+ *   사용되면 0으로 초기화된다.
+ */
 static atomic_long_t calc_load_nohz[2];
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - calc_load_nohz의 lock
+ */
 static int calc_load_idx;
 
+/*
+ * IAMROOT, 2022.12.03:
+ *                 0s            5s            10s           15s
+ *                   +10           +10           +10           +10
+ *                 |-|-----------|-|-----------|-|-----------|-|
+ *             r:0 0 1           1 0           0 1           1 0
+ *             w:0 1 1           0 0           1 1           0 0
+ *                   ^             ^             ^             ^
+ * calc_load_idx   0 1             2             3             4
+ *
+ * - idx == 0 이였던경우 reader는 idx == 0을 계속 읽을것이고
+ *   writer는 idx = 1에 write를한다. write를 다했으면 idx++ 하여
+ *   reader가 완전히 write된 idx = 1에 접근할수있게 할것이다.
+ */
 static inline int calc_load_write_idx(void)
 {
     int idx = calc_load_idx;
@@ -226,11 +274,19 @@ static inline int calc_load_write_idx(void)
     return idx & 1;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - calc_global_nohz()에 의해 증가된 calc_load_idx의 홀/짝여부를 가져온다.
+ */
 static inline int calc_load_read_idx(void)
 {
     return calc_load_idx & 1;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - task개수 변동이 생겼으면 변동값을 calc_load_nohz에 저장한다.
+ */
 static void calc_load_nohz_fold(struct rq *rq)
 {
     long delta;
@@ -243,6 +299,11 @@ static void calc_load_nohz_fold(struct rq *rq)
     }
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - nohz가 시작될시 진입한다.
+ *   task개수 변화를 감지하여 calc_load_nohz에 갱신한다.
+ */
 void calc_load_nohz_start(void)
 {
     /*
@@ -281,11 +342,23 @@ void calc_load_nohz_stop(void)
         this_rq->calc_load_update += LOAD_FREQ;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - calc_load_idx의 홀짝에 따른 delta값을 가져온다. 없다면 return 0.
+ */
 static long calc_load_nohz_read(void)
 {
+/*
+ * IAMROOT, 2022.12.03:
+ * - idx는 0 or 1
+ */
     int idx = calc_load_read_idx();
     long delta = 0;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - read를 해서 0이 아니라면 어떤 값(delta)이 있다는것. 0와 xchg를 하여 가져와서 return한다.
+ */
     if (atomic_long_read(&calc_load_nohz[idx]))
         delta = atomic_long_xchg(&calc_load_nohz[idx], 0);
 
@@ -301,11 +374,38 @@ static long calc_load_nohz_read(void)
  * Once we've updated the global active value, we need to apply the exponential
  * weights adjusted to the number of cycles missed.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   NO_HZ는 calc_load_fold_active()를 호출하는 모든 CPU당 틱을 놓치게 할 수 있지만,
+ *   NO_HZ CPU는 calc_load_nohz_start()마다 델타를 calc_load_nohz로 접기 때문에 NO_HZ 기간이
+ *   로드 사이클을 넘으면 보류 중인 NO_HZ 델타를 접기만 하면 됩니다. 경계.
+ *
+ *   전역 활성 값을 업데이트한 후에는 놓친 주기 수에 맞게 조정된 지수 가중치를 적용해야
+ *   합니다.
+ *
+ * - nohz구간이 존재한다면 해당구간의 시간을 보정해준다.
+ * - calc_load_idx를 증가시켜 write가 완료됫음을 알린다.
+ */
 static void calc_global_nohz(void)
 {
     unsigned long sample_window;
     long delta, active, n;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - calc_global_load()에서 이함수를 진입한경우 calc_global_load가 old에서 LOAD_FREQ만큼
+ *   증가됫을것이다. 증가 됬음에도 불구하고 현재시간 + 10보다 이전이라면 calc_load를 다시
+ *   수행한다.
+ * - 결국 sleep으로 인해서 고려가 안된 시간만큼 n회를 더 수행하기 위함
+ *
+ * - ex)
+ *   |    sleep  |   sleep  | wakeup |
+ *   ^last갱신                       ^new갱신
+ *               ^miss      ^miss
+ *   miss가 2번 발생했다.
+ *   new갱신은 calc_global_load()에서 했지만 2번을 못해줬다. 2번에 대해서 여기서 처리한다.
+ */
     sample_window = READ_ONCE(calc_load_update);
     if (!time_before(jiffies, sample_window + 10)) {
         /*
@@ -317,6 +417,10 @@ static void calc_global_nohz(void)
         active = atomic_long_read(&calc_load_tasks);
         active = active > 0 ? active * FIXED_1 : 0;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - n회를 구하여 n만큼 load를 구한다.
+ */
         avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
         avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
         avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
@@ -331,6 +435,13 @@ static void calc_global_nohz(void)
      * calc_load_write_idx() will see the new time when it reads the new
      * index, this avoids a double flip messing things up.
      */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   NO_HZ 인덱스 뒤집기...
+ *   먼저 새 시간을 쓴 다음 색인을 뒤집어 calc_load_write_idx()가 새 색인을 읽을 때 새 시간을
+ *   볼 수 있도록 해야 합니다. 이렇게 하면 이중 뒤집기가 일을 망치는 것을 방지할 수 있습니다.
+ */
     smp_wmb();
     calc_load_idx++;
 }
@@ -347,11 +458,22 @@ static inline void calc_global_nohz(void) { }
  *
  * Called from the global timer code.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - sample_window이후의 시간(5초마다)일때 avenrun, load를 갱신한다.
+ *   또한 nohz 구간이 있었을경우 해당 구간을 고려한다.
+ */
 void calc_global_load(void)
 {
     unsigned long sample_window;
     long active, delta;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - sample_window + 10 전이라면 return.
+ * - 10의 의미.
+ *   task들이 동작을할때 calc_load_tasks를 갱신해줘야되는데 이 시간을 조금 고려한거 같다.
+ */
     sample_window = READ_ONCE(calc_load_update);
     if (time_before(jiffies, sample_window + 10))
         return;
@@ -360,16 +482,41 @@ void calc_global_load(void)
      * Fold the 'old' NO_HZ-delta to include all NO_HZ CPUs.
      */
     delta = calc_load_nohz_read();
+/*
+ * IAMROOT, 2022.12.03:
+ * - nohz때 계산된 delta값을 calc_load_tasks에 더해준다.
+ */
     if (delta)
         atomic_long_add(delta, &calc_load_tasks);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - active는 task숫자라고 생각하면된다.
+ */
     active = atomic_long_read(&calc_load_tasks);
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - active * 2048
+ */
     active = active > 0 ? active * FIXED_1 : 0;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - /proc/loadavg
+ *   ex) 1.33 0.63 0.40 1/712 40301
+ *       ^0   ^1   ^2
+ *      1분  5분  15분
+ */
     avenrun[0] = calc_load(avenrun[0], EXP_1, active);
     avenrun[1] = calc_load(avenrun[1], EXP_5, active);
     avenrun[2] = calc_load(avenrun[2], EXP_15, active);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 이전 update시각 + LOAD_FREQ(5초 + 1tck)이후로 next update시각을 정한다.
+ *   최종적으로 next update시각은 sample_window + LOAD_FREQ + 10tick이 될것이다.
+ */
     WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);
 
     /*
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 9ca6673d3eef..2c2ee32f540e 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1123,6 +1123,11 @@ struct rq {
 
     /* calc_load related fields */
     unsigned long        calc_load_update;
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - runing + nr_uninterruptible. calc_load_fold_active() 참고
+ */
     long            calc_load_active;
 
 #ifdef CONFIG_SCHED_HRTICK
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 61eb67d4fd16..561503f35243 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -135,6 +135,10 @@ u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
 }
 EXPORT_SYMBOL_GPL(clockevent_delta2ns);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - @state에따라 필요한 callback 함수를 실행한다.
+ */
 static int __clockevents_switch_state(struct clock_event_device *dev,
                       enum clock_event_state state)
 {
@@ -191,6 +195,10 @@ static int __clockevents_switch_state(struct clock_event_device *dev,
  *
  * Must be called with interrupts disabled !
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - @state에 따른 callback을 수행하고 @dev의 state을 @state로 변경한다.
+ */
 void clockevents_switch_state(struct clock_event_device *dev,
                   enum clock_event_state state)
 {
@@ -316,12 +324,22 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
  *
  * Returns 0 on success, -ETIME when the retry loop failed.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - @set_next_event callback을 실행한다.
+ */
 static int clockevents_program_min_delta(struct clock_event_device *dev)
 {
     unsigned long long clc;
     int64_t delta = 0;
     int i;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - retry 10.
+ *   programming이 불가능할 정도로 term이 짧은경우가 있을수있기 때문에 조금씩 늘려서
+ *   재시도를 한다. 즉 최대 min_delta_ns * 10이후에 실행될수도 있게 된다.
+ */
     for (i = 0; i < 10; i++) {
         delta += dev->min_delta_ns;
         dev->next_event = ktime_add_ns(ktime_get(), delta);
@@ -330,6 +348,10 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
             return 0;
 
         dev->retries++;
+/*
+ * IAMROOT, 2022.12.03:
+ * - mult shift로 ns -> cycle화 한다.
+ */
         clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
         if (dev->set_next_event((unsigned long) clc, dev) == 0)
             return 0;
@@ -347,6 +369,10 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
  *
  * Returns 0 on success, -ETIME when the event is in the past.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - exipires시간으로 program한다.
+ */
 int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
                   bool force)
 {
@@ -367,19 +393,42 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
           clockevent_get_state(dev));
 
     /* Shortcut for clockevent devices that can deal with ktime. */
+/*
+ * IAMROOT, 2022.12.03:
+ * - ktime으로 timer로 설정이가능한경우.
+ */
     if (dev->features & CLOCK_EVT_FEAT_KTIME)
         return dev->set_next_ktime(expires, dev);
 
     delta = ktime_to_ns(ktime_sub(expires, ktime_get()));
+/*
+ * IAMROOT, 2022.12.03:
+ * - 이전시간이면 force가 있는경우에 한해서만 시도한다.
+ */
     if (delta <= 0)
         return force ? clockevents_program_min_delta(dev) : -ETIME;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 요청한 expires값을 clamp하여 program을 시도한다.
+ */
     delta = min(delta, (int64_t) dev->max_delta_ns);
     delta = max(delta, (int64_t) dev->min_delta_ns);
 
     clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - prgram 시도.
+ */
     rc = dev->set_next_event((unsigned long) clc, dev);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - rc != 0 실패.
+ *   force가 있다면 가능한한 시도해야되므로 clockevents_program_min_delta()를 수행한다.
+ *   그게 아니거나(rc == 0) 성공했으면 return rc.
+ */
     return (rc && force) ? clockevents_program_min_delta(dev) : rc;
 }
 
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index ba19d7aaa26a..08cad711bf91 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -946,6 +946,10 @@ static void retrigger_next_event(void *arg);
 /*
  * Switch to high resolution mode
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer로 전환.
+ */
 static void hrtimer_switch_to_hres(void)
 {
     struct hrtimer_cpu_base *base = this_cpu_ptr(&hrtimer_bases);
@@ -955,6 +959,11 @@ static void hrtimer_switch_to_hres(void)
             base->cpu);
         return;
     }
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer로 설정에 성공.
+ */
     base->hres_active = 1;
     hrtimer_resolution = HIGH_RES_NSEC;
 
@@ -982,6 +991,19 @@ static inline void hrtimer_switch_to_hres(void) { }
  * are optimized out it vanishes as well, i.e. no need for lots of
  * #ifdeffery.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   Retrigger 다음 이벤트는 SMP 함수 호출을 통해 또는 낮은 수준의 재개
+ *   코드에서 직접 인터럽트가 비활성화된 상태에서 시계가 설정된 후 호출됩니다.
+ *
+ *   다음과 같은 경우에만 호출됩니다.
+ *   - CONFIG_HIGH_RES_TIMERS가 활성화되었습니다.
+ *   - CONFIG_NOHZ_COMMON이 활성화됨
+ *
+ *   다른 경우에는 이 함수가 비어 있고 호출 사이트가 최적화되었기 때문에
+ *   사라집니다. 즉, 많은 #ifdeffery가 필요하지 않습니다.
+ */
 static void retrigger_next_event(void *arg)
 {
     struct hrtimer_cpu_base *base = this_cpu_ptr(&hrtimer_bases);
@@ -1000,6 +1022,21 @@ static void retrigger_next_event(void *arg)
      * function call will take care of the reprogramming in case the
      * CPU was in a NOHZ idle sleep.
      */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   고해상도 모드 또는 nohz가 활성화되면 CLOCK_REALTIME/TAI/BOOTTIME의
+ *   오프셋을 업데이트해야 합니다. 그렇지 않으면 다음 틱이 처리합니다.
+ *
+ *   고해상도 모드가 활성화되면 다음 만료 타이머를 재평가해야 하며
+ *   필요한 경우 클록 이벤트 장치를 다시 프로그래밍해야 합니다. 
+ *
+ *   NOHZ의 경우 오프셋 업데이트 및 다음 만료 타이머의 재평가로 충분합니다.
+ *   SMP 함수 호출로부터의 반환은 CPU가 NOHZ 유휴 수면 상태인 경우 재프로그래밍을 처리합니다.
+ *
+ * - hres mode active or nohz active가 되면 clock의 offset을 update 및
+ *   reprogram을 한다.
+ */
     if (!__hrtimer_hres_active(base) && !tick_nohz_active)
         return;
 
@@ -2500,6 +2537,13 @@ static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h)
  * High resolution timer interrupt
  * Called with interrupts disabled
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - schedule tick
+ *   hrtimer가 활성화된후 timer interrupt가 이함수로 진입해서
+ *   schedule tick에 대한것은 tick_sched_timer가 호출된다.
+ *   그 전까지는 tick_handle_periodic으로 진입한다.
+ */
 void hrtimer_interrupt(struct clock_event_device *dev)
 {
     struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
@@ -2613,12 +2657,22 @@ static inline void __hrtimer_peek_ahead_timers(void) { }
 /*
  * Called from run_local_timers in hardirq context every jiffy
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - periodic tick에서 hrtimer가 아직 활성화안될경우 hrtimer를 직접 가동한다.
+ *   hrtimer switch가 가능한 상태가 되면 switch를 수행하고, 이미 hrtimer가
+ *   전환됬으면 아무도일도 안할것이다.
+ */
 void hrtimer_run_queues(void)
 {
     struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
     unsigned long flags;
     ktime_t now;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer가 이미동작 하고있으므로 return.
+ */
     if (__hrtimer_hres_active(cpu_base))
         return;
 
@@ -2629,17 +2683,38 @@ void hrtimer_run_queues(void)
      * there only sets the check bit in the tick_oneshot code,
      * otherwise we might deadlock vs. xtime_lock.
      */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   This _is_ ugly: highres 및/또는 nohz 모드로 전환할 수 있는지 주기적으로 확인해야 합니다.
+ *   clocksource 스위치는 xtime_lock이 유지된 상태에서 발생합니다. 그곳으로부터의 알림은
+ *   tick_oneshot 코드의 확인 비트만 설정합니다. 그렇지 않으면 xtime_lock과 교착
+ *   상태에 빠질 수 있습니다.*
+ */
     if (tick_check_oneshot_change(!hrtimer_is_hres_enabled())) {
+/*
+ * IAMROOT, 2022.12.03:
+ * - hres전환. 
+ */
         hrtimer_switch_to_hres();
         return;
     }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer로 아직전환이 안된경우 아래 로직이 동작한다.
+ *   hrtimer의 invoke 함수를 호출한다.
+ */
     raw_spin_lock_irqsave(&cpu_base->lock, flags);
     now = hrtimer_update_base(cpu_base);
 
     if (!ktime_before(now, cpu_base->softirq_expires_next)) {
         cpu_base->softirq_expires_next = KTIME_MAX;
         cpu_base->softirq_activated = 1;
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer 동작.
+ */
         raise_softirq_irqoff(HRTIMER_SOFTIRQ);
     }
 
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 2d7dfe856c66..6968e2e2a1d7 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1361,6 +1361,11 @@ static void handle_posix_cpu_timers(struct task_struct *tsk)
  * already updated our counts.  We need to check if any timers fire now.
  * Interrupts are disabled.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - PASS
+ *   user task의 수행시간을 누적 or timer 하기 위한용도.
+ */
 void run_posix_cpu_timers(void)
 {
     struct task_struct *tsk = current;
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index f7fe6fe36173..4b943cf5cd91 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -159,6 +159,10 @@ static bool tick_set_oneshot_wakeup_device(struct clock_event_device *newdev,
 /*
  * Conditionally install/replace broadcast device
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - broadcast 인경우에만 동작한다.
+ */
 void tick_install_broadcast_device(struct clock_event_device *dev, int cpu)
 {
     struct clock_event_device *cur = tick_broadcast_device.evtdev;
@@ -1063,6 +1067,11 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 /*
  * Select oneshot operating mode for the broadcast device
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - broadcast 설정을 한다. 설정만 할뿐 고성능 arm계열에서는
+ *   거의 사용하지 않는다. 
+ */
 void tick_broadcast_switch_to_oneshot(void)
 {
     struct clock_event_device *bc;
@@ -1071,6 +1080,10 @@ void tick_broadcast_switch_to_oneshot(void)
     raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
     tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
+/*
+ * IAMROOT, 2022.12.03:
+ * - 설정되있는경우에만 setup.
+ */
     bc = tick_broadcast_device.evtdev;
     if (bc)
         tick_broadcast_setup_oneshot(bc);
@@ -1123,6 +1136,10 @@ int tick_broadcast_oneshot_active(void)
 /*
  * Check whether the broadcast device supports oneshot.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - CLOCK_EVT_FEAT_ONESHOT 이 있는지 확인.
+ */
 bool tick_broadcast_oneshot_available(void)
 {
     struct clock_event_device *bc = tick_broadcast_device.evtdev;
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 4d3756a801d3..4c76c1475e60 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -35,6 +35,14 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  * CPU which handles the tick and protected by jiffies_lock. There is
  * no requirement to write hold the jiffies seqcount for it.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   다음 이벤트 선택: 틱 시간을 추적합니다. 틱을 처리하는 CPU에 의해 업데이트되고
+ *   jiffies_lock에 의해 보호됩니다. 그것에 대한 jiffies seqcount를 보류할 필요는 없습니다.
+ *
+ * - 1tick이 더해진 next period를 저장해놓는다.
+ */
 ktime_t tick_next_period;
 
 /*
@@ -51,6 +59,21 @@ ktime_t tick_next_period;
  *    at it will take over and keep the time keeping alive.  The handover
  *    procedure also covers cpu hotplug.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   tick_do_timer_cpu는 do_timer() 호출을 담당하는 CPU NR을 보유하는 타이머 코어 내부
+ *   변수입니다. 이 변수에는 두 가지 기능이 있습니다.
+ *
+ *   1) 시간 기록 잠금을 한 번에 모두 잡으려고 시도하는 수많은 CPU의 천둥 무리 문제를
+ *   방지합니다. 업데이트를 수행하도록 할당된 CPU만 업데이트를 처리합니다.
+ *
+ *   2) 값을 TICK_DO_TIMER_NONE(즉, 존재하지 않는 CPU)으로 설정하여 NOHZ 유휴 상태에서 작업을
+ *   해제합니다. 따라서 그것을 보는 다음 CPU가 시간을 이어받아 계속 살아있게 합니다. 핸드오버
+ *   절차에는 CPU 핫플러그도 포함됩니다.
+ *
+ * - 시간 갱신을 하는 cpu가 저장된다. 결정되기 전에는 TICK_DO_TIMER_BOOT가 저장되있다.
+ */
 int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
 #ifdef CONFIG_NO_HZ_FULL
 /*
@@ -72,12 +95,23 @@ struct tick_device *tick_get_device(int cpu)
 /**
  * tick_is_oneshot_available - check for a oneshot capable event device
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - oneshot이 enable되있는지 확인한다.
+ */
 int tick_is_oneshot_available(void)
 {
     struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
 
     if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT))
         return 0;
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - clock 절전기능이 없으면 return 1.
+ *   이 기능이 없는경우 전원을 아에 껏다가 켜야되는데, 짧은 시간을 껏다 켜야되는경우
+ *   성능이 오히려 느려져 시스템에 영향이 있다.
+ */
     if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
         return 1;
     return tick_broadcast_oneshot_available();
@@ -86,13 +120,25 @@ int tick_is_oneshot_available(void)
 /*
  * Periodic tick
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - periodic tick 작업 수행.
+ */
 static void tick_periodic(int cpu)
 {
+/*
+ * IAMROOT, 2022.12.03:
+ * - @cpu가 jiffies을 계산하는 cpu가 맞다면 시간갱신을한다.
+ */
     if (tick_do_timer_cpu == cpu) {
         raw_spin_lock(&jiffies_lock);
         write_seqcount_begin(&jiffies_seq);
 
         /* Keep track of the next tick event */
+/*
+ * IAMROOT, 2022.12.03:
+ * - +1 tick
+ */
         tick_next_period = ktime_add_ns(tick_next_period, TICK_NSEC);
 
         do_timer(1);
@@ -108,6 +154,13 @@ static void tick_periodic(int cpu)
 /*
  * Event handler for periodic ticks
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - event_handler에 등록되서 사용된다. timer interrupt
+ *   hrtimer가 활성화 되기 전에 timer interrupt가 이 함수로 진입한다.
+ * - schedule tick의 경우
+ *   활성화가 된후에는 hrtimer_interrupt를 통해서 tick_sched_timer가 호출된다.
+ */
 void tick_handle_periodic(struct clock_event_device *dev)
 {
     int cpu = smp_processor_id();
@@ -206,6 +259,10 @@ static void tick_take_do_timer_from_boot(void)
 /*
  * Setup the tick device
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - 최초의 진입이라면(tick device setup) @cpu를 tick_do_timer_cpu로 정한다.
+ */
 static void tick_setup_device(struct tick_device *td,
                   struct clock_event_device *newdev, int cpu,
                   const struct cpumask *cpumask)
@@ -221,6 +278,10 @@ static void tick_setup_device(struct tick_device *td,
          * If no cpu took the do_timer update, assign it to
          * this cpu:
          */
+/*
+ * IAMROOT, 2022.12.03:
+ * - @cpu로 tick_next_period를 정한다.
+ */
         if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
             tick_do_timer_cpu = cpu;
 
@@ -344,7 +405,7 @@ bool tick_check_replacement(struct clock_event_device *curdev,
  */
 /*
  * IAMROOT, 2022.08.27:
- * - TODO
+ * - @newdev를 검사하여 tick_do_timer_cpu등을 결정한다.
  */
 void tick_check_new_device(struct clock_event_device *newdev)
 {
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 3a6176519ba3..c5dc3d24f583 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -138,6 +138,11 @@ extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - oneshot이 가능한지 확인.
+ */
 static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
 #endif /* !(BROADCAST && ONESHOT) */
 
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
index 475ecceda768..7e1c407adf1a 100644
--- a/kernel/time/tick-oneshot.c
+++ b/kernel/time/tick-oneshot.c
@@ -20,6 +20,18 @@
 /**
  * tick_program_event
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - @expire == KTIME_MAX
+ *   stop
+ * - tick_cpu_device가 stop상태였다면.
+ *   oneshot mode로 변경후 program.
+ * - @expires로 program한다.
+ *
+ * - @force == 1인 경우
+ *   expires가 현재시각 이전이여도 prgram을 시도하고,
+ *   program을 실패해도 min_delta_ns * 10의 시간까지 최대 10번을 재시도한다.
+ */
 int tick_program_event(ktime_t expires, int force)
 {
     struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
@@ -70,6 +82,10 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
 /**
  * tick_switch_to_oneshot - switch to oneshot mode
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - oneshot 모드로 동작되면 return 0
+ */
 int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
 {
     struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
@@ -121,6 +137,10 @@ int tick_oneshot_mode_active(void)
  *
  * Called with interrupts disabled.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer_interrupt oneshot event_handler를 사용한다.
+ */
 int tick_init_highres(void)
 {
     return tick_switch_to_oneshot(hrtimer_interrupt);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 6bffe5af8cb1..14bf9c3bc4e8 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -49,11 +49,24 @@ struct tick_sched *tick_get_tick_sched(int cpu)
  * jiffies_lock and jiffies_seq. tick_nohz_next_event() needs to get a
  * consistent view of jiffies and last_jiffies_update.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   마지막 jiffy 업데이트가 발생한 시간입니다. 쓰기 액세스는 jiffies_lock 및 jiffies_seq를
+ *   보유해야 합니다. tick_nohz_next_event()는 jiffies 및 last_jiffies_update의 일관된 보기를
+ *   가져와야 합니다.
+ */
 static ktime_t last_jiffies_update;
 
 /*
  * Must be called with interrupts disabled !
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - @now를 기준으로 jiffies_64를 갱신한다.
+ * - tick_next_period는 acquire-release barrier를 통해서 동기화를 한다.
+ *   jiffies_64는 spinlock + seqlock으로 동기화한다.
+ */
 static void tick_do_update_jiffies64(ktime_t now)
 {
     unsigned long ticks = 1;
@@ -68,6 +81,19 @@ static void tick_do_update_jiffies64(ktime_t now)
      * consists of two 32bit stores and the first store could move it
      * to a random point in the future.
      */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   64비트는 jiffies 잠금을 유지하지 않고 시퀀스 카운트를 보지 않고
+ *   빠른 검사를 수행할 수 있습니다. smp_load_acquire()는 이 함수에서
+ *   나중에 수행되는 업데이트와 쌍을 이룹니다.
+ *
+ *   tick_next_period의 저장소는 두 개의 32비트 저장소로 구성되어 있고
+ *   첫 번째 저장소는 향후 임의의 지점으로 이동할 수 있기 때문에
+ *   32비트는 그렇게 할 수 없습니다.
+ *
+ * - smp_store_release와 쌍으로 barrier.
+ */
     if (IS_ENABLED(CONFIG_64BIT)) {
         if (ktime_before(now, smp_load_acquire(&tick_next_period)))
             return;
@@ -101,6 +127,11 @@ static void tick_do_update_jiffies64(ktime_t now)
     write_seqcount_begin(&jiffies_seq);
 
     delta = ktime_sub(now, tick_next_period);
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - TICK_NSEC보다 많이 지났으면 단위개수만큼 ticks를 더 고려해준다.
+ */
     if (unlikely(delta >= TICK_NSEC)) {
         /* Slow path for long idle sleep times */
         s64 incr = TICK_NSEC;
@@ -115,6 +146,10 @@ static void tick_do_update_jiffies64(ktime_t now)
     }
 
     /* Advance jiffies to complete the jiffies_seq protected job */
+/*
+ * IAMROOT, 2022.12.03:
+ * - 계산된 ticks을 더해준다.
+ */
     jiffies_64 += ticks;
 
     /*
@@ -129,6 +164,13 @@ static void tick_do_update_jiffies64(ktime_t now)
          * not reordered vs. the store to tick_next_period, neither
          * by the compiler nor by the CPU.
          */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   위의 잠금 없는 빠른 검사에서 smp_load_acquire()와 쌍을 이루고
+ *   jiffies_64에 대한 업데이트가 컴파일러나 CPU에 의해 tick_next_period에
+ *   대한 저장에 대해 재정렬되지 않도록 합니다.
+ */
         smp_store_release(&tick_next_period, nextp);
     } else {
         /*
@@ -145,6 +187,10 @@ static void tick_do_update_jiffies64(ktime_t now)
      */
     write_seqcount_end(&jiffies_seq);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - jiffies_64가 변경됬으므로 global load계산을 재수행한다.
+ */
     calc_global_load();
 
     raw_spin_unlock(&jiffies_lock);
@@ -154,6 +200,10 @@ static void tick_do_update_jiffies64(ktime_t now)
 /*
  * Initialize and return retrieve the jiffies update.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - lock을 통해서 last_jiffies_update를 가져온다.
+ */
 static ktime_t tick_init_jiffy_update(void)
 {
     ktime_t period;
@@ -161,6 +211,10 @@ static ktime_t tick_init_jiffy_update(void)
     raw_spin_lock(&jiffies_lock);
     write_seqcount_begin(&jiffies_seq);
     /* Did we start the jiffies update yet ? */
+/*
+ * IAMROOT, 2022.12.03:
+ * - 업데이트한적이 없는경우 tick_next_period로 last_jiffies_update를 갱신한다.
+ */
     if (last_jiffies_update == 0)
         last_jiffies_update = tick_next_period;
     period = last_jiffies_update;
@@ -169,6 +223,10 @@ static ktime_t tick_init_jiffy_update(void)
     return period;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - jiffies update
+ */
 static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
 {
     int cpu = smp_processor_id();
@@ -184,6 +242,20 @@ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
      * If nohz_full is enabled, this should not happen because the
      * tick_do_timer_cpu never relinquishes.
      */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   do_timer duty가 drop되었는지 확인합니다. 우리는 동시성에 대해
+ *   신경 쓰지 않습니다. 이것은 담당 CPU가 긴 수면에 들어간
+ *   경우에만 발생합니다. 두 개의 CPU가 이 작업에 자신을 할당하는
+ *   경우 jiffies 업데이트는 여전히 jiffies_lock에 의해 직렬화됩니다.
+ *
+ *   nohz_full이 활성화된 경우 tick_do_timer_cpu가 절대 포기하지 않기
+ *   때문에 이런 일이 발생하지 않아야 합니다.
+ *
+ * - 동시성에 신경쓰지 않아 경쟁상황인 경우도 있다. 별로 상관없지만
+ *   검사는 수행한다.
+ */
     if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE)) {
 #ifdef CONFIG_NO_HZ_FULL
         WARN_ON(tick_nohz_full_running);
@@ -200,6 +272,11 @@ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
         ts->got_idle_tick = 1;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - update_process_times수행
+ *   (tick이 증가하면서 수행해야될 작업들)
+ */
 static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
 {
 #ifdef CONFIG_NO_HZ_COMMON
@@ -211,6 +288,14 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
      * idle" jiffy stamp so the idle accounting adjustment we do
      * when we go busy again does not account too much ticks.
      */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   idle 상태이고 틱이 중지되면 정말 오랜 시간 동안 일정을 잡지 않을 수 있으므로
+ *   워치독을 터치해야 합니다. 이것은 로그인 프롬프트를 기다리는 동안 완전한 idle
+ *   SMP 시스템에서 발생합니다. 또한 idle jiffy 스탬프의 시작을 증가시켜 다시 바쁠
+ *   때 수행하는 idle accounting 조정이 너무 많은 틱을 고려하지 않도록 합니다.
+ */
     if (ts->tick_stopped) {
         touch_softlockup_watchdog_sched();
         if (is_idle_task(current))
@@ -220,6 +305,12 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
          * expiration, make sure we don't bypass the next clock reprogramming
          * to the same deadline.
          */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   현재 틱이 예상 만료 시간보다 너무 일찍 실행되는 경우 동일한 데드라인으로
+ *   재프로그래밍되는 다음 클록을 우회하지 않도록 합니다.
+ */
         ts->next_tick = 0;
     }
 #endif
@@ -572,6 +663,10 @@ void __init tick_nohz_init(void)
 /*
  * NO HZ enabled ?
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - nohz= 로 설정한다. default true.
+ */
 bool tick_nohz_enabled __read_mostly  = true;
 unsigned long tick_nohz_active  __read_mostly;
 /*
@@ -1327,12 +1422,21 @@ static void tick_nohz_handler(struct clock_event_device *dev)
     tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - @mode를 nohz_mode로 설정한다. schedule에 nohz enable을 예약한다.
+ */
 static inline void tick_nohz_activate(struct tick_sched *ts, int mode)
 {
     if (!tick_nohz_enabled)
         return;
     ts->nohz_mode = mode;
     /* One update is enough */
+/*
+ * IAMROOT, 2022.12.03:
+ * - active == 0인 경우 bit0 set을 하면서 timers_update_nohz()를 수행한다.
+ *   즉 최초에 수행.
+ */
     if (!test_and_set_bit(0, &tick_nohz_active))
         timers_update_nohz();
 }
@@ -1340,6 +1444,10 @@ static inline void tick_nohz_activate(struct tick_sched *ts, int mode)
 /**
  * tick_nohz_switch_to_nohz - switch to nohz mode
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - nohz로 switch한다. schedule동작할때 nohz가 active되도록 예약한다.
+ */
 static void tick_nohz_switch_to_nohz(void)
 {
     struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
@@ -1348,6 +1456,10 @@ static void tick_nohz_switch_to_nohz(void)
     if (!tick_nohz_enabled)
         return;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - oneshot이 아니면 경우 return.
+ */
     if (tick_switch_to_oneshot(tick_nohz_handler))
         return;
 
@@ -1360,6 +1472,10 @@ static void tick_nohz_switch_to_nohz(void)
     next = tick_init_jiffy_update();
 
     hrtimer_set_expires(&ts->sched_timer, next);
+/*
+ * IAMROOT, 2022.12.03:
+ * - hrtimer최초 시작. 1tick 시작.
+ */
     hrtimer_forward_now(&ts->sched_timer, TICK_NSEC);
     tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
     tick_nohz_activate(ts, NOHZ_MODE_LOWRES);
@@ -1404,6 +1520,10 @@ void tick_irq_enter(void)
  * We rearm the timer until we get disabled by the idle code.
  * Called with interrupts disabled.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - jiffies갱신 및 tick 작업 수행 및 hrtimer tick 생성.
+ */
 static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
 {
     struct tick_sched *ts =
@@ -1423,14 +1543,28 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
         ts->next_tick = 0;
 
     /* No need to reprogram if we are in idle or full dynticks mode */
+
+/*
+ * IAMROOT, 2022.12.03:
+ * - stop상태인 경우 여기서 return.
+ */
     if (unlikely(ts->tick_stopped))
         return HRTIMER_NORESTART;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - tick 생성.
+ */
     hrtimer_forward(timer, now, TICK_NSEC);
 
     return HRTIMER_RESTART;
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 0 or 1
+ *   TICK / 2 의 시간을 cpu개수로 나눠서 어긋나게 schedule을 수행한다.
+ */
 static int sched_skew_tick;
 
 static int __init skew_tick(char *str)
@@ -1444,6 +1578,11 @@ early_param("skew_tick", skew_tick);
 /**
  * tick_setup_sched_timer - setup the tick emulation timer
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - sched timer를 tick_sched_timer로 설정한다.
+ *   nohz를 NOHZ_MODE_HIGHRES로 설정한다.(arm계열이 자주사용한다)
+ */
 void tick_setup_sched_timer(void)
 {
     struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
@@ -1459,6 +1598,11 @@ void tick_setup_sched_timer(void)
     hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update());
 
     /* Offset the tick to avert jiffies_lock contention. */
+/*
+ * IAMROOT, 2022.12.03:
+ * - sched_skew_tick option이 켜져있으면 반틱을 cpu개수로 나눠서 어긋나게 schedule이
+ *   수행하도록 보정한다.
+ */
     if (sched_skew_tick) {
         u64 offset = TICK_NSEC >> 1;
         do_div(offset, num_possible_cpus());
@@ -1466,6 +1610,10 @@ void tick_setup_sched_timer(void)
         hrtimer_add_expires_ns(&ts->sched_timer, offset);
     }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - 실제 hrtimer 첫 틱 생성 시작.
+ */
     hrtimer_forward(&ts->sched_timer, now, TICK_NSEC);
     hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS_PINNED_HARD);
     tick_nohz_activate(ts, NOHZ_MODE_HIGHRES);
@@ -1515,16 +1663,42 @@ void tick_oneshot_notify(void)
  * mode, because high resolution timers are disabled (either compile
  * or runtime). Called with interrupts disabled.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - papago
+ *   원샷이 가능한 변화가 있는지 확인합니다.
+ *
+ *   hrtimer softirq(타이머 softirq에 의해 구동됨) allow_nohz 신호에서 주기적으로
+ *   호출되며 고해상도 타이머가 비활성화되기 때문에(컴파일 또는 런타임) 저해상도
+ *   nohz 모드로 전환할 수 있습니다. 인터럽트가 비활성화된 상태에서 호출됩니다.
+ *
+ * - oneshot nohz enable.
+ *   return 0. 이미되있거나 switch 성공.
+ *   return 1. 수행안함.
+ */
 int tick_check_oneshot_change(int allow_nohz)
 {
     struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - clocksource가 바뀌지 않았으면 return.
+ */
     if (!test_and_clear_bit(0, &ts->check_clocks))
         return 0;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - NOHZ_MODE_HIGHRES 인경우 return.
+ *   inactive만 아니면 이미 전환됬다고 판단한다.
+ */
     if (ts->nohz_mode != NOHZ_MODE_INACTIVE)
         return 0;
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - hres가 아니거나 oneshot이 안켜져있으면 return.
+ */
     if (!timekeeping_valid_for_hres() || !tick_is_oneshot_available())
         return 0;
 
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index a55105afa33c..18f3548776b9 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1538,6 +1538,10 @@ EXPORT_SYMBOL(ktime_get_raw_ts64);
 /**
  * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - CLOCK_SOURCE_VALID_FOR_HRES가 set되있는지 확인.
+ */
 int timekeeping_valid_for_hres(void)
 {
     struct timekeeper *tk = &tk_core.timekeeper;
@@ -2228,6 +2232,10 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - TODO
+ */
 void update_wall_time(void)
 {
     if (timekeeping_advance(TK_ADV_TICK))
@@ -2288,6 +2296,11 @@ EXPORT_SYMBOL(ktime_get_coarse_ts64);
 /*
  * Must hold jiffies_lock
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - jiffies_64에 ticks증가.
+ *   cpu global load.
+ */
 void do_timer(unsigned long ticks)
 {
     jiffies_64 += ticks;
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 142e2cbee7ab..b5881e761d2f 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -295,6 +295,12 @@ static void timer_update_keys(struct work_struct *work)
     mutex_unlock(&timer_keys_mutex);
 }
 
+/*
+ * IAMROOT, 2022.12.03:
+ * - timers_nohz_active,timers_migration_enabled enable.
+ *   schedule이 동작하고나서부터 돌라는 사전 예약의 의미가 있다.
+ *   (schedule이 동작안하고 있을때에는 nohz가 필요없기때문)
+ */
 void timers_update_nohz(void)
 {
     schedule_work(&timer_update_work);
@@ -2349,12 +2355,22 @@ static __latent_entropy void run_timer_softirq(struct softirq_action *h)
 /*
  * Called by the local, per-CPU timer interrupt on SMP.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - expiry time을 확인하여 lowres timer를 동작시킨다.
+ *   hrtimer가 아직 활성화가 안된경우 hrtimer까지 수행한다.
+ */
 static void run_local_timers(void)
 {
     struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
 
     hrtimer_run_queues();
     /* Raise the softirq only if required. */
+/*
+ * IAMROOT, 2022.12.03:
+ * - expiry 시간 전이면 return.
+ *   nohz가 켜져있으면 deferred 까지 검사한다.
+ */
     if (time_before(jiffies, base->next_expiry)) {
         if (!IS_ENABLED(CONFIG_NO_HZ_COMMON))
             return;
@@ -2363,6 +2379,10 @@ static void run_local_timers(void)
         if (time_before(jiffies, base->next_expiry))
             return;
     }
+/*
+ * IAMROOT, 2022.12.03:
+ * - lowres timer 동작.
+ */
     raise_softirq(TIMER_SOFTIRQ);
 }
 
@@ -2370,6 +2390,14 @@ static void run_local_timers(void)
  * Called from the timer interrupt handler to charge one tick to the current
  * process.  user_tick is 1 if the tick is user time, 0 for system.
  */
+/*
+ * IAMROOT, 2022.12.03:
+ * - user상태인경우 @user_tick == 1.
+ *   kernel인경우 @user_tick == 0
+ *
+ * - tick이 update될시 수행할 모든일을 수행한다.
+ *   수행하는 일이 많으므로 내부 api각각 참조.
+ */
 void update_process_times(int user_tick)
 {
     struct task_struct *p = current;
 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 623
185 [커널 18차] 93주차 kkr 2023.03.04 53
184 [커널 18차] 91주차 kkr 2023.02.18 95
183 [커널 19차] 39 주차 Min 2023.02.18 53
182 [커널 18차] 90주차 kkr 2023.02.13 63
181 [커널 19차] 38 주차 Min 2023.02.11 45
180 [커널 19차] 37 주차 Min 2023.02.04 478
179 [커널 19차] 36 주차 Min 2023.01.28 85
178 [커널 18차] 88주차 kkr 2023.01.28 55
177 [커널 19차] 35 주차 Min 2023.01.14 93
176 [커널 17차] 120 ~ 121주차 ㅇㅇㅇ 2023.01.08 110
175 [커널 18차] 85주차 kkr 2023.01.07 53
174 [커널 19차] 34 주차 Min 2023.01.07 42
173 [커널 18차] 84주차 kkr 2022.12.31 104
172 [커널 19차] 33 주차 Min 2022.12.31 51
171 [커널 17차] 117 ~ 119주차 ㅇㅇㅇ 2022.12.25 61
170 [커널 19차] 31 주차 Min 2022.12.17 63
169 [커널 19차] 30 주차 Min 2022.12.10 61
168 [커널 17차] 112 ~ 116주차 ㅇㅇㅇ 2022.12.05 72
» [커널 18차] 80주차 kkr 2022.12.03 156
166 [커널 19차] 28 ~ 29 주차 Min 2022.12.03 35
XE Login