[커널 18차] 67주차

2022.09.03 22:24

kkr 조회 수:138

lowres timer 진행.

추석연휴 휴식

 

git : https://github.com/iamroot18/5.10/commit/441edf6ccc4b22fe3cccf9606ae30444f1317b1d

 

diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h
index e83f0982b99c..658a198a17a9 100644
--- a/arch/arm64/include/asm/preempt.h
+++ b/arch/arm64/include/asm/preempt.h
@@ -7,6 +7,10 @@
 #define PREEMPT_NEED_RESCHED    BIT(32)
 #define PREEMPT_ENABLED    (PREEMPT_NEED_RESCHED)
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - preempt count를 가져온다.
+ */
 static inline int preempt_count(void)
 {
     return READ_ONCE(current_thread_info()->preempt.count);
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 4ade2757d06d..aac88978ccb7 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -949,6 +949,16 @@ static void arch_timer_configure_evtstream(void)
  * - evt_stream_div = arch_timer_rate / 2000
  *   arch_timer_rate = 19.2M이라고 했을대
  *   evt_stream_div = 19200000 / 2000 = 9600
+ * - ex) x us마다 evt 발생.
+ *   1us 마다
+ *   arch_timerr_rate / 1000_000
+ *   10us 마다
+ *   arch_timerr_rate / 100_000
+ *   100us 마다
+ *   arch_timerr_rate / 10_000
+ *   1000us 마다
+ *   arch_timerr_rate / 1_000
+ *
  */
     evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ / 2;
 
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 1f22a30c0963..7fbf8a85c90a 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -515,6 +515,10 @@ DECLARE_STATIC_KEY_FALSE(force_irqthreads_key);
 enum
 {
     HI_SOFTIRQ=0,
+/*
+ * IAMROOT, 2022.09.03:
+ * - softirq bottom half
+ */
     TIMER_SOFTIRQ,
     NET_TX_SOFTIRQ,
     NET_RX_SOFTIRQ,
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 5d85ffb15800..4810e7d317f1 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -108,16 +108,60 @@ static inline u64 get_jiffies_64(void)
  * good compiler would generate better code (and a really good compiler
  * wouldn't care). Gcc is currently neither.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - return true가 되는 상황.
+ *
+ * i) A, B둘다 값이 작을때.
+ *
+ *           signed long
+ *    B A          |                 
+ *   --------------|-----------
+ *   
+ *
+ * ii) A, B둘다 값이 클때(signed long값 over가 안됬을때)
+ *
+ *           signed long
+ *                 |       B A                 
+ *   --------------|-----------
+ *    
+ * iii) A가 unsigned log값을 over flow
+ *
+ *           signed long
+ *    A            |         B                 
+ *   --------------|-----------
+ */
 #define time_after(a,b)        \
     (typecheck(unsigned long, a) && \
      typecheck(unsigned long, b) && \
      ((long)((b) - (a)) < 0))
+
+/*
+ * IAMROOT, 2022.09.03:
+ * -
+ *         A   B
+ * time ----------->
+ * return true.
+ *
+ * - if (a < b)
+ *    return true;
+ *   return false;
+ */
 #define time_before(a,b)    time_after(b,a)
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - a가 b시각 이후이거나 같으면 true.
+ */
 #define time_after_eq(a,b)    \
     (typecheck(unsigned long, a) && \
      typecheck(unsigned long, b) && \
      ((long)((a) - (b)) >= 0))
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - a가 b시각 이전이거나 같으면 true.
+ */
 #define time_before_eq(a,b)    time_after_eq(b,a)
 
 /*
diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h
index cc9f393e2a70..47f9167a04af 100644
--- a/include/linux/sched/isolation.h
+++ b/include/linux/sched/isolation.h
@@ -17,6 +17,11 @@ enum hk_flags {
     HK_FLAG_KTHREAD        = (1 << 8),
 };
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - ex) kernel param : nohz_full=4-7
+ *   4~7번 cpu를 nohz_full로 사용할수 있게 한다.
+ */
 #ifdef CONFIG_CPU_ISOLATION
 DECLARE_STATIC_KEY_FALSE(housekeeping_overridden);
 extern int housekeeping_any_cpu(enum hk_flags flags);
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index f56d89e358c5..3f1e1ac65fb8 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -291,6 +291,10 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
 
 #endif
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - irq disable후 spin lock수행.
+ */
 #define raw_spin_lock_irq(lock)        _raw_spin_lock_irq(lock)
 #define raw_spin_lock_bh(lock)        _raw_spin_lock_bh(lock)
 #define raw_spin_unlock(lock)        _raw_spin_unlock(lock)
diff --git a/include/linux/timer.h b/include/linux/timer.h
index fda13c9d1256..d25907404a50 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -16,6 +16,13 @@ struct timer_list {
     struct hlist_node    entry;
     unsigned long        expires;
     void            (*function)(struct timer_list *);
+/*
+ * IAMROOT, 2022.09.03:
+ * - TIMER_BASEMASK 참고.
+ *   cpu id(TIMER_CPUMASK. 18bits)와 같이 field를 사용한다.
+ *   ex)
+ *   timer->flags = flags | raw_smp_processor_id();
+ */
     u32            flags;
 
 #ifdef CONFIG_LOCKDEP
@@ -61,6 +68,33 @@ struct timer_list {
  * should be placed on a particular CPU, then add_timer_on() has to be
  * used.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   @TIMER_DEFERRABLE: 지연 가능한 타이머는 시스템이 사용 중일 때 정상적으로
+ *   작동하지만 CPU를 서비스하기 위해 유휴 상태에서 벗어나게 하지는 않습니다.
+ *   대신, CPU가 나중에 지연되지 않는 타이머로 깨어날 때 타이머가 서비스됩니다. 
+ *
+ *   @TIMER_IRQSAFE: irqsafe 타이머는 IRQ가 비활성화된 상태에서 실행되며, 예를 들어
+ *   del_timer_sync()를 호출하여 IRQ 처리기에서 실행 중인 인스턴스가 완료될 때까지
+ *   기다리는 것이 안전합니다.
+ *
+ *   Note: irq 비활성화된 콜백 실행은 작업 대기열 잠금 문제의 특별한 경우입니다.
+ *   인터럽트가 비활성화된 상태에서 무작위 쓰레기를 실행하기 위한 것이 아닙니다.
+ *   학대가 모니터링됩니다!
+ *
+ *   @TIMER_PINNED: 고정된 타이머는 타이머 배치 휴리스틱(예: NOHZ)의 영향을 받지 
+ *   않으며 타이머가 대기열에 추가된 CPU에서 항상 만료됩니다.
+ *
+ *  Note: 타이머를 대기열에 넣으면 한 CPU에서 다른 CPU로 타이머를 마이그레이션할
+ *  수 있으므로 고정된 타이머가 처음에 선택한 CPU에 유지된다는 보장은 없습니다.
+ *  enqueue 기능이 mod_timer() 또는 add_timer()를 통해 호출되는 CPU로 이동합니다.
+ *  타이머를 특정 CPU에 배치해야 하는 경우 add_timer_on()을 사용해야 합니다.
+ *
+ *  - field
+ *  | 10bits    | 4bits   | 18bits |
+ *  | timer idx | flags   | cpu id |
+ */
 #define TIMER_CPUMASK        0x0003FFFF
 #define TIMER_MIGRATING        0x00040000
 #define TIMER_BASEMASK        (TIMER_CPUMASK | TIMER_MIGRATING)
@@ -73,6 +107,10 @@ struct timer_list {
 
 #define TIMER_TRACE_FLAGMASK    (TIMER_MIGRATING | TIMER_DEFERRABLE | TIMER_PINNED | TIMER_IRQSAFE)
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - compile time시 timer 초기화.
+ */
 #define __TIMER_INITIALIZER(_function, _flags) {        \
         .entry = { .next = TIMER_ENTRY_STATIC },    \
         .function = (_function),            \
@@ -81,6 +119,11 @@ struct timer_list {
             __FILE__ ":" __stringify(__LINE__))    \
     }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - compile time시 timer 초기화.
+ * - runtime시는 timer_setup
+ */
 #define DEFINE_TIMER(_name, _function)                \
     struct timer_list _name =                \
         __TIMER_INITIALIZER(_function, 0)
@@ -122,6 +165,10 @@ static inline void init_timer_on_stack_key(struct timer_list *timer,
                     #_timer, &__key);         \
     } while (0)
 #else
+/*
+ * IAMROOT, 2022.09.03:
+ * - @_timer를 초기화한다.
+ */
 #define __init_timer(_timer, _fn, _flags)                \
     init_timer_key((_timer), (_fn), (_flags), NULL, NULL)
 #define __init_timer_on_stack(_timer, _fn, _flags)            \
@@ -138,6 +185,11 @@ static inline void init_timer_on_stack_key(struct timer_list *timer,
  * or timer_setup(). For timers on the stack, timer_setup_on_stack() must
  * be used and must be balanced with a call to destroy_timer_on_stack().
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - runtime시 timer초기화.
+ *   실제 timer 등록은 add_timer를 수행해야한다.
+ */
 #define timer_setup(timer, callback, flags)            \
     __init_timer((timer), (callback), (flags))
 
@@ -163,6 +215,13 @@ static inline void destroy_timer_on_stack(struct timer_list *timer) { }
  *
  * return value: 1 if the timer is pending, 0 if not.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * @return value 1 if the timer is pending, 0 if not.
+ * - @timer가 wheel에 등록이 되있는지 안되있는지 확인한다.
+ * - list의 pprev가 있다면 등록이 되있다는 의미.
+ *   없다면 expire가 됬거나 등록이 안 됬다는 의미.
+ */
 static inline int timer_pending(const struct timer_list * timer)
 {
     return !hlist_unhashed_lockless(&timer->entry);
@@ -178,6 +237,10 @@ extern int timer_reduce(struct timer_list *timer, unsigned long expires);
  * The jiffies value which is added to now, when there is no timer
  * in the timer wheel:
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - 2^30 - 1 
+ */
 #define NEXT_TIMER_MAX_DELTA    ((1UL << 30) - 1)
 
 extern void add_timer(struct timer_list *timer);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f21714ea3db8..6f176718435c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1003,20 +1003,49 @@ void resched_cpu(int cpu)
  * selecting an idle CPU will add more delays to the timers than intended
  * (as that CPU's timer base may not be uptodate wrt jiffies etc).
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papgo
+ *   semi idle 상태의 경우 유휴 CPU에서 타이머를 마이그레이션하기 위해 가장 가까운
+ *   사용 중인 CPU를 사용합니다. 절전에 좋습니다.
+ *
+ *   우리는 완전히 idle 상태인 시스템에 대해 유사한 최적화를 수행하지 않습니다.
+ *  idle CPU를 선택하면 타이머에 의도한 것보다 더 많은 지연이 추가되기
+ *  때문입니다(해당 CPU의 타이머 기반이 wrt jiffies 등으로 업데이트되지 않을 수
+ *  있음).
+ *
+ * - busy cpu를 찾는다.
+ */
 int get_nohz_timer_target(void)
 {
     int i, cpu = smp_processor_id(), default_cpu = -1;
     struct sched_domain *sd;
     const struct cpumask *hk_mask;
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - housekeeping이 가능한 cpu인지 확인(동작해도 되는 cpu인지 확인)
+ */
     if (housekeeping_cpu(cpu, HK_FLAG_TIMER)) {
+/*
+ * IAMROOT, 2022.09.03:
+ * - busy이면 return.
+ */
         if (!idle_cpu(cpu))
             return cpu;
+/*
+ * IAMROOT, 2022.09.03:
+ * - 현재 cpu가 idle이면 idle이 아닌것을 찾으러간다.
+ */
         default_cpu = cpu;
     }
 
     hk_mask = housekeeping_cpumask(HK_FLAG_TIMER);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 가장 가까운 domain. 인접한 cpu에서 busy cpu를 찾아온다.
+ */
     rcu_read_lock();
     for_each_domain(cpu, sd) {
         for_each_cpu_and(i, sched_domain_span(sd), hk_mask) {
@@ -1030,6 +1059,11 @@ int get_nohz_timer_target(void)
         }
     }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - idle이 아닌걸 못 찾고, 현재 cpu가 housekeeping이 아니였다면 hosekeeping중에
+ *   any cpu로 고른다.
+ */
     if (default_cpu == -1)
         default_cpu = housekeeping_any_cpu(HK_FLAG_TIMER);
     cpu = default_cpu;
@@ -1086,6 +1120,14 @@ static bool wake_up_full_nohz_cpu(int cpu)
  * caller's responsibility to deal with the lost wakeup, for example,
  * by hooking into the CPU_DEAD notifier like timers and hrtimers do.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   지정된 CPU를 깨우십시오. CPU가 오프라인 상태가 되면 호출자의 책임은 타이머
+ *   및 hrtimers와 같이 CPU_DEAD 알리미에 연결하는 것과 같이 손실된 웨이크업을
+ *   처리하는 것입니다.
+ * -
+ */
 void wake_up_nohz_cpu(int cpu)
 {
     if (!wake_up_full_nohz_cpu(cpu))
@@ -6990,6 +7032,12 @@ int task_prio(const struct task_struct *p)
  *
  * Return: 1 if the CPU is currently idle. 0 otherwise.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * @return 1 idle
+ *         0 run
+ * - 현재 idle인지 아닌지 판별한다.
+ */
 int idle_cpu(int cpu)
 {
     struct rq *rq = cpu_rq(cpu);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 3d3e5793e117..8c5291801ce8 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1736,6 +1736,10 @@ queue_balance_callback(struct rq *rq,
  * The domain tree of any CPU may only be accessed from within
  * preempt-disabled sections.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - tree 구조로 되있다. sched domain 위로 올라간다.
+ */
 #define for_each_domain(cpu, __sd) \
     for (__sd = rcu_dereference_check_sched_domain(cpu_rq(cpu)->sd); \
             __sd; __sd = __sd->parent)
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 322b65d45676..a12dbf8ca8bd 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -683,6 +683,10 @@ inline void raise_softirq_irqoff(unsigned int nr)
         wakeup_softirqd();
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @nr번의 softirq 처리요청.
+ */
 void raise_softirq(unsigned int nr)
 {
     unsigned long flags;
@@ -699,6 +703,10 @@ void __raise_softirq_irqoff(unsigned int nr)
     or_softirq_pending(1UL << nr);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - softirq @nr에 대한 @action함수를 등록한다.
+ */
 void open_softirq(int nr, void (*action)(struct softirq_action *))
 {
     softirq_vec[nr].action = action;
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 643d412ac623..2d7dfe856c66 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1153,6 +1153,11 @@ static inline bool fastpath_timer_check(struct task_struct *tsk)
 static void handle_posix_cpu_timers(struct task_struct *tsk);
 
 #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - posix timer 초기화.(application timer)
+ */
 static void posix_cpu_timers_work(struct callback_head *work)
 {
     handle_posix_cpu_timers(current);
@@ -1162,6 +1167,11 @@ static void posix_cpu_timers_work(struct callback_head *work)
  * Initialize posix CPU timers task work in init task. Out of line to
  * keep the callback static and to avoid header recursion hell.
  */
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - posix timer 초기화.(application timer)
+ */
 void __init posix_cputimers_init_work(void)
 {
     init_task_work(&current->posix_cputimers_work.work,
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 3a68f23b6786..142e2cbee7ab 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -157,6 +157,21 @@ EXPORT_SYMBOL(jiffies_64);
 #define LVL_CLK_DIV    (1UL << LVL_CLK_SHIFT)
 #define LVL_CLK_MASK    (LVL_CLK_DIV - 1)
 #define LVL_SHIFT(n)    ((n) * LVL_CLK_SHIFT)
+
+/*
+ * IAMROOT, 2022.09.03:
+ * ex) 1000hz 기준.
+ * n    LVL_SHIFT(n)  LVL_GRAN(n)
+ * 0    0 * 3 = 0     1 << 0   = 1
+ * 1    1 * 3 = 3     1 << 3   = 8
+ * 2    2 * 3 = 6     1 << 6   = 64
+ * 3    3 * 3 = 9     1 << 9   = 512
+ * 4    4 * 3 = 12    1 << 12  = 4096
+ * 5    5 * 3 = 15    1 << 15  = 32768
+ * 6    6 * 3 = 18    1 << 18  = 262144
+ * 7    7 * 3 = 21    1 << 21  = 2097152
+ * 8    8 * 3 = 24    1 << 24  = 16777216
+ */
 #define LVL_GRAN(n)    (1UL << LVL_SHIFT(n))
 
 /*
@@ -164,6 +179,24 @@ EXPORT_SYMBOL(jiffies_64);
  * time. We start from the last possible delta of the previous level
  * so that we can later add an extra LVL_GRAN(n) to n (see calc_index()).
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   대기열에 넣을 때 버킷을 선택하기 위한 각 레벨의 시간 시작 값입니다. 이전
+ *   레벨의 마지막 가능한 델타에서 시작하여 나중에 LVL_GRAN(n)을 n에 추가할 수
+ *   있습니다(calc_index() 참조).
+ *
+ * n  (((n) - 1) * LVL_CLK_SHIFT) LEVL_START(n)    
+ * 1  0                           0b111111 << 0 
+ * 2  3                           0b111111 << 3    
+ * 3  6                           0b111111 << 6
+ * 4  9                           0b111111 << 9
+ * 5  12                          0b111111 << 12
+ * 6  15                          0b111111 << 15
+ * 7  18                          0b111111 << 18
+ * 8  21                          0b111111 << 21
+ *
+ */
 #define LVL_START(n)    ((LVL_SIZE - 1) << (((n) - 1) * LVL_CLK_SHIFT))
 
 /* Size of each clock level */
@@ -187,11 +220,23 @@ EXPORT_SYMBOL(jiffies_64);
  * The resulting wheel size. If NOHZ is configured we allocate two
  * wheels so we have a separate storage for the deferrable timers.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - LVL_DEPTH == 9
+ *   2^6 * 9 = 576
+ *
+ * - LVL_DEPTH == 8
+ *   2^6 * 8 = 512
+ */
 #define WHEEL_SIZE    (LVL_SIZE * LVL_DEPTH)
 
 #ifdef CONFIG_NO_HZ_COMMON
 # define NR_BASES    2
 # define BASE_STD    0
+/*
+ * IAMROOT, 2022.09.03:
+ * - NOHZ용 (deffered 가능한).
+ */
 # define BASE_DEF    1
 #else
 # define NR_BASES    1
@@ -478,12 +523,19 @@ unsigned long round_jiffies_up_relative(unsigned long j)
 }
 EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
 
-
+/*
+ * IAMROOT, 2022.09.03:
+ * - flags로부터 timer가 위치한 vector idx를 가져온다.
+ */
 static inline unsigned int timer_get_idx(struct timer_list *timer)
 {
     return (timer->flags & TIMER_ARRAYMASK) >> TIMER_ARRAYSHIFT;
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - flags에 timer vector @idx를 set한다.
+ */
 static inline void timer_set_idx(struct timer_list *timer, unsigned int idx)
 {
     timer->flags = (timer->flags & ~TIMER_ARRAYMASK) |
@@ -494,6 +546,71 @@ static inline void timer_set_idx(struct timer_list *timer, unsigned int idx)
  * Helper function to calculate the array index for a given expiry
  * time.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - Git blame
+ *
+ *   timers: Use only bucket expiry for base->next_expiry value
+ *
+ *   The bucket expiry time is the effective expriy time of timers and is
+ *   greater than or equal to the requested timer expiry time. This is due
+ *   to the guarantee that timers never expire early and the reduced expiry
+ *   granularity in the secondary wheel levels.
+ *
+ *   When a timer is enqueued, trigger_dyntick_cpu() checks whether the
+ *   timer is the new first timer. This check compares next_expiry with
+ *   the requested timer expiry value and not with the effective expiry
+ *   value of the bucket into which the timer was queued.
+ *
+ *   Storing the requested timer expiry value in base->next_expiry can lead
+ *   to base->clk going backwards if the requested timer expiry value is
+ *   smaller than base->clk. Commit 30c66fc30ee7 ("timer: Prevent base->clk
+ *   from moving backward") worked around this by preventing the store when
+ *   timer->expiry is before base->clk, but did not fix the underlying
+ *   problem.
+ *
+ *   Use the expiry value of the bucket into which the timer is queued to
+ *   do the new first timer check. This fixes the base->clk going backward
+ *   problem.
+ *
+ *   The workaround of commit 30c66fc30ee7 ("timer: Prevent base->clk from
+ *   moving backward") in trigger_dyntick_cpu() is not longer necessary as the
+ *   timers bucket expiry is guaranteed to be greater than or equal base->clk.
+ *
+ * - papago
+ *   timers: base->next_expiry 값에 대해 버킷 만료만 사용합니다.
+ *
+ *   버킷 만료 시간은 타이머의 유효 만료 시간이며 요청된 타이머 만료 시간보다
+ *   크거나 같습니다. 이는 타이머가 일찍 만료되지 않는다는 보장과 보조 휠 레벨의
+ *   만료 세분성 감소 때문입니다.
+ *
+ *   타이머가 대기열에 추가되면 trigger_dyntick_cpu()는 타이머가 새로운 첫 번째
+ *   타이머인지 확인합니다. 이 검사는 next_expiry를 요청된 타이머 만료 값과
+ *   비교하며 타이머가 대기열에 포함된 버킷의 유효 만료 값과 비교하지 않습니다. 
+ *
+ *   요청된 타이머 만료 값을 base->next_expiry에 저장하면 요청된 타이머 만료 값이
+ *   base->clk보다 작은 경우 base->clk가 뒤로 이동할 수 있습니다. 커밋 
+ *   30c66fc30ee7("타이머: 기본->clk가 뒤로 이동하는 것을 방지")은 timer->expire가
+ *   기본->clk 이전일 때 저장소를 방지하여 이 문제를 해결했지만 근본적인 문제는
+ *   수정하지 않았습니다.
+ *
+ *   타이머가 대기 중인 버킷의 만료 값을 사용하여 새로운 첫 번째 타이머 확인을
+ *   수행합니다. 이것은 base->clk가 거꾸로 가는 문제를 수정합니다.
+ *
+ *   trigger_dyntick_cpu()의 커밋 30c66fc30ee7("타이머: 기본->clk가 뒤로 이동하는
+ *   것을 방지")의 해결 방법은 타이머 버킷 만료가 base->clk보다 크거나 같도록
+ *   보장되므로 더 이상 필요하지 않습니다.
+ *
+ * @bucket_expiry LVL_GRAN(lvl) 단위로 올림.
+ * ex) exipres = 0x43dd, lvl = 2일때 return, bucket_expiry
+ * expires_new = (0x43dd + LVL_GRAN(2)) >> LVL_SHIFT(2)
+ *             = (0x43dd + 0x40) >> 6 = 0x441d >> 6
+ *             = 0x110
+ * bucket_expiry = 0x110 << 6
+ *               = 0x4400 = 17408
+ * return  = LVL_OFFS(2) + (0x110 & 0x3f)
+ *         = 0x80 + 0x10 = 0x90
+ */
 static inline unsigned calc_index(unsigned long expires, unsigned lvl,
                   unsigned long *bucket_expiry)
 {
@@ -511,12 +628,30 @@ static inline unsigned calc_index(unsigned long expires, unsigned lvl,
     return LVL_OFFS(lvl) + (expires & LVL_MASK);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * @clk base->clk
+ * wheel idx를 구한다.
+ *
+ * ex) clk = 2, expires = 67
+ * delta = 65 -> calc_index(expires, 1, bucket_expiry) 호출
+ *
+ * expires_new = (67 + 8) >> 3 = 9
+ * bucket_expiry = 9 << 3 = 72
+ * return = 64 + (9 & 0x3f) = 73
+ *
+ * bucket_expiry = 72, idx = 73
+ */
 static int calc_wheel_index(unsigned long expires, unsigned long clk,
                 unsigned long *bucket_expiry)
 {
     unsigned long delta = expires - clk;
     unsigned int idx;
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - delta가 들어갈 idx를 찾는다.
+ */
     if (delta < LVL_START(1)) {
         idx = calc_index(expires, 0, bucket_expiry);
     } else if (delta < LVL_START(2)) {
@@ -532,11 +667,24 @@ static int calc_wheel_index(unsigned long expires, unsigned long clk,
     } else if (delta < LVL_START(7)) {
         idx = calc_index(expires, 6, bucket_expiry);
     } else if (LVL_DEPTH > 8 && delta < LVL_START(8)) {
+/*
+ * IAMROOT, 2022.09.03:
+ * - LVL_DEPTH가 9가 존재하면 lvl 7까지.(0 ~ 7)
+ *   LVL_DEPTH가 8까지라면 lvl 6까지만한다. (0 ~ 6)
+ */
         idx = calc_index(expires, 7, bucket_expiry);
     } else if ((long) delta < 0) {
+/*
+ * IAMROOT, 2022.09.03:
+ * - delta가 -면 lvl 0로 본다.
+ */
         idx = clk & LVL_MASK;
         *bucket_expiry = clk;
     } else {
+/*
+ * IAMROOT, 2022.09.03:
+ * - delta가 너무 큰상황. 마지막 값으로 fixup 한후 idx를 재계산한다.
+ */
         /*
          * Force expire obscene large timeouts to expire at the
          * capacity limit of the wheel.
@@ -549,6 +697,13 @@ static int calc_wheel_index(unsigned long expires, unsigned long clk,
     return idx;
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @base->cpu가 nohz로 동작중일때 깨운다.
+ *   1. 일반 timer인 경우 idle 상태면 깨운다.
+ *   2. defferable일경우 nohz full일 경우에만 깨운다.
+ *      nohz idle 상태일경우엔 그냥 빠져올것이다.
+ */
 static void
 trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
 {
@@ -559,6 +714,11 @@ trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
      * TODO: This wants some optimizing similar to the code below, but we
      * will do that when we switch from push to pull for deferrable timers.
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - deffered로 등록한 timer인 경우 deffer를 하지만, cpu가 nohz full인 상태라면
+ *   cpu를 wakeup.
+ */
     if (timer->flags & TIMER_DEFERRABLE) {
         if (tick_nohz_full_cpu(base->cpu))
             wake_up_nohz_cpu(base->cpu);
@@ -570,6 +730,14 @@ trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
      * timer is not deferrable. If the other CPU is on the way to idle
      * then it can't set base->is_idle as we hold the base lock:
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * -papago
+ *  베이스가 idle 상태이고 타이머를 연기할 수 없는 경우 원격 CPU를 IPI해야 할 수도
+ *  있습니다. 다른 CPU가 유휴 상태가 되면 기본 잠금을 유지하므로 base->is_idle을
+ *  설정할 수 없습니다. 
+ * - base->is_idle : base쪽 timer tick이 꺼져있다는뜻.
+ */
     if (base->is_idle)
         wake_up_nohz_cpu(base->cpu);
 }
@@ -579,6 +747,11 @@ trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
  * the bitmap, store the index in the timer flags then wake up
  * the target CPU if needed.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer를 idx에 add한다. cpu가 idle인 상태인경우 next_expiry가
+ *   갱신되는 상황에서 필요에 따라 cpu를 깨운다.
+ */
 static void enqueue_timer(struct timer_base *base, struct timer_list *timer,
               unsigned int idx, unsigned long bucket_expiry)
 {
@@ -594,6 +767,13 @@ static void enqueue_timer(struct timer_base *base, struct timer_list *timer,
      * effective expiry time of the timer is required here
      * (bucket_expiry) instead of timer->expires.
      */
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - bucket_expire가 timer_base보다 먼저라면 bucket_expiry로 갱신한다.
+ * - 기존에 있었던 next timer보다 새로 추가되는 timer의 bucket_expiry가
+ *   빠르면 bucket_expiry로 갱신하라는것이다.
+ */
     if (time_before(bucket_expiry, base->next_expiry)) {
         /*
          * Set the next expiry time and kick the CPU so it
@@ -606,6 +786,10 @@ static void enqueue_timer(struct timer_base *base, struct timer_list *timer,
     }
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - idx를 산출해서 enqueue 한다.
+ */
 static void internal_add_timer(struct timer_base *base, struct timer_list *timer)
 {
     unsigned long bucket_expiry;
@@ -788,6 +972,10 @@ static inline void debug_assert_init(struct timer_list *timer)
     debug_timer_assert_init(timer);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer를 초기화한다. 초기화시 함수를 실행한 cpu id를 flags에 기록한다.
+ */
 static void do_init_timer(struct timer_list *timer,
               void (*func)(struct timer_list *),
               unsigned int flags,
@@ -813,6 +1001,10 @@ static void do_init_timer(struct timer_list *timer,
  * init_timer_key() must be done to a timer prior calling *any* of the
  * other timer functions.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer를 초기화한다.
+ */
 void init_timer_key(struct timer_list *timer,
             void (*func)(struct timer_list *), unsigned int flags,
             const char *name, struct lock_class_key *key)
@@ -822,6 +1014,10 @@ void init_timer_key(struct timer_list *timer,
 }
 EXPORT_SYMBOL(init_timer_key);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 0timer를 detach 한다.
+ */
 static inline void detach_timer(struct timer_list *timer, bool clear_pending)
 {
     struct hlist_node *entry = &timer->entry;
@@ -834,14 +1030,27 @@ static inline void detach_timer(struct timer_list *timer, bool clear_pending)
     entry->next = LIST_POISON2;
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer를 @base로부터 분리를 시도한다.
+ */
 static int detach_if_pending(struct timer_list *timer, struct timer_base *base,
                  bool clear_pending)
 {
     unsigned idx = timer_get_idx(timer);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 이미 분리 되있다. 아무것도 안한다.
+ */
     if (!timer_pending(timer))
         return 0;
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @idx vector에 timer가 1개만 등록되있다면. pending_map을 clear한다.
+ *   최종적으로 한개를 분리해내면 idx에서 아무것도 없어지기 때문이다.
+ */
     if (hlist_is_singular_node(&timer->entry, base->vectors + idx)) {
         __clear_bit(idx, base->pending_map);
         base->next_expiry_recalc = true;
@@ -851,6 +1060,10 @@ static int detach_if_pending(struct timer_list *timer, struct timer_base *base,
     return 1;
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @cpu에 해당하는 timer_base를 가져온다.
+ */
 static inline struct timer_base *get_timer_cpu_base(u32 tflags, u32 cpu)
 {
     struct timer_base *base = per_cpu_ptr(&timer_bases[BASE_STD], cpu);
@@ -859,11 +1072,19 @@ static inline struct timer_base *get_timer_cpu_base(u32 tflags, u32 cpu)
      * If the timer is deferrable and NO_HZ_COMMON is set then we need
      * to use the deferrable base.
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - nohz enable이면서 deffered로 등록한 timer라면 nohz용 timer_base를 가져온다.
+ */
     if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && (tflags & TIMER_DEFERRABLE))
         base = per_cpu_ptr(&timer_bases[BASE_DEF], cpu);
     return base;
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 현재 cpu의 timer base를 가져온다.
+ */
 static inline struct timer_base *get_timer_this_cpu_base(u32 tflags)
 {
     struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
@@ -877,22 +1098,49 @@ static inline struct timer_base *get_timer_this_cpu_base(u32 tflags)
     return base;
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @tflags의 cpu로 timer_base를 가져온다.
+ */
 static inline struct timer_base *get_timer_base(u32 tflags)
 {
     return get_timer_cpu_base(tflags, tflags & TIMER_CPUMASK);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 1. busy cpu에서 timer base 얻어오기.
+ *   2. 현재 cpu로 timer base 얻어오기.
+ */
 static inline struct timer_base *
 get_target_base(struct timer_base *base, unsigned tflags)
 {
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
+/*
+ * IAMROOT, 2022.09.03:
+ * - migration이 가능하고, pinned를 해야된다는 flag가 없다면 busy cpu에서
+ *   timer_base를 가져온다.
+ *
+ */
     if (static_branch_likely(&timers_migration_enabled) &&
         !(tflags & TIMER_PINNED))
         return get_timer_cpu_base(tflags, get_nohz_timer_target());
 #endif
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - pinned요청이거나, migration을 못한다면 현재 cpu의 timer_base를 가져온다.
+ */
     return get_timer_this_cpu_base(tflags);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @base를 현재 시간 기준으로 udpate한다.
+ *
+ * - 기본적으로 @base->clk을 현재 시간으로 update를 한다.
+ *   만약 next_expiry가 현재 과거(ex. nohz)라면 base->clk으로 update한다.
+ */
 static inline void forward_timer_base(struct timer_base *base)
 {
     unsigned long jnow = READ_ONCE(jiffies);
@@ -902,6 +1150,10 @@ static inline void forward_timer_base(struct timer_base *base)
      * Also while executing timers, base->clk is 1 offset ahead
      * of jiffies to avoid endless requeuing to current jiffies.
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - 이미 timer start 시간이 지낫으면 return.
+ */
     if ((long)(jnow - base->clk) < 1)
         return;
 
@@ -909,11 +1161,47 @@ static inline void forward_timer_base(struct timer_base *base)
      * If the next expiry value is > jiffies, then we fast forward to
      * jiffies otherwise we forward to the next expiry value.
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - next_expiry가 현재시간 이후라면 현재시간을 base->clk에 등록.
+ *   그게 아니면 clk를 next_expiry로 등록.
+ */
     if (time_after(base->next_expiry, jnow)) {
+/*
+ * IAMROOT, 2022.09.03:
+ * - 매 tick마다 갱신된다.(normal case)
+ *                 now
+ * -----------------|-----------|-------
+ *                  |          next
+ *           update base->clk
+ */
         base->clk = jnow;
     } else {
+/*
+ * IAMROOT, 2022.09.03:
+ * - error 처리.
+ * - timer가 이미 지낫으면 return.
+ * - next_expiry가 base->clk이전 warn후 return.
+ *                          now
+ *                           |
+ * ---------|-------|--------|----------
+ *        next    base->clk    
+ */
         if (WARN_ON_ONCE(time_before(base->next_expiry, base->clk)))
             return;
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - nohz로 인해서 발생하는 상황.
+ * - base->clk <--> now사이에 sleep timer가 tick이 들어오지 않아서
+ *   갱신이 안됬을때.
+ *                               now
+ *                                |
+ * --------|------------|---------|---
+ *       base->clk    next        
+ *                      |
+ *                update base->clk
+ */
         base->clk = base->next_expiry;
     }
 }
@@ -930,6 +1218,10 @@ static inline void forward_timer_base(struct timer_base *base)
  * When a timer is migrating then the TIMER_MIGRATING flag is set and we need
  * to wait until the migration is done.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - @flags에 등록된 cpu의 timer base를 가져온다.
+ */
 static struct timer_base *lock_timer_base(struct timer_list *timer,
                       unsigned long *flags)
     __acquires(timer->base->lock)
@@ -945,8 +1237,23 @@ static struct timer_base *lock_timer_base(struct timer_list *timer,
          */
         tf = READ_ONCE(timer->flags);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - migrating 자체가 매우빠르기 때문에 for문으로 migrating이
+ *   풀릴때까지 적당히 기다린다.
+ * - migrating이 끝나면 기본적으로 cpu가 바뀐다.
+ */
         if (!(tf & TIMER_MIGRATING)) {
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer의 flag(tf)에 timer를 생성한 cpu nr이 등록되있어, 해당
+ *   cpu의 timer_base를 가져온다.
+ */
             base = get_timer_base(tf);
+/*
+ * IAMROOT, 2022.09.03:
+ * - tf가 같지 않으면 경쟁상황. loop를 계속돈다.
+ */
             raw_spin_lock_irqsave(&base->lock, *flags);
             if (timer->flags == tf)
                 return base;
@@ -960,6 +1267,10 @@ static struct timer_base *lock_timer_base(struct timer_list *timer,
 #define MOD_TIMER_REDUCE        0x02
 #define MOD_TIMER_NOTPENDING        0x04
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer를 추가하거나 expired를 변경한다.
+ */
 static inline int
 __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int options)
 {
@@ -975,16 +1286,45 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
      * the timer is re-modified to have the same timeout or ends up in the
      * same array bucket then just return:
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   이것은 네트워킹 코드에 의해 트리거되는 일반적인 최적화입니다. 타이머가 동일한
+ *   시간 초과를 갖도록 다시 수정되거나 동일한 어레이 버킷에서 끝나는 경우 다음을
+ *   반환합니다.
+ * - pending중인 timer이면서 option이
+ *   MOD_TIMER_PENDING_ONLY (mod_timer_pending())
+ *   MOD_TIMER_REDUCE       (timer_reduce()),
+ *   0                      (mod_timer())
+ *   경우 if문 동작.
+ *
+ * - 즉 add_timer()가 아닌 경우
+ */
     if (!(options & MOD_TIMER_NOTPENDING) && timer_pending(timer)) {
         /*
          * The downside of this optimization is that it can result in
          * larger granularity than you would get from adding a new
          * timer with this expiry.
          */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   이 최적화의 단점은 이 만료로 새 타이머를 추가하는 것보다 더 큰 세분성을
+ *   초래할 수 있다는 것입니다.
+ */
         long diff = timer->expires - expires;
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 갱신하는 expires시간이 기존과 같다면 아무것도 할필요없을것이다.
+ */
         if (!diff)
             return 1;
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - reduce일때 expire 시간을 더 증가시키는 경우는 무시한다.
+ */
         if (options & MOD_TIMER_REDUCE && diff <= 0)
             return 1;
 
@@ -994,9 +1334,22 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
          * just update the expiry time and avoid the whole
          * dequeue/enqueue dance.
          */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   여기에서 타이머 베이스를 잠그고 버킷 인덱스를 계산합니다. 타이머가
+ *   동일한 버킷에서 끝나면 만료 시간을 업데이트하고 전체 대기열에서
+ *   빼기/대기하기 댄스를 방지합니다.
+ *
+ * - lock을 건다.
+ */
         base = lock_timer_base(timer, &flags);
         forward_timer_base(base);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - reduce일때, @expires값이 기존보다 감소되지 않았으면 무시.
+ */
         if (timer_pending(timer) && (options & MOD_TIMER_REDUCE) &&
             time_before_eq(timer->expires, expires)) {
             ret = 1;
@@ -1011,6 +1364,14 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
          * timer. If it matches set the expiry to the new value so a
          * subsequent call will exit in the expires check above.
          */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   보류 중인 타이머의 배열 인덱스를 검색하고 비교합니다. 일치하는 경우 만료를
+ *   새 값으로 설정하여 위의 만료 확인에서 후속 호출이 종료되도록 합니다.
+ * - idx가 변한게 없는경우, expires만 재갱신한다.
+ *   reduce인 경우 전진만 허용한다.
+ */
         if (idx == timer_get_idx(timer)) {
             if (!(options & MOD_TIMER_REDUCE))
                 timer->expires = expires;
@@ -1020,16 +1381,34 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
             goto out_unlock;
         }
     } else {
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer의 cpu에 해당하는 timer base를 가져오고 update한다.
+ */
         base = lock_timer_base(timer, &flags);
         forward_timer_base(base);
     }
 
     ret = detach_if_pending(timer, base, false);
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - mod_timer_pending()으로 pending중인 timer에 한해서 수정 요청이 왔는데
+ *   이미 timer가 없는 상황. 종료한다.
+ */
     if (!ret && (options & MOD_TIMER_PENDING_ONLY))
         goto out_unlock;
 
     new_base = get_target_base(base, timer->flags);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer에서 사용하는 cpu와 변경되었는지 확인한다.
+ * - ex) cpu0에서 timer0를 add_timer했다고 가정.
+ *   cpu0 -> add_timer().   timer0가 cpu0번으로 등록
+ *   cpu1 -> mod_timer(timer0).
+ *   이런 상황일 경우 base != new_base가 된다.
+ */
     if (base != new_base) {
         /*
          * We are trying to schedule the timer on the new base.
@@ -1038,6 +1417,18 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
          * handler yet has not finished. This also guarantees that the
          * timer is serialized wrt itself.
          */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   new base에서 타이머를 예약하려고 합니다.,
+ *   그러나 타이머가 실행되는 동안에는 타이머의 기반을 변경할 수 없습니다.
+ *   그렇지 않으면 del_timer_sync()가 타이머의 핸들러가 아직 완료되지 않았음을
+ *   감지할 수 없습니다. 이것은 또한 타이머가 자체적으로 직렬화됨을 보장합니다.
+ *
+ * - running_timer : expired 되서 동작중인 timer.
+ * - running_timer와 현재 timer가 다를경우, 즉 동작중인 timer가 아닐경우.
+ *   new_base로 base를 갱신하고 timer의 cpu를 갱신된 new_base로 고친후 update.
+ */
         if (likely(base->running_timer != timer)) {
             /* See the comment in lock_timer_base() */
             timer->flags |= TIMER_MIGRATING;
@@ -1060,6 +1451,16 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
      * enqueue_timer() is required. Otherwise we need to (re)calculate
      * the wheel index via internal_add_timer().
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   'idx'가 위에서 계산되었고 기본 시간이 'idx' 계산과 기본 전환 사이에 진행되지
+ *   않은 경우 enqueue_timer()만 필요합니다. 그렇지 않으면 internal_add_timer()를
+ *   통해 휠 인덱스를 (재)계산해야 합니다.
+ *
+ * - 기존 timer가 존재하여 이미 idx를 알아온 경우 즉시. enqueue.
+ *   새로 들어온 timer인 경우 idx가 없으므로 idx를 새로 산출해서 enqueue한다.
+ */
     if (idx != UINT_MAX && clk == base->clk)
         enqueue_timer(base, timer, idx, bucket_expiry);
     else
@@ -1081,6 +1482,10 @@ __mod_timer(struct timer_list *timer, unsigned long expires, unsigned int option
  *
  * It is useful for unserialized use of timers.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer가 pending중일때, expires를 변경한다.
+ */
 int mod_timer_pending(struct timer_list *timer, unsigned long expires)
 {
     return __mod_timer(timer, expires, MOD_TIMER_PENDING_ONLY);
@@ -1107,6 +1512,25 @@ EXPORT_SYMBOL(mod_timer_pending);
  * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
  * active timer returns 1.)
  */
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   mod_timer()는 활성 타이머의 만료 필드를 업데이트하는 더 효율적인
+ *   방법입니다(타이머가 비활성화된 경우 활성화됨)
+ *
+ *   mod_timer(timer, expires)는 다음과 같습니다.
+ *
+ *     del_timer(timer); timer->expires = expires; add_timer(timer);
+ *
+ *   동일한 타이머의 직렬화되지 않은 동시 사용자가 여러 명 있는 경우
+ *   add_timer()가 이미 실행 중인 타이머를 수정할 수 없으므로
+ *   mod_timer()가 시간 초과를 수정하는 유일한 안전한 방법입니다.
+ *
+ *   함수는 보류 중인 타이머를 수정했는지 여부를 반환합니다.
+ *   (즉, 비활성 타이머의 mod_timer()는 0을 반환하고 활성 타이머의
+ *   mod_timer()는 1을 반환합니다.)
+ */
 int mod_timer(struct timer_list *timer, unsigned long expires)
 {
     return __mod_timer(timer, expires, 0);
@@ -1122,6 +1546,10 @@ EXPORT_SYMBOL(mod_timer);
  * modify a running timer if that would reduce the expiration time (it will
  * start a timer that isn't running).
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer가 pending중일때, expired를 줄인다.
+ */
 int timer_reduce(struct timer_list *timer, unsigned long expires)
 {
     return __mod_timer(timer, expires, MOD_TIMER_REDUCE);
@@ -1142,6 +1570,10 @@ EXPORT_SYMBOL(timer_reduce);
  * Timers with an ->expires field in the past will be executed in the next
  * timer tick.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer 등록.
+ */
 void add_timer(struct timer_list *timer)
 {
     BUG_ON(timer_pending(timer));
@@ -1199,6 +1631,10 @@ EXPORT_SYMBOL_GPL(add_timer_on);
  * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
  * active timer returns 1.)
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer가 pending중이라면 detach.
+ */
 int del_timer(struct timer_list *timer)
 {
     struct timer_base *base;
@@ -1224,6 +1660,12 @@ EXPORT_SYMBOL(del_timer);
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * @return -1. running중인 timer라면 삭제를 못한다는것.
+ *          1. 삭제 성공.
+ *          0. 이미 expire되서 없다.
+ */
 int try_to_del_timer_sync(struct timer_list *timer)
 {
     struct timer_base *base;
@@ -1244,16 +1686,30 @@ int try_to_del_timer_sync(struct timer_list *timer)
 EXPORT_SYMBOL(try_to_del_timer_sync);
 
 #ifdef CONFIG_PREEMPT_RT
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - spinlock을 사용한다.
+ */
 static __init void timer_base_init_expiry_lock(struct timer_base *base)
 {
     spin_lock_init(&base->expiry_lock);
 }
 
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - spin_lock
+ */
 static inline void timer_base_lock_expiry(struct timer_base *base)
 {
     spin_lock(&base->expiry_lock);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - spin_unlock
+ */
 static inline void timer_base_unlock_expiry(struct timer_base *base)
 {
     spin_unlock(&base->expiry_lock);
@@ -1266,10 +1722,26 @@ static inline void timer_base_unlock_expiry(struct timer_base *base)
  * timer callback to finish. Drop expiry_lock and reacquire it. That allows
  * the waiter to acquire the lock and make progress.
  */
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   del_timer_wait_running()의 대응물.
+ *
+ *   base->expiry_lock에 대한 웨이터가 있는 경우 타이머 콜백이 완료되기를 기다리고
+ *   있는 것입니다. expiry_lock을 삭제하고 다시 획득하십시오. 그러면 웨이터가
+ *   잠금을 획득하고 진행할 수 있습니다.
+ * - 
+ */
 static void timer_sync_wait_running(struct timer_base *base)
 {
     if (atomic_read(&base->timer_waiters)) {
         raw_spin_unlock_irq(&base->lock);
+/*
+ * IAMROOT, 2022.09.03:
+ * - del_timer_wait_running()에서 del wait를 하고 있는경우 deadlock풀어서
+ *   callback이 끝난걸 알려 delete가 가능하게 풀어준다.
+ */
         spin_unlock(&base->expiry_lock);
         spin_lock(&base->expiry_lock);
         raw_spin_lock_irq(&base->lock);
@@ -1286,6 +1758,18 @@ static void timer_sync_wait_running(struct timer_base *base)
  * delete a timer preempted the softirq thread running the timer callback
  * function.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   이 함수는 타이머 콜백 함수가 실행 중이기 때문에 타이머의 빠른 경로 삭제가
+ *   실패한 경우 PREEMPT_RT 커널에서 호출됩니다.
+ *
+ *   이것은 원격 CPU의 softirq 스레드가 선점된 경우 우선 순위 반전을 방지하고
+ *   타이머를 삭제하려는 작업이 타이머 콜백 기능을 실행하는 softirq 스레드를
+ *   선점할 때 생명 잠금을 방지합니다.
+ * - timer가 irqsafe가 아니라면 timer_waiters에 등록하고 deadlock을 걸어
+ *   callback이 끝날떄까지 기다린다.
+ */
 static void del_timer_wait_running(struct timer_list *timer)
 {
     u32 tf;
@@ -1303,6 +1787,11 @@ static void del_timer_wait_running(struct timer_list *timer)
          * causes another wait loop.
          */
         atomic_inc(&base->timer_waiters);
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer_sync_wait_running()의 spin_unlock을 deadlock을 걸어 기다린다.
+ */
         spin_lock_bh(&base->expiry_lock);
         atomic_dec(&base->timer_waiters);
         spin_unlock_bh(&base->expiry_lock);
@@ -1353,6 +1842,13 @@ static inline void del_timer_wait_running(struct timer_list *timer) { }
  *
  * The function returns whether it has deactivated a pending timer or not.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - @timer를 삭제한다.
+ *   1. pending중인 경우. 삭제후 return 0.
+ *   2. expire된 경우 별거 안하고 return 1.
+ *   3. running중인 경우 deadlock을 걸어 callback이 끝날때까지 wait.
+ */
 int del_timer_sync(struct timer_list *timer)
 {
     int ret;
@@ -1385,6 +1881,12 @@ int del_timer_sync(struct timer_list *timer)
     do {
         ret = try_to_del_timer_sync(timer);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - running중인 timer를 삭제하라는 요청이 왔다.
+ *   irqsave가 없는 timer인 경우 callback이 완료 될때까지
+ *   deadlock으로 기다리고, 그렇지 않을 경우 cpu_relax를 한번한후 while.
+ */
         if (unlikely(ret < 0)) {
             del_timer_wait_running(timer);
             cpu_relax();
@@ -1396,6 +1898,10 @@ int del_timer_sync(struct timer_list *timer)
 EXPORT_SYMBOL(del_timer_sync);
 #endif
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @fn callback 수행.
+ */
 static void call_timer_fn(struct timer_list *timer,
               void (*fn)(struct timer_list *),
               unsigned long baseclk)
@@ -1427,6 +1933,11 @@ static void call_timer_fn(struct timer_list *timer,
 
     lock_map_release(&lockdep_map);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @fn 안에서 preempt_enable/disable을 증감 하면 count가 증감하게된다.
+ *   이러면안된다.
+ */
     if (count != preempt_count()) {
         WARN_ONCE(1, "timer: %pS preempt leak: %08x -> %08x\n",
               fn, count, preempt_count());
@@ -1436,10 +1947,21 @@ static void call_timer_fn(struct timer_list *timer,
          * callback kept a lock held, bad luck, but not worse
          * than the BUG() we had.
          */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   선점 횟수를 복원합니다. 그것은 우리에게 생존하고 정보를 추출할 적절한 기회를
+ *   제공합니다. 콜백이 잠금을 유지했다면 운이 나빴지만 BUG()보다 나쁘지는
+ *   않았습니다.
+ */
         preempt_count_set(count);
     }
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @head에 있는 timer에 등록된 callback function을 호출한다.
+ */
 static void expire_timers(struct timer_base *base, struct hlist_head *head)
 {
     /*
@@ -1447,12 +1969,24 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
      * incremented directly before expire_timers was called. But expiry
      * is related to the old base->clk value.
      */
+/*
+ * IAMROOT, 2022.09.03:
+ * - papago
+ *   이 값은 추적에만 필요합니다. base->clk는 expire_timers가 호출되기 직전에
+ *   증분되었습니다. 그러나 만료는 이전 base->clk 값과 관련이 있습니다.
+ */
     unsigned long baseclk = base->clk - 1;
 
     while (!hlist_empty(head)) {
         struct timer_list *timer;
         void (*fn)(struct timer_list *);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 1. timer를 한개빼고
+ *   2. running에 넣은후
+ *   3. callback 함수 호출.
+ */
         timer = hlist_entry(head->first, struct timer_list, entry);
 
         base->running_timer = timer;
@@ -1460,12 +1994,21 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
 
         fn = timer->function;
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - timer가 irq safe라는 일반 spinlock, 그렇지 않은 경우 irq spinlock수행.
+ * - irq에 영향이 없는 timer인경우.
+ */
         if (timer->flags & TIMER_IRQSAFE) {
             raw_spin_unlock(&base->lock);
             call_timer_fn(timer, fn, baseclk);
             raw_spin_lock(&base->lock);
             base->running_timer = NULL;
         } else {
+/*
+ * IAMROOT, 2022.09.03:
+ * - irq에 영향이 있는경우,
+ */
             raw_spin_unlock_irq(&base->lock);
             call_timer_fn(timer, fn, baseclk);
             raw_spin_lock_irq(&base->lock);
@@ -1475,6 +2018,11 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
     }
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * lvl 0..LVL_DEPTH 까지 순회하며 expired된 timer들을 heads에 옮기며 가장 높은
+ * level을 기록한다.
+ */
 static int collect_expired_timers(struct timer_base *base,
                   struct hlist_head *heads)
 {
@@ -1483,6 +2031,17 @@ static int collect_expired_timers(struct timer_base *base,
     int i, levels = 0;
     unsigned int idx;
 
+/*
+ * IAMROOT, 2022.09.03:
+ *
+ * lvl 0..LVL_DEPTH 까지 순회하며 expired된 timer들을 heads에 옮기며 가져온
+ * 레벨 개수를 return 한다.
+ *
+ * level 0 -> timer0, timer1, timer2 -> heads[0]에 통째로 넣어진다.
+ * level 1 -> timer3, timer4,        -> heads[1]에 통째로 넣어진다.
+ * level 2 -> NULL                   -> 여기서 중단되고 return level2
+ * level 3 -> timer5.
+ */
     for (i = 0; i < LVL_DEPTH; i++) {
         idx = (clk & LVL_MASK) + i * LVL_SIZE;
 
@@ -1492,6 +2051,11 @@ static int collect_expired_timers(struct timer_base *base,
             levels++;
         }
         /* Is it time to look at the next level? */
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - 중간이 비면 그만한다.
+ */
         if (clk & LVL_CLK_MASK)
             break;
         /* Shift clock for the next level granularity */
@@ -1523,6 +2087,10 @@ static int next_pending_bucket(struct timer_base *base, unsigned offset,
  * Search the first expiring timer in the various clock levels. Caller must
  * hold base->lock.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - TODO
+ */
 static unsigned long __next_timer_interrupt(struct timer_base *base)
 {
     unsigned long clk, next, adj;
@@ -1711,17 +2279,34 @@ void timer_clear_idle(void)
  * __run_timers - run all expired timers (if any) on this CPU.
  * @base: the timer vector to be processed.
  */
+
+/*
+ * IAMROOT, 2022.09.03:
+ * - 
+ */
 static inline void __run_timers(struct timer_base *base)
 {
     struct hlist_head heads[LVL_DEPTH];
     int levels;
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 만료시각이 아직 안됬다. return.
+ */
     if (time_before(jiffies, base->next_expiry))
         return;
 
     timer_base_lock_expiry(base);
     raw_spin_lock_irq(&base->lock);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * 
+ * time ---------|--------------|-------------------------|--------
+ *           base->clk      base->next_expiry        jiffies     
+ *               ---------------------------------------->
+ *                   이 사이에 있는 timer들을 expire 시킨다.
+ */
     while (time_after_eq(jiffies, base->clk) &&
            time_after_eq(jiffies, base->next_expiry)) {
         levels = collect_expired_timers(base, heads);
@@ -1734,6 +2319,10 @@ static inline void __run_timers(struct timer_base *base)
         base->clk++;
         base->next_expiry = __next_timer_interrupt(base);
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 가져온 timer들을 역순으로 expire 시킨다.
+ */
         while (levels--)
             expire_timers(base, heads + levels);
     }
@@ -1744,6 +2333,10 @@ static inline void __run_timers(struct timer_base *base)
 /*
  * This function runs timers and the timer-tq in bottom half context.
  */
+/*
+ * IAMROOT, 2022.09.03:
+ * - TIMER_SOFTIRQ 발생시 동작하는 함수.
+ */
 static __latent_entropy void run_timer_softirq(struct softirq_action *h)
 {
     struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
@@ -1998,6 +2591,10 @@ int timers_dead_cpu(unsigned int cpu)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - @cpu의 lowres timer 자료구조를 초기화한다.
+ */
 static void __init init_timer_cpu(int cpu)
 {
     struct timer_base *base;
@@ -2007,12 +2604,20 @@ static void __init init_timer_cpu(int cpu)
         base = per_cpu_ptr(&timer_bases[i], cpu);
         base->cpu = cpu;
         raw_spin_lock_init(&base->lock);
+/*
+ * IAMROOT, 2022.09.03:
+ * - 현재 clock을 저장해놓는다.
+ */
         base->clk = jiffies;
         base->next_expiry = base->clk + NEXT_TIMER_MAX_DELTA;
         timer_base_init_expiry_lock(base);
     }
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 전체 cpu의 lowres timer 자료구조를 초기화한다.
+ */
 static void __init init_timer_cpus(void)
 {
     int cpu;
@@ -2021,6 +2626,13 @@ static void __init init_timer_cpus(void)
         init_timer_cpu(cpu);
 }
 
+/*
+ * IAMROOT, 2022.09.03:
+ * - 1. 전체 cpu lowres timer 자료구조 초기화.
+ *   2. posix timer 초기화.
+ *   3. TIMER_SOFTIRQ callback 함수 등록.
+ *      (raise_softirq)
+ */
 void __init init_timers(void)
 {
     init_timer_cpus();
 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 623
165 [커널 19차] 27 주차 Min 2022.11.22 82
164 [커널 18차] 78주차 kkr 2022.11.19 186
163 [커널 19차] 25 ~ 26 주차 Min 2022.11.14 71
162 [커널 18차] 76-77주차 kkr 2022.11.12 385
161 [커널 19차] 24주차 Min 2022.10.31 108
160 [커널 17차] 112주차 ㅇㅇㅇ 2022.10.30 81
159 [커널 18차] 75주차 kkr 2022.10.29 40
158 [커널 17차] 107 ~ 111주차 ㅇㅇㅇ 2022.10.23 71
157 [커널 19차] 22주차 Min 2022.10.17 76
156 [커널 18차] 73주차 kkr 2022.10.15 44
155 [커널 18차] 72주차 kkr 2022.10.09 182
154 [커널 18차] 71주차 kkr 2022.10.01 74
153 [커널 18차] 70주차 kkr 2022.09.24 76
152 [커널 18차] 69주차 kkr 2022.09.22 57
151 [커널 17차] 105~106주차 ㅇㅇㅇ 2022.09.18 50
150 [커널 17차] 104주차 ㅇㅇㅇ 2022.09.04 87
» [커널 18차] 67주차 kkr 2022.09.03 138
148 [커널 17차] 103주차 ㅇㅇㅇ 2022.08.28 35
147 [커널 18차] 66주차 kkr 2022.08.27 75
146 [커널 17차] 101~102주차 ㅇㅇㅇ 2022.08.21 45
XE Login