[커널 18차] 90주차

2023.02.13 16:07

kkr 조회 수:63

rt : pick_next_task_rt, put_prev_task_rt완

    set_next_task_rt 측 push_rt_tasks 진행중

 

git : https://github.com/iamroot18/5.10/commit/079ea9f374ecac6ebec54e1da0eefe33172593b2

 

diff --git a/README.md b/README.md
index 7f0622735a1d..256d75ad8736 100644
--- a/README.md
+++ b/README.md
@@ -385,3 +385,7 @@
 - 2023.02.04, Zoom 온라인(6명 참석)
 - 스케줄러 진행중(rt)
 
+### 90주차
+- 2023.02.11, Zoom 온라인(6명 참석)
+- 스케줄러 진행중(rt)
+
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
index 86470cfcef60..6998a93599da 100644
--- a/include/asm-generic/bitops/sched.h
+++ b/include/asm-generic/bitops/sched.h
@@ -10,6 +10,14 @@
  * way of searching a 100-bit bitmap.  It's guaranteed that at least
  * one of the 100 bits is cleared.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   모든 아키텍처는 이 기능을 정의해야 합니다. 100비트 비트맵을 
+ *   검색하는 가장 빠른 방법입니다. 100비트 중 적어도 하나는 
+ *   지워지는 것이 보장됩니다.
+ * - sched 전용으로 100개 전용으로 비트맵 검색을 만든것.
+ */
 static inline int sched_find_first_bit(const unsigned long *b)
 {
 #if BITS_PER_LONG == 64
diff --git a/include/linux/sched/sd_flags.h b/include/linux/sched/sd_flags.h
index 57bde66d95f7..66b64745e816 100644
--- a/include/linux/sched/sd_flags.h
+++ b/include/linux/sched/sd_flags.h
@@ -79,6 +79,16 @@ SD_FLAG(SD_BALANCE_WAKE, SDF_SHARED_CHILD | SDF_NEEDS_GROUPS)
  *
  * SHARED_CHILD: Set from the base domain up to the NUMA reclaim level.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * ---
+ *  task가 잠들엇다 일어날때 가장 좋은방법은 같은 cpu에서 깨어나는것이다.
+ *  만약 그렇지 못할 경우 다른 cpu를 선택해야되는데 그 경우에 대한것이다.
+ *  domain내의 idle sibling중인 cpu에 대해서 선택한다는것이다.
+ * ---
+ * - idle상태에서 깨어난 cpu가 domain내의 idle sibling 선택을 허용한다.
+ *
+ */
 SD_FLAG(SD_WAKE_AFFINE, SDF_SHARED_CHILD)
 
 /*
diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
index 8f0f778b7c91..fd0e62bdb315 100644
--- a/include/linux/sched/topology.h
+++ b/include/linux/sched/topology.h
@@ -153,6 +153,10 @@ struct sched_domain {
     unsigned long span[];
 };
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @sd에 소속되있는 cpumask
+ */
 static inline struct cpumask *sched_domain_span(struct sched_domain *sd)
 {
     return to_cpumask(sd->span);
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index d6165f8cdf95..10c2c3380c20 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -85,6 +85,10 @@ EXPORT_SYMBOL_GPL(irq_work_queue);
  *
  * Can be re-enqueued while the callback is still in progress.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - irq가 끝나고 나서 해소되는 work
+ */
 bool irq_work_queue_on(struct irq_work *work, int cpu)
 {
 #ifndef CONFIG_SMP
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5ddda52f0ecd..6e3c6d39442e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -935,6 +935,10 @@ static bool set_nr_if_polling(struct task_struct *p)
 #endif
 #endif
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @head에 @task를 추가한다.
+ */
 static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
 {
     struct wake_q_node *node = &task->wake_q;
@@ -971,6 +975,10 @@ static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
  * This function must be used as-if it were wake_up_process(); IOW the task
  * must be ready to be woken at this location.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - @head에 @task를 추가한다. 성공했으면 ref up.
+ */
 void wake_q_add(struct wake_q_head *head, struct task_struct *task)
 {
     if (__wake_q_add(head, task))
@@ -1000,6 +1008,11 @@ void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task)
         put_task_struct(task);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - TODO
+ *   @head의 task들를 깨운다.
+ */
 void wake_up_q(struct wake_q_head *head)
 {
     struct wake_q_node *node = head->first;
@@ -2704,6 +2717,11 @@ static int migration_cpu_stop(void *data)
     return 0;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - this rq에서 task보다 낮은 lowest_rq를 찾아 balance를 수행한다.
+ *   (this rq와 task rq가 같은 경우에 한해서)
+ */
 int push_cpu_stop(void *arg)
 {
     struct rq *lowest_rq = NULL, *rq = this_rq();
@@ -2712,6 +2730,11 @@ int push_cpu_stop(void *arg)
     raw_spin_lock_irq(&p->pi_lock);
     raw_spin_rq_lock(rq);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - lock만 하고 find_lock_rq에서 double lock을 잡기전 한번 
+ *   검사를 한다.
+ */
     if (task_rq(p) != rq)
         goto out_unlock;
 
@@ -2722,6 +2745,13 @@ int push_cpu_stop(void *arg)
 
     p->migration_flags &= ~MDF_PUSH;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - rt : find_lock_lowest_rq()
+ *   @p보다 우선순위가 낮은 lowest_rq를 찾아온다. 찾아지면 double lock
+ *   이 걸려있는 상태가 된다.
+ *   
+ */
     if (p->sched_class->find_lock_rq)
         lowest_rq = p->sched_class->find_lock_rq(p, rq);
 
@@ -2729,6 +2759,14 @@ int push_cpu_stop(void *arg)
         goto out_unlock;
 
     // XXX validate p is still the highest prio task
+/*
+ * IAMROOT, 2023.02.11:
+ * - doublelock을 얻은후에 한번더 task rq와 this rq가 같은지 검사를 
+ *   한다.
+ *
+ * - this rq에서 @p를 deactivate시킨후 lowest_rq에 activate를 시키고,
+ *   lowest_rq를 curr로 reschedule 한다.
+ */
     if (task_rq(p) == rq) {
         deactivate_task(rq, p, 0);
         set_task_cpu(p, lowest_rq->cpu);
@@ -8901,6 +8939,10 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
     return ret;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - yield 처리후 schedule 수행.
+ */
 static void do_sched_yield(void)
 {
     struct rq_flags rf;
@@ -9056,6 +9098,10 @@ EXPORT_SYMBOL(__cond_resched_rwlock_write);
  * If you want to use yield() to be 'nice' for others, use cond_resched().
  * If you still want to use yield(), do not!
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - yield 처리 후 schedule 처리한다.
+ */
 void __sched yield(void)
 {
     set_current_state(TASK_RUNNING);
diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c
index 27005b1d1a6c..c77bd4457553 100644
--- a/kernel/sched/cpupri.c
+++ b/kernel/sched/cpupri.c
@@ -40,6 +40,16 @@
  *
  *                 100      100 (CPUPRI_HIGHER)
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 원래 prio는 낮을수록 우선순위가 높은데, 이를 역으로 변환하여
+ *   높을수록 우선순위가 높도록 한다.
+ *   (cpupri 또는 user 관점 priority는 번호가 높을수록 우선순위가 높다.)
+ * ----
+ * - 옛날에는 102개 체재 였다(idle이란게 있었다.). 지금은 idle이 빠져 
+ *   101개 체재가 됬다.
+ *   101개 체재에선 RT100을 NORMAL과 동일하게 처리한다.
+ */
 static int convert_prio(int prio)
 {
     int cpupri;
@@ -58,6 +68,10 @@ static int convert_prio(int prio)
         break;
 
     case MAX_RT_PRIO:
+/*
+ * IAMROOT, 2023.02.11:
+ * - deadline 용인듯 싶다.
+ */
         cpupri = CPUPRI_HIGHER;        /* 100 */
         break;
     }
@@ -65,9 +79,20 @@ static int convert_prio(int prio)
     return cpupri;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @p->cpumask와 @idx 우선순위에 해당하는 cpupri에 둘다 포함되는 cpu가 
+ *   있으면 return 1.
+ *   @lowest_mask 가 NULL이 아니면 겹치는 cpu가 lowest_mask에 기록된다.
+ */
 static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p,
                 struct cpumask *lowest_mask, int idx)
 {
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - @cp의 @idx에 
+ */
     struct cpupri_vec *vec  = &cp->pri_to_cpu[idx];
     int skip = 0;
 
@@ -91,15 +116,46 @@ static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p,
      *  pull this task if the run queue is running at a lower
      *  priority.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   벡터를 볼 때 카운터를 읽고 메모리 배리어를 수행한 다음 마스크를 읽어야 
+ *   합니다.
+ *
+ *   Note: 이것은 여전히 정교하지만 처리 할 수 있습니다.
+ *   이상적으로는 설정된 마스크만 보고자 합니다.
+ *
+ *   마스크가 설정되지 않은 경우 유일한 잘못된 점은 필요한 것보다 조금 더 
+ *   많은 작업을 수행한 것입니다.
+ *
+ *   메모리 장벽으로 인해 0 카운트를 읽었지만 마스크가 설정된 경우 실행 
+ *   대기열에 대한 가장 높은 우선 순위 작업이 실행 대기열을 떠났을 때만 
+ *   발생할 수 있으며 이 경우 풀이 이어집니다. 우리가 처리하고 있는 작업이 
+ *   갈 적절한 위치를 찾는 데 실패하면 실행 대기열이 낮은 우선순위에서 실행 
+ *   중인 경우 풀 요청이 이 작업을 풀합니다.
+ */
     smp_rmb();
 
     /* Need to do the rmb for every iteration */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 해당 우선순위에 해당하는 cpu가 하나도 없으면 return.
+ */
     if (skip)
         return 0;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 미포함. return 0.
+ */
     if (cpumask_any_and(&p->cpus_mask, vec->mask) >= nr_cpu_ids)
         return 0;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - cpu_mask와 vec mask 와 겹치는 mask가 있으면 return 1.
+ *   없으면 return 0
+ */
     if (lowest_mask) {
         cpumask_and(lowest_mask, &p->cpus_mask, vec->mask);
 
@@ -111,6 +167,14 @@ static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p,
          * condition, simply act as though we never hit this
          * priority level and continue on.
          */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   vec->mask의 첫 번째 읽기와 두 번째 읽기 사이에 맵이 동시에 비워질 
+ *   수 있기 때문에 배열에 적어도 하나의 비트가 여전히 설정되어 있는지 
+ *   확인해야 합니다. 이 조건에 도달하면 이 우선 순위 수준에 도달하지 않은 
+ *   것처럼 행동하고 계속 진행하십시오.
+ */
         if (cpumask_empty(lowest_mask))
             return 0;
     }
@@ -118,6 +182,11 @@ static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p,
     return 1;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - fitness_fn 수행을 안하고 그냥 @p의 우선순위 범위에 대해서 @cp에 
+ *   해당하는 cpu를 찾는다.
+ */
 int cpupri_find(struct cpupri *cp, struct task_struct *p,
         struct cpumask *lowest_mask)
 {
@@ -141,26 +210,76 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
  *
  * Return: (int)bool - CPUs were found
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   cpupri_find_fitness - 시스템에서 최상의(가장 낮은 pri) CPU 찾기 
+ *   @cp: cpupri 컨텍스트 
+ *   @p: 작업 
+ *   @lowest_mask: 선택한 CPU(또는 NULL)로 채울 마스크 
+ *   @fitness_fn: 사용자 지정 검사를 수행하는 함수에 대한 포인터는 해당 
+ *   CPU만 반환하도록 CPU가 특정 기준에 맞는지 여부를 확인합니다.
+ *
+ *   참고: 이 함수는 현재 호출 중에 계산된 권장 CPU를 반환합니다. 
+ *   호출이 반환될 때까지 CPU는 실제로 여러 번 우선 순위를 변경했을 수 
+ *   있습니다. 이상적이지는 않지만 일반 리밸런서 로직이 현재 우선 순위 
+ *   구성의 불확실성에 대한 경주로 인해 생성된 모든 불일치를 수정하므로 
+ *   정확성의 문제는 아닙니다.
+ *
+ *   return: (int)bool - CPU가 발견되었습니다.  
+ *
+ * - 1. @p의 우선순위범위에서 @cp 범위와 겹치는 cpu를 찾는다.
+ *   2. @lowest_mask, @fitness_fn 이 있는 경우 찾은 cpu를 기록하고
+ *   fitness_fn을 수행하여 성공한 cpu를 lowest_mask에 기록한다.
+ *   3. @fitness_fn이 없는 경우 cpu를 찾기만 하고 끝낸다.
+ */
 int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
         struct cpumask *lowest_mask,
         bool (*fitness_fn)(struct task_struct *p, int cpu))
 {
+/*
+ * IAMROOT, 2023.02.11:
+ * - task priority로 max priority를 구한다.
+ *   자신보다 낮는것을 찾아야되는 상황이다.
+ */
     int task_pri = convert_prio(p->prio);
     int idx, cpu;
 
     BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 낮은것부터 높은순으로 iterate
+ */
     for (idx = 0; idx < task_pri; idx++) {
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @cp의 idx 우선순위의 cpumask와 @p의 cpumask 둘다 포함되는 cpu를
+ *   lowest_mask에 기록한다. 없으면 continue.
+ */
         if (!__cpupri_find(cp, p, lowest_mask, idx))
             continue;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @lowest_mask, fitness_fn 가 인자로 안들어왔으면 그냥 cpu를 찾고 
+ *   끝낸다.
+ */
         if (!lowest_mask || !fitness_fn)
             return 1;
 
         /* Ensure the capacity of the CPUs fit the task */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 찾아낸 lowest_mask에 대해서 @fitness_fn을 수행한다.
+ */
         for_each_cpu(cpu, lowest_mask) {
             if (!fitness_fn(p, cpu))
+/*
+ * IAMROOT, 2023.02.11:
+ * - 적합하지 않으면 lowest_mask에서 해당 cpu를 clear한다.
+ */
                 cpumask_clear_cpu(cpu, lowest_mask);
         }
 
@@ -168,9 +287,18 @@ int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
          * If no CPU at the current priority can fit the task
          * continue looking
          */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 전부 실패한 개념이되므로 다음 priority로 이동.
+ */
         if (cpumask_empty(lowest_mask))
             continue;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - fitness_fn을 해당 priority에서 성공한 lowest_mask cpu가 있었다면 
+ *   return 1.
+ */
         return 1;
     }
 
@@ -191,9 +319,35 @@ int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
      * must do proper RT planning to avoid overloading the system if they
      * really care.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   적합한 최하위 마스크를 찾지 못한 경우 이번에는 적합성 기준을 고려하지 
+ *   않고 새 검색을 시작합니다. 
+ *
+ *   이 규칙은 올바른 CPU에 작업을 맞추는 것보다 우선 순위를 존중하는 것을 
+ *   선호합니다(현재 용량 인식이 유일한 사용자임).
+ *   아이디어는 더 높은 우선 순위 작업이 실행될 수 있는 경우 적합하지 않은 
+ *   CPU에서 종료되더라도 실행되어야 한다는 것입니다.
+ *
+ *   이 트레이드 오프의 비용은 완전히 명확하지 않으며 일부 워크로드에는 좋고 
+ *   다른 워크로드에는 좋지 않을 수 있습니다.
+ *
+ *   여기서 주요 아이디어는 일부 CPU가 과도하게 커밋된 경우 스케줄러가 
+ *   전통적으로 수행한 대로 확산을 시도한다는 것입니다. 시스템 관리자는 
+ *   정말로 관심이 있는 경우 시스템 과부하를 피하기 위해 적절한 RT 계획을 
+ *   수행해야 합니다.
+ *
+ * - lowest cpu를 priority범위에서 하나도 못찾았다. fitness_fn 함수 수행
+ *   없이 한번더 시도한다.
+ */
     if (fitness_fn)
         return cpupri_find(cp, p, lowest_mask);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - fitness_fn 수행요청없이도 cpu를 못찾은상태. return 0.
+ */
     return 0;
 }
 
diff --git a/kernel/sched/cpupri.h b/kernel/sched/cpupri.h
index 25b5e3451ff9..f087c25e9c05 100644
--- a/kernel/sched/cpupri.h
+++ b/kernel/sched/cpupri.h
@@ -2,6 +2,10 @@
 
 #define CPUPRI_NR_PRIORITIES    (MAX_RT_PRIO+1)
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - cpupri는 번호가 높을수록 우선순위가 높다.
+ */
 #define CPUPRI_INVALID        -1
 #define CPUPRI_NORMAL         0
 /* values 1-99 are for RT1-RT99 priorities */
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index f97323486f3a..c662ff50cad0 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -94,7 +94,7 @@ unsigned int sysctl_sched_child_runs_first __read_mostly;
  * - papago
  *  SCHED_OTHER 깨우기 세분성입니다.
  *
- *  이 옵션은 분리된 워크로드의 선점 효과를 지연시키고 과도한 스케줄링을 줄입니다. 
+ *  이 옵션은 분리된 워크로드의 선점 효과를 지연시키고 과도한 스케줄링을 줄입니다.
  *  동기식 워크로드에는 여전히 즉각적인 깨우기/절전 대기 시간이 있습니다.
  *
  * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
@@ -279,7 +279,7 @@ static void __update_inv_weight(struct load_weight *lw)
  *
  * - 실제론 이미 계산된 1 / lw.weight값을 사용해서 이진화 정수계산으로
  *   구한다 (위 주석 참고)
- * - 계산을 수행하면서 발생할수있는 32bit overflow에 대한 처리와, 
+ * - 계산을 수행하면서 발생할수있는 32bit overflow에 대한 처리와,
  *   그에 따른 정밀도 감소처리가 있다.
  *
  * - calc_delta_fair 에서 호출 하였을 때
@@ -713,20 +713,20 @@ static inline bool entity_before(struct sched_entity *a,
  *   2. curr가 없거나 on_rq가 아닌 상태면 leftmost_se->vruntime으로 처리
  *   3. 그게 아니면 min_vruntime유지
  *
- * - 보통은 curr->vruntime이 가장 빠른 시간으로 설정되고, 그에따라 
+ * - 보통은 curr->vruntime이 가장 빠른 시간으로 설정되고, 그에따라
  *   아래 조건들로 해서도 왠간해선 curr->vruntime이 선택 될것이다.
  *   그러나 어찌됫든 혹시나 모를 상황에 대비해 min, max비교등을 수행해서
  *   min_vruntime이 갱신된다.
  *
  * --- vruntime이 min_vruntime보다 클경우(chat open ai. 검증필요. 참고만)
- *  1. task이 이전에 선점되었고 나중에 재개된 경우입니다. task가 선점되면 
- *  해당 vruntime이 일시적으로 중지될 수 있으며 다시 시작되면 해당 
- *  vruntime이 현재 시간으로 업데이트될 수 있습니다. task가 min_vruntime 
+ *  1. task이 이전에 선점되었고 나중에 재개된 경우입니다. task가 선점되면
+ *  해당 vruntime이 일시적으로 중지될 수 있으며 다시 시작되면 해당
+ *  vruntime이 현재 시간으로 업데이트될 수 있습니다. task가 min_vruntime
  *  값보다 나중에 재개되면 해당 vruntime이 min_vruntime보다 클 수 있습니다.
  *
- *  2. 현재 실행 중인 task이 cfs_rq의 다른 task보다 높은 우선 순위를 
- *  가지고 있어 더 많은 CPU 시간을 받은 경우입니다. 이 경우 현재 실행 중인 
- *  task의 vruntime이 아직 실행되지 않은 task의 vruntime보다 클 수 
+ *  2. 현재 실행 중인 task이 cfs_rq의 다른 task보다 높은 우선 순위를
+ *  가지고 있어 더 많은 CPU 시간을 받은 경우입니다. 이 경우 현재 실행 중인
+ *  task의 vruntime이 아직 실행되지 않은 task의 vruntime보다 클 수
  *  있으므로 min_vruntime 값보다 클 수 있습니다.
  */
 static void update_min_vruntime(struct cfs_rq *cfs_rq)
@@ -740,14 +740,14 @@ static void update_min_vruntime(struct cfs_rq *cfs_rq)
  * IAMROOT, 2022.12.21:
  * - min_vruntime과 비교될 vruntime을 결정한다.
  *
- * 1. curr가 rq에 들어있다. leftmost 
+ * 1. curr가 rq에 들어있다. leftmost
  * 1. curr가 rq에 들어있고, leftmost가 존재.
  *   vruntime = min_vruntime(curr->vruntime, leftmost_se->vruntime)
  * 2. leftmost가 있고 curr가 없는 상태.
  *   vruntime = leftmost_se->vruntime
  *
  * curr on_rq leftmost (compare max_vruntime cfs_rq->min_vruntime)
- * X    -     X        -                   
+ * X    -     X        -
  * X    -     O        leftmost_se->vruntime
  * O    X     X        -
  * O    X     O        leftmost_se->vruntime
@@ -762,7 +762,7 @@ static void update_min_vruntime(struct cfs_rq *cfs_rq)
  * - leftmost가 없는 상황이면 curr->vruntime이 min_vruntime과 비교되서
  *   들어가는데 보통은 같다.
  *
- * - 
+ * -
  */
     if (curr) {
 /*
@@ -956,7 +956,7 @@ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
  */
     unsigned int nr_running = cfs_rq->nr_running;
     u64 slice;
-    
+
 /*
  * IAMROOT, 2023.01.07:
  * - 계층구조의 task 수로 갱신한다.
@@ -3439,7 +3439,7 @@ dequeue_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
  *
  *   reweight_entity 진입전 값들정리(cpu0 = 50%)
  *   cfs_rq load weight = 1024
- *   cfs_rq load avg    = 1024 
+ *   cfs_rq load avg    = 1024
  *   cfs_rq load sum    = 47742
  *
  *   se load weight = 512
@@ -3617,22 +3617,22 @@ void reweight_task(struct task_struct *p, int prio)
  * - papago
  *   이 모든 것은 우리 모두가 싫어하는 전체 합계를 포함하는 계층적 비율에 가깝습니다.
  *
- *   즉, 그룹 엔터티의 가중치는 그룹 실행 대기열 가중치를 기반으로 한 그룹 가중치의 비례적 
- *   공유입니다. 그건: 
+ *   즉, 그룹 엔터티의 가중치는 그룹 실행 대기열 가중치를 기반으로 한 그룹 가중치의 비례적
+ *   공유입니다. 그건:
  *
  *                     tg->weight * grq->load.weight
  *   ge->load.weight = -----------------------------               (1)
  *                       \Sum grq->load.weight
- *  
- *  이제 그 합계를 계산하는 것은 엄청나게 비용이 많이 들기 때문에(거기에 있었고, 
- *  완료했습니다) 우리는 이 평균값으로 근사합니다. 평균은 느리게 이동하므로 근사값이 더 
+ *
+ *  이제 그 합계를 계산하는 것은 엄청나게 비용이 많이 들기 때문에(거기에 있었고,
+ *  완료했습니다) 우리는 이 평균값으로 근사합니다. 평균은 느리게 이동하므로 근사값이 더
  *  저렴하고 안정적입니다.
  *
- *  따라서 위의 대신 다음을 대체합니다. 
+ *  따라서 위의 대신 다음을 대체합니다.
  *
  *  grq->load.weight -> grq->avg.load_avg (2)
  *
- *  결과는 다음과 같습니다. 
+ *  결과는 다음과 같습니다.
  *
  *
  *                     tg->weight * grq->avg.load_avg
@@ -3645,19 +3645,19 @@ void reweight_task(struct task_struct *p, int prio)
  *
  * 그것은 share_avg이며, 맞습니다(주어진 근사치(2)).
  *
- * 문제는 평균이 느리기 때문에(당연히 정확히 그렇게 설계되었으므로) 경계 조건에서 과도 
- * 현상이 발생한다는 것입니다. 특히 그룹이 유휴 상태이고 하나의 작업을 시작하는 경우입니다. 
- * CPU의 grq->avg.load_avg가 쌓이는 데 시간이 걸리고 대기 시간이 좋지 않습니다. 
+ * 문제는 평균이 느리기 때문에(당연히 정확히 그렇게 설계되었으므로) 경계 조건에서 과도
+ * 현상이 발생한다는 것입니다. 특히 그룹이 유휴 상태이고 하나의 작업을 시작하는 경우입니다.
+ * CPU의 grq->avg.load_avg가 쌓이는 데 시간이 걸리고 대기 시간이 좋지 않습니다.
  *
  * 이제 특별한 경우 (1)은 다음과 같이 줄어듭니다.
  *
  *                     tg->weight * grq->load.weight
  *   ge->load.weight = ----------------------------- = tg->weight   (4)
  *                         grp->load.weight
- *                         
+ *
  * 즉, 다른 모든 CPU가 유휴 상태이므로 합계가 축소됩니다. UP 시나리오.
  *
- * 따라서 우리가 하는 일은 다음과 같이 (가까운) UP 사례에서 (4)에 접근하도록 근사치 (3)을 
+ * 따라서 우리가 하는 일은 다음과 같이 (가까운) UP 사례에서 (4)에 접근하도록 근사치 (3)을
  * 수정하는 것입니다.
  *
  *   ge->load.weight =
@@ -3665,14 +3665,14 @@ void reweight_task(struct task_struct *p, int prio)
  *              tg->weight * grq->load.weight
  *     ---------------------------------------------------         (5)
  *     tg->load_avg - grq->avg.load_avg + grq->load.weight
- *  
+ *
  *  (
  *     ex) rq 2개.
  *         rq 1개가 idle. 1개가 tg의 load를 100%했을때. 즉 UP와 다름 없는 상황.
  *         tg->load_avg == grp->avg.load_avg
  *
  *              tg->weight * grq->load.weight
- *     ---------------------------------------------------         
+ *     ---------------------------------------------------
  *     tg->load_avg - tg->load_avg + grq->load.weight
  *
  *     =
@@ -3681,12 +3681,12 @@ void reweight_task(struct task_struct *p, int prio)
  *                     grq->load.weight
  *
  *     ex) rq 2개.
- *         rq 1개가 50%. 1개가 50%했을때. 
+ *         rq 1개가 50%. 1개가 50%했을때.
  *
  *         tg->load_avg / 2 == grp->avg.load_avg
  *
  *              tg->weight * grq->load.weight
- *     ---------------------------------------------------         
+ *     ---------------------------------------------------
  *     tg->load_avg - tg->load_avg / 2 + grq->load.weight
  *
  *     =
@@ -3700,7 +3700,7 @@ void reweight_task(struct task_struct *p, int prio)
  *         tg->load_avg * 7 / 10 == grp->avg.load_avg
  *
  *              tg->weight * grq->load.weight
- *     ---------------------------------------------------         
+ *     ---------------------------------------------------
  *     tg->load_avg - tg->load_avg * 7 / 10 + grq->load.weight
  *
  *     =
@@ -3716,7 +3716,7 @@ void reweight_task(struct task_struct *p, int prio)
  *           tg->load_avg * 7 / 10 + grq->load.weigh
  *  )
  *
- * 그러나 grq->load.weight가 0으로 떨어질 수 있으므로 결과적으로 0으로 나누기 때문에 
+ * 그러나 grq->load.weight가 0으로 떨어질 수 있으므로 결과적으로 0으로 나누기 때문에
  * grq->avg.load_avg를 하한으로 사용해야 합니다. 그런 다음 다음을 제공합니다.
  *
  *
@@ -3729,7 +3729,7 @@ void reweight_task(struct task_struct *p, int prio)
  *   tg_load_avg' = tg->load_avg - grq->avg.load_avg +
  *                  max(grq->load.weight, grq->avg.load_avg)
  *
- * 그리고 그것은 share_weight이고 엉뚱합니다. (가까운) UP 경우에는 (4)에 접근하고 일반적인 
+ * 그리고 그것은 share_weight이고 엉뚱합니다. (가까운) UP 경우에는 (4)에 접근하고 일반적인
  * 경우에는 (3)에 접근합니다. ge->load.weight를 일관되게 과대평가하므로 다음과 같습니다.
  *
  *   \Sum ge->load.weight >= tg->weight
@@ -3775,18 +3775,18 @@ static long calc_group_shares(struct cfs_rq *cfs_rq)
  *   grq->avg.load_avg => cfs_rq->tg_load_avg_contrib로 치환해서 생각한다.
  *
  *
- * - 풀어쓰기 
+ * - 풀어쓰기
  *   load = max(scale_load_down(cfs_rq->load.weight), cfs_rq->avg.load_avg);
  *
  *                     tg->weight * grq->load.weight
- *   ge->load.weight = -----------------------------           
+ *   ge->load.weight = -----------------------------
  *                             tg_load_avg'
  *
  *   =>
  *                          tg->shares * load
  *   return = --------------------------------------------------
  *             tg->load_avg - cfs_rq->tg_load_avg_contrib + load
- *             
+ *
  */
     tg_shares = READ_ONCE(tg->shares);
 
@@ -3823,14 +3823,14 @@ static long calc_group_shares(struct cfs_rq *cfs_rq)
 /*
  * IAMROOT, 2023.01.07:
  * - papago
- *   MIN_SHARES는 tg->shares 값이 작은 그룹의 CPU당 파티셔닝을 지원하기 위해 
- *   여기에서 크기를 조정하지 않아야 합니다. CPU에서 그룹을 나타내는 
- *   sched_entity에 최소 load.weight로 할당되는 floor 값입니다. 
+ *   MIN_SHARES는 tg->shares 값이 작은 그룹의 CPU당 파티셔닝을 지원하기 위해
+ *   여기에서 크기를 조정하지 않아야 합니다. CPU에서 그룹을 나타내는
+ *   sched_entity에 최소 load.weight로 할당되는 floor 값입니다.
  *
- *   예를 들어 64비트에서 tg->shares of scale_load(15)=15*1024 그룹의 경우 
- *   하나의 CPU 공유에서 각각 실행 가능한 8개의 작업이 있는 8코어 시스템에서 
- *   15*1024*1/8=1920이 되어야 합니다. scale_load(MIN_SHARES)=2*1024. 
- *   CPU에서 실행할 수 있는 작업이 없는 경우 MIN_SHARES=2가 0 대신 반환되어야 합니다. 
+ *   예를 들어 64비트에서 tg->shares of scale_load(15)=15*1024 그룹의 경우
+ *   하나의 CPU 공유에서 각각 실행 가능한 8개의 작업이 있는 8코어 시스템에서
+ *   15*1024*1/8=1920이 되어야 합니다. scale_load(MIN_SHARES)=2*1024.
+ *   CPU에서 실행할 수 있는 작업이 없는 경우 MIN_SHARES=2가 0 대신 반환되어야 합니다.
  */
     return clamp_t(long, shares, MIN_SHARES, tg_shares);
 }
@@ -3874,7 +3874,7 @@ static void update_cfs_group(struct sched_entity *se)
  * - UMP일 경우.
  * - @se weight와 group의 shares가 같으면 return.
  *   reweight을 할 필요가 없다.
- *   초기값은 shares기준으로 만들어지기때문이다. 
+ *   초기값은 shares기준으로 만들어지기때문이다.
  *   shares나 weight이 변경되는 경우만 아래로 진입할것이다.
  */
     shares = READ_ONCE(gcfs_rq->tg->shares);
@@ -3932,16 +3932,16 @@ static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq, int flags)
 /*
  * IAMROOT, 2023.01.07:
  * - papago
- *   이것이 놓칠 수 있는 몇 가지 경계 사례가 있지만 실제 문제가 되지 않도록 
- *   충분히 자주 호출되어야 합니다. 
+ *   이것이 놓칠 수 있는 몇 가지 경계 사례가 있지만 실제 문제가 되지 않도록
+ *   충분히 자주 호출되어야 합니다.
  *
- *   유휴 스레드가 다른 클래스(!fair)이기 때문에 유휴 상태일 때 호출되지 않으며 
+ *   유휴 스레드가 다른 클래스(!fair)이기 때문에 유휴 상태일 때 호출되지 않으며
  *   사용률에 RT 작업과 같은 항목이 포함되지 않습니다.
  *
- *   있는 그대로, util 번호는 freq-invariant가 아닙니다(이를 위해 
- *   arch_scale_freq_capacity()를 구현해야 합니다). 
+ *   있는 그대로, util 번호는 freq-invariant가 아닙니다(이를 위해
+ *   arch_scale_freq_capacity()를 구현해야 합니다).
  *
- *   cpu_util()을 참조하십시오. 
+ *   cpu_util()을 참조하십시오.
  */
         cpufreq_update_util(rq, flags);
     }
@@ -3961,10 +3961,10 @@ static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq, int flags)
  * IAMROOT, 2022.12.27:
  * - TODO
  * - papago
- *   list_add_leaf_cfs_rq는 항상 상위 cfs_rq 바로 앞에 하위 cfs_rq를 
- *   목록에 배치하고 cfs_rqs는 목록 상향식에서 제거하기 때문에 목록에서 
- *   우리 앞에 있는 cfs_rq가 하위인지 여부만 테스트하면 됩니다.  
- *   cfs_rq가 목록에 없으면 분기를 트리에 연결하기 위해 자식을 추가해야 
+ *   list_add_leaf_cfs_rq는 항상 상위 cfs_rq 바로 앞에 하위 cfs_rq를
+ *   목록에 배치하고 cfs_rqs는 목록 상향식에서 제거하기 때문에 목록에서
+ *   우리 앞에 있는 cfs_rq가 하위인지 여부만 테스트하면 됩니다.
+ *   cfs_rq가 목록에 없으면 분기를 트리에 연결하기 위해 자식을 추가해야
  *   하는지 여부를 테스트합니다 * (자세한 내용은 list_add_leaf_cfs_rq() 참조)
  */
 static inline bool child_cfs_rq_on_list(struct cfs_rq *cfs_rq)
@@ -4035,13 +4035,13 @@ static inline bool cfs_rq_is_decayed(struct cfs_rq *cfs_rq)
 /*
  * IAMROOT, 2023.01.07:
  * - papago
- *   update_tg_load_avg - update the tg's load avg 
+ *   update_tg_load_avg - update the tg's load avg
  *   @cfs_rq: the cfs_rq whose avg changed
  *
  *   이 기능은 다음을 '보장'합니다. tg->load_avg := \Sum tg->cfs_rq[]->avg.load.
  *   그러나 tg->load_avg는 전역 값이므로 성능을 고려해야 합니다.
  *
- *   다른 cfs_rq를 볼 필요가 없도록 전파한 마지막 값을 저장하는 차등 업데이트를 사용합니다. 
+ *   다른 cfs_rq를 볼 필요가 없도록 전파한 마지막 값을 저장하는 차등 업데이트를 사용합니다.
  *   차등이 '작은' 경우 업데이트를 건너뛸 수 있습니다.
  *
  *   update_cfs_share() 전에 tg의 load_avg 업데이트가 필요합니다.
@@ -4193,198 +4193,198 @@ void set_task_rq_fair(struct sched_entity *se,
 /*
  * IAMROOT, 2022.12.31:
  * - papago
- *   마이그레이션 중에 sched_entity가 PELT 계층 구조에 합류/탈퇴할 때 기여도를 
- *   전파해야 합니다. 이 전파의 핵심은 각 그룹에 대한 불변성입니다. 
+ *   마이그레이션 중에 sched_entity가 PELT 계층 구조에 합류/탈퇴할 때 기여도를
+ *   전파해야 합니다. 이 전파의 핵심은 각 그룹에 대한 불변성입니다.
  *
  *   ge->avg == grq->avg                        (1)
  *
- *   IFF_ 순수한 running 및 runnable sum을 봅니다. 계층 구조의 다른 지점에서 
+ *   IFF_ 순수한 running 및 runnable sum을 봅니다. 계층 구조의 다른 지점에서
  *   매우 동일한 entity를 나타내기 때문입니다.
  *
- *   위의 update_tg_cfs_util() 및 update_tg_cfs_runnable()은 사소하고 단순히 
- *   running/runnable sum을 복사합니다(그러나 그룹 엔티티 및 그룹 rq에 PELT 
- *   window가 정렬되어 있지 않기 때문에 여전히 잘못됨). 
+ *   위의 update_tg_cfs_util() 및 update_tg_cfs_runnable()은 사소하고 단순히
+ *   running/runnable sum을 복사합니다(그러나 그룹 엔티티 및 그룹 rq에 PELT
+ *   window가 정렬되어 있지 않기 때문에 여전히 잘못됨).
  *
- *   그러나 update_tg_cfs_load()는 더 복잡합니다. 그래서 우리는: 
+ *   그러나 update_tg_cfs_load()는 더 복잡합니다. 그래서 우리는:
  *
  *   ge->avg.load_avg = ge->load.weight * ge->avg.runnable_avg        (2)
  *
- *   그리고 util과 마찬가지로 runnable을 직접 양도할 수 있어야 하므로 
+ *   그리고 util과 마찬가지로 runnable을 직접 양도할 수 있어야 하므로
  *   다음과 같이 간단하게 접근할 수 있습니다.
  *
  *   grq->avg.load_avg = grq->load.weight * grq->avg.runnable_avg    (3)
  *
- *   그리고 (1)에 따라 다음이 있습니다. 
+ *   그리고 (1)에 따라 다음이 있습니다.
  *
- *   ge->avg.runnable_avg == grq->avg.runnable_avg 
+ *   ge->avg.runnable_avg == grq->avg.runnable_avg
  *
- *   다음을 제공합니다. 
+ *   다음을 제공합니다.
  *
  *                      ge->load.weight * grq->avg.load_avg
  *   ge->avg.load_avg = -----------------------------------        (4)
  *                               grq->load.weight
- * 
+ *
  *   틀린 것만 빼면!
  *
- *   entity의 경우 historical weight는 중요하지 않고 실제로는 미래에만 관심이 
- *   있으므로 순수 runnable sum을 고려할 수 있지만 rq는 이를 수행할 수 
+ *   entity의 경우 historical weight는 중요하지 않고 실제로는 미래에만 관심이
+ *   있으므로 순수 runnable sum을 고려할 수 있지만 rq는 이를 수행할 수
  *   없습니다.
  *   (se는 weight 필요없이 runnable값으로만 계산해도 상관없지만, cfs_rq는
  *   필요해서 결국 weight를 고려해야된다는 말이다.)
  *
- *   우리는 특히 rq가 historical weight를 포함하는 load_avg를 갖기를 원합니다. 
- *   그것들은 blocked load, 즉 (곧) 우리에게 돌아올 것으로 예상되는 load를 
- *   나타냅니다. 
- *   이것은 weight를 sum의 필수적인 부분으로 유지해야만 작동합니다. 따라서 
- *   (3)에 따라 분해할 수 없습니다. 
- *   (historical weight load_avg가 rq에 필요하기 때문에 결국 load sum을 
+ *   우리는 특히 rq가 historical weight를 포함하는 load_avg를 갖기를 원합니다.
+ *   그것들은 blocked load, 즉 (곧) 우리에게 돌아올 것으로 예상되는 load를
+ *   나타냅니다.
+ *   이것은 weight를 sum의 필수적인 부분으로 유지해야만 작동합니다. 따라서
+ *   (3)에 따라 분해할 수 없습니다.
+ *   (historical weight load_avg가 rq에 필요하기 때문에 결국 load sum을
  *   계산할때 weight를 사용해야된다는 의미.)
  *
- *   이것이 작동하지 않는 또 다른 이유는 runnable이 0-sum entity가 아니기 
- *   때문입니다.  
- *   각각 2/3 시간 동안 runnable 2개의 작업이 있는 rq를 상상해 보십시오. 
- *   그런 다음 rq 자체는 이러한 작업의 runnable 섹션이 겹치는 방식 
- *   (또는 겹치지 않음)에 따라 2/3에서 1 사이 어디에서나 runnable 가능합니다. 
- *   rq를 전체적으로 완벽하게 정렬하려면 시간의 2/3를 runnable 수 있습니다. 
- *   그러나 항상 최소한 하나의 runnable 작업이 있는 경우 전체 rq는 항상 
+ *   이것이 작동하지 않는 또 다른 이유는 runnable이 0-sum entity가 아니기
+ *   때문입니다.
+ *   각각 2/3 시간 동안 runnable 2개의 작업이 있는 rq를 상상해 보십시오.
+ *   그런 다음 rq 자체는 이러한 작업의 runnable 섹션이 겹치는 방식
+ *   (또는 겹치지 않음)에 따라 2/3에서 1 사이 어디에서나 runnable 가능합니다.
+ *   rq를 전체적으로 완벽하게 정렬하려면 시간의 2/3를 runnable 수 있습니다.
+ *   그러나 항상 최소한 하나의 runnable 작업이 있는 경우 전체 rq는 항상
  *   runnable 가능합니다.
  *   (각 task runnable시간의 sum이 group의 sum보다 같거나 작을수박에
  *   없다는의미.)
  *
- *   그래서 우리는 근사해야 할 것입니다.. :/ 
+ *   그래서 우리는 근사해야 할 것입니다.. :/
  *
- *   주어진 제약조건: 
+ *   주어진 제약조건:
  *
- *   ge->avg.running_sum <= ge->avg.runnable_sum <= LOAD_AVG_MAX 
+ *   ge->avg.running_sum <= ge->avg.runnable_sum <= LOAD_AVG_MAX
  *
  *   최소한의 overlap을 가정하여 rq에 runnable을 추가하는 규칙을 구성할 수 있습니다.
  *   (runnable이 양수인경우엔 overlap의 개념을 도입해서 적당히 그냥 add만
  *   한다는 의미.)
  *
- *   제거할 때 각 작업이 동등하게 runnable이라고가정합니다. 결과는 다음과 
+ *   제거할 때 각 작업이 동등하게 runnable이라고가정합니다. 결과는 다음과
  *   같습니다.
  *
- *   grq->avg.runnable_sum = grq->avg.load_sum / grq->load.weight 
+ *   grq->avg.runnable_sum = grq->avg.load_sum / grq->load.weight
  *
- *   (runnable이 음수일때는 제거되는 과정이 되므로 overlap된값을 결국 배제하고 
+ *   (runnable이 음수일때는 제거되는 과정이 되므로 overlap된값을 결국 배제하고
  *   좀 정확히 계산해야되므로 식을 사용해 계산해야된다는 의미.)
  *
- *   XXX: 
- *   runnable > running ? 부분에 대해서만 이 작업을 수행합니다. 
+ *   XXX:
+ *   runnable > running ? 부분에 대해서만 이 작업을 수행합니다.
  *
  * ------------------ chat open ai --------------------------------------
  * --- 주석의 줄임말
- * - "IFF"는 "if and only if"의 약자입니다. 명제가 특정 조건에서만 참임을 
+ * - "IFF"는 "if and only if"의 약자입니다. 명제가 특정 조건에서만 참임을
  *   나타내는 데 사용됩니다.
 *
 *  -"XXX"는 수행해야 하거나 추가 주의가 필요한 작업에 대한 자리 표시자입니다.
-*   검토하거나 수정해야 하는 영역을 나타내기 위해 코드 주석에서 자주 
-*   사용됩니다. 
+*   검토하거나 수정해야 하는 영역을 나타내기 위해 코드 주석에서 자주
+*   사용됩니다.
 *
 *  - 0-sum entity
-*  스케줄러에서 "runnable" entity의 개념입니다. 
-*  "0-sum"이라는 용어는 작업 그룹에 대한 "runnable" 시간의 sum가 그룹이 
-*  실행 가능한 총 시간과 반드시 같지는 않다는 사실을 나타냅니다. 이는 그룹의 
-*  작업이 항상 동시에 실행되지 않을 수 있기 때문에 그룹 전체가 개별 작업의 
-*  실행 가능한 시간의 합보다 더 긴 시간 동안 실행될 수 있기 때문입니다. 
+*  스케줄러에서 "runnable" entity의 개념입니다.
+*  "0-sum"이라는 용어는 작업 그룹에 대한 "runnable" 시간의 sum가 그룹이
+*  실행 가능한 총 시간과 반드시 같지는 않다는 사실을 나타냅니다. 이는 그룹의
+*  작업이 항상 동시에 실행되지 않을 수 있기 때문에 그룹 전체가 개별 작업의
+*  실행 가능한 시간의 합보다 더 긴 시간 동안 실행될 수 있기 때문입니다.
 * --------------------
 * --- PELT 관련 용어 ---
 *  - PELT window
-*  task 또는 task gorup의 load 및 util을 추적하는 기간입니다. PELT window의 
-*  크기는 task 또는 task group의 load 및 util avg이 업데이트되는 빈도에 따라 
-*  결정됩니다. 
+*  task 또는 task gorup의 load 및 util을 추적하는 기간입니다. PELT window의
+*  크기는 task 또는 task group의 load 및 util avg이 업데이트되는 빈도에 따라
+*  결정됩니다.
 *
-*  PELT window의 크기는 task 또는 task group의 load 및 util avg이 
-*  업데이트되는 빈도에 따라 결정됩니다. load 및 uitl avg은 일반적으로 
-*  1ms의 정기적인 간격으로 업데이트됩니다. 즉, PELT window의 크기도 
+*  PELT window의 크기는 task 또는 task group의 load 및 util avg이
+*  업데이트되는 빈도에 따라 결정됩니다. load 및 uitl avg은 일반적으로
+*  1ms의 정기적인 간격으로 업데이트됩니다. 즉, PELT window의 크기도
 *  1ms이며 업데이트 간격과 동시에 시작하고 끝납니다.
 *
 *  - PELT window align
-*  서로 다른 task 및 task group의 PELT window을 서로 정렬하면 크기와 
-*  시작 및 종료 시간이 동일함을 의미합니다. PELT 창을 정렬하면 task 및 
-*  task group에 대해 계산된 load 및 util avg의 정확도를 개선하는 데 도움이 
+*  서로 다른 task 및 task group의 PELT window을 서로 정렬하면 크기와
+*  시작 및 종료 시간이 동일함을 의미합니다. PELT 창을 정렬하면 task 및
+*  task group에 대해 계산된 load 및 util avg의 정확도를 개선하는 데 도움이
 *  될 수 있습니다.
 *
-*  예를 들어 A와 B라는 두 개의 task과 CPU에서 실행되는 G라는 task group이 
-*  있다고 가정합니다. A, B, G의 load 및 util avg은 PELT 알고리즘을 사용하여 
+*  예를 들어 A와 B라는 두 개의 task과 CPU에서 실행되는 G라는 task group이
+*  있다고 가정합니다. A, B, G의 load 및 util avg은 PELT 알고리즘을 사용하여
 *  계산되며 각 task 및 task group에는 자체 PELT window가 있습니다.
 *
-*  A, B, G의 PELT window가 서로 정렬되어 있지 않으면 크기나 시작 시간과 
-*  종료 시간이 같지 않다는 의미입니다. PELT 알고리즘은 서로 다른 기간 
-*  동안 task 및 task group의 load 및 util을 추적하므로 각 task 및 
+*  A, B, G의 PELT window가 서로 정렬되어 있지 않으면 크기나 시작 시간과
+*  종료 시간이 같지 않다는 의미입니다. PELT 알고리즘은 서로 다른 기간
+*  동안 task 및 task group의 load 및 util을 추적하므로 각 task 및
 *  task group에 대해 계산된 load 및 util avg이 부정확해질 수 있습니다.
 *
-*  반면에 A, B, G의 PELT 창들이 서로 정렬되어 있다면 크기와 시작 시간과 
-*  종료 시간이 같다는 뜻입니다. 이를 통해 PELT 알고리즘은 동일한 기간 동안 
-*  task 및 task group의 load 및 util을 추적하므로 각 task 및 task group에 
+*  반면에 A, B, G의 PELT 창들이 서로 정렬되어 있다면 크기와 시작 시간과
+*  종료 시간이 같다는 뜻입니다. 이를 통해 PELT 알고리즘은 동일한 기간 동안
+*  task 및 task group의 load 및 util을 추적하므로 각 task 및 task group에
 *  대해 계산된 load 및 util avg의 정확도를 개선하는 데 도움이 될 수 있습니다.
 * --------------------
 * --- load 관련 용어 ---
 *  - historical weigth
-*  과거에 작업 또는 작업 그룹에 주어진 CPU 시간의 양을 나타냅니다. 
-*  스케줄러에서 작업 또는 작업 그룹의 "load_avg"는 향후 소비할 것으로 
-*  예상되는 CPU 시간을 측정한 것입니다. 이 load_avg 값은 작업 또는 그룹의 
-*  현재 및 과거 CPU 사용량을 기반으로 하는 경우가 많습니다. 
+*  과거에 작업 또는 작업 그룹에 주어진 CPU 시간의 양을 나타냅니다.
+*  스케줄러에서 작업 또는 작업 그룹의 "load_avg"는 향후 소비할 것으로
+*  예상되는 CPU 시간을 측정한 것입니다. 이 load_avg 값은 작업 또는 그룹의
+*  현재 및 과거 CPU 사용량을 기반으로 하는 경우가 많습니다.
 *
-*  예를 들어 오랫동안 CPU에서 실행되어 온 작업 그룹을 생각해 보십시오. 
-*  이 그룹은 과거에 많은 CPU 시간을 소비했기 때문에 높은 "역사적 가중치"를 
-*  갖게 됩니다. 그룹이 앞으로도 비슷한 양의 CPU 시간을 계속 사용할 것으로 
-*  예상되면 해당 load_avg 값이 높아집니다. 반면에 그룹이 앞으로 더 적은 
+*  예를 들어 오랫동안 CPU에서 실행되어 온 작업 그룹을 생각해 보십시오.
+*  이 그룹은 과거에 많은 CPU 시간을 소비했기 때문에 높은 "역사적 가중치"를
+*  갖게 됩니다. 그룹이 앞으로도 비슷한 양의 CPU 시간을 계속 사용할 것으로
+*  예상되면 해당 load_avg 값이 높아집니다. 반면에 그룹이 앞으로 더 적은
 *  CPU 시간을 소비할 것으로 예상되는 경우에는 load_avg 값이 더 낮아집니다.
 *
 *  - blocked load
-*  현재 예약 대기 중이며 현재 CPU에서 실행되고 있지 않은 작업의 load입니다. 
-*  이러한 task은 스케줄러에서 CPU를 할당할 때까지 실행할 수 없기 때문에 
-*  "block"된 것으로 간주됩니다.  
+*  현재 예약 대기 중이며 현재 CPU에서 실행되고 있지 않은 작업의 load입니다.
+*  이러한 task은 스케줄러에서 CPU를 할당할 때까지 실행할 수 없기 때문에
+*  "block"된 것으로 간주됩니다.
 *
-*  blocked load는 block task가 실행 가능해지고 CPU에서 실행되도록 예약된 후 
-*  task 또는 task group이 반환될 것으로 예상되는 load를 나타내기 때문에 
+*  blocked load는 block task가 실행 가능해지고 CPU에서 실행되도록 예약된 후
+*  task 또는 task group이 반환될 것으로 예상되는 load를 나타내기 때문에
 *  task 또는 task group의 load avg에 포함됩니다. load avg에 block load를
-*  포함함으로써 스케줄러는 예약 대기 중인 작업의 CPU 리소스 사용량을 
-*  고려하고 다른 task 및 task group에 CPU 시간을 할당하는 방법에 대해 더 많은 
+*  포함함으로써 스케줄러는 예약 대기 중인 작업의 CPU 리소스 사용량을
+*  고려하고 다른 task 및 task group에 CPU 시간을 할당하는 방법에 대해 더 많은
 *  정보에 입각한 결정을 내릴 수 있습니다.
 *
-*  blocked load는 task 또는 task group의 avg load를 계산하는 데 사용되기 
-*  때문에 load sum의 필수 부분으로 유지됩니다. 하중 avg은 하중 sum를 
-*  PELT window의 크기로 나누어 계산합니다. blocked load가 load sum의 필수 
-*  부분으로 포함되지 않은 경우 load avg에 정확하게 반영되지 않으며 
-*  스케줄러는 task 또는 task group의 CPU 리소스 사용에 대한 완전한 그림을 
-*  갖지 못할 것입니다. 
+*  blocked load는 task 또는 task group의 avg load를 계산하는 데 사용되기
+*  때문에 load sum의 필수 부분으로 유지됩니다. 하중 avg은 하중 sum를
+*  PELT window의 크기로 나누어 계산합니다. blocked load가 load sum의 필수
+*  부분으로 포함되지 않은 경우 load avg에 정확하게 반영되지 않으며
+*  스케줄러는 task 또는 task group의 CPU 리소스 사용에 대한 완전한 그림을
+*  갖지 못할 것입니다.
 *
 * - overlap
-*  A와 B라는 두 개의 작업이 있는 실행 대기열이 있다고 상상해 보십시오. 
-*  작업 A는 실행 가능한 시간의 50%이고 작업 B는 실행 가능한 시간의 
-*  40%입니다. 이 경우 두 작업의 실행 가능한 기간이 완전히 겹치기 때문에 
-*  runqueue는 항상 실행 가능합니다. 작업 A가 실행 가능할 때 작업 B도 실행 
-*  가능한 시간의 40%이고 작업 B가 실행 가능한 경우 작업 A도 실행 가능한 
-*  시간의 50%이기 때문입니다.  
+*  A와 B라는 두 개의 작업이 있는 실행 대기열이 있다고 상상해 보십시오.
+*  작업 A는 실행 가능한 시간의 50%이고 작업 B는 실행 가능한 시간의
+*  40%입니다. 이 경우 두 작업의 실행 가능한 기간이 완전히 겹치기 때문에
+*  runqueue는 항상 실행 가능합니다. 작업 A가 실행 가능할 때 작업 B도 실행
+*  가능한 시간의 40%이고 작업 B가 실행 가능한 경우 작업 A도 실행 가능한
+*  시간의 50%이기 때문입니다.
 *
-*  이제 C와 D라는 두 개의 작업이 있는 실행 대기열이 있다고 상상해 보십시오. 
-*  작업 C는 실행 가능한 시간의 60%이고 작업 D는 실행 가능한 시간의 
-*  70%입니다. 이 경우 runqueue는 두 작업의 실행 가능한 기간이 겹치는 방식에 
-*  따라 시간의 60%에서 100% 사이 어디에서나 실행할 수 있습니다. 두 작업을 
-*  동시에 실행할 수 없는 경우 실행 대기열은 시간의 60%만 실행할 수 
-*  있습니다(각 작업이 실행 가능한 최소 시간). 두 작업이 항상 동시에 실행 
-*  가능한 경우 실행 대기열은 시간의 100% 실행 가능합니다(각 작업이 실행 
-*   가능한 최대 시간). 두 작업의 실행 가능 기간이 겹치면 실행 대기열 
-*   실행 가능 시간이 60%에서 100% 사이가 됩니다. 
+*  이제 C와 D라는 두 개의 작업이 있는 실행 대기열이 있다고 상상해 보십시오.
+*  작업 C는 실행 가능한 시간의 60%이고 작업 D는 실행 가능한 시간의
+*  70%입니다. 이 경우 runqueue는 두 작업의 실행 가능한 기간이 겹치는 방식에
+*  따라 시간의 60%에서 100% 사이 어디에서나 실행할 수 있습니다. 두 작업을
+*  동시에 실행할 수 없는 경우 실행 대기열은 시간의 60%만 실행할 수
+*  있습니다(각 작업이 실행 가능한 최소 시간). 두 작업이 항상 동시에 실행
+*  가능한 경우 실행 대기열은 시간의 100% 실행 가능합니다(각 작업이 실행
+*   가능한 최대 시간). 두 작업의 실행 가능 기간이 겹치면 실행 대기열
+*   실행 가능 시간이 60%에서 100% 사이가 됩니다.
 *
 * - assuming minimal overlap
-*   runqueue(rq)에 대한 실행 가능 시간을 계산할 때 runqueue에 있는 작업의 
-*   실행 가능 기간이 많이 겹치지 않는다고 가정하는 것을 의미합니다. 이로 
+*   runqueue(rq)에 대한 실행 가능 시간을 계산할 때 runqueue에 있는 작업의
+*   실행 가능 기간이 많이 겹치지 않는다고 가정하는 것을 의미합니다. 이로
 *   인해 runqueue의 실행 가능한 시간에 대한 추정치가 낮아집니다.
 *
-*   예를 들어 E와 F라는 두 개의 작업이 있는 실행 대기열이 있고 실행 대기열의 
-*   실행 가능 시간을 계산하려는 경우 두 작업의 실행 가능 기간이 전혀 겹치지 
-*   않는다고 가정할 수 있습니다. 이 경우 실행 대기열에 대한 총 실행 가능 
-*   시간을 얻기 위해 각 작업에 대한 실행 가능 시간을 추가하기만 하면 됩니다. 
-*   이렇게 하면 두 작업 간의 중복이 최소화된다고 가정하기 때문에 실행 
+*   예를 들어 E와 F라는 두 개의 작업이 있는 실행 대기열이 있고 실행 대기열의
+*   실행 가능 시간을 계산하려는 경우 두 작업의 실행 가능 기간이 전혀 겹치지
+*   않는다고 가정할 수 있습니다. 이 경우 실행 대기열에 대한 총 실행 가능
+*   시간을 얻기 위해 각 작업에 대한 실행 가능 시간을 추가하기만 하면 됩니다.
+*   이렇게 하면 두 작업 간의 중복이 최소화된다고 가정하기 때문에 실행
 *   대기열의 실행 가능한 시간에 대한 추정치가 낮아집니다.
 *
-*   반면에 두 작업의 실행 가능한 기간이 상당히 겹친다고 가정하면 실행 
-*   대기열의 실행 가능한 시간에 대해 더 높은 추정치를 얻을 수 있습니다. 
-*   작업이 동시에 더 자주 실행될 수 있다고 가정하기 때문에 실행 대기열의 
-*   전체 실행 가능 시간이 늘어납니다. 
+*   반면에 두 작업의 실행 가능한 기간이 상당히 겹친다고 가정하면 실행
+*   대기열의 실행 가능한 시간에 대해 더 높은 추정치를 얻을 수 있습니다.
+*   작업이 동시에 더 자주 실행될 수 있다고 가정하기 때문에 실행 대기열의
+*   전체 실행 가능 시간이 늘어납니다.
 * --------------------
  * ----------------------------------------------------------------------
 * - @gcfs_rq나 @se에 변화가 생긴경우 @se, @cfs를 update한다.
@@ -4461,12 +4461,12 @@ update_tg_cfs_runnable(struct cfs_rq *cfs_rq, struct sched_entity *se, struct cf
  * - propagate runnable sum값의 증감 유무에 따라 @se의 load를 update하고
  *   변경된 값만큼 @cfs_rq의 load를 재계산한다.
  *
- * 1. 증가하는경우 assuming minimal overlap을 적용하는 개념으로 
+ * 1. 증가하는경우 assuming minimal overlap을 적용하는 개념으로
  *    add 와 divider에 대한 min처리만 수행한다.
  *
  * 2. 감소하는 경우는 weight를 고려한다. 위쪽 주석의 식에 따라
  *                      ge->load.weight * grq->avg.load_avg
- *   ge->avg.load_avg = -----------------------------------    
+ *   ge->avg.load_avg = -----------------------------------
  *                               grq->load.weight
  *
  *   를 사용하여 재계산한다. 단 재계산값이 증가했을 경우엔 min처리를 한다.
@@ -4507,10 +4507,10 @@ update_tg_cfs_load(struct cfs_rq *cfs_rq, struct sched_entity *se, struct cfs_rq
 
 /*
  * IAMROOT, 2022.12.31:
- * - 감소됬다면 task runnable이 균등하게 계산한다는 관점으로 avg와 weight로 
+ * - 감소됬다면 task runnable이 균등하게 계산한다는 관점으로 avg와 weight로
  *   재계산한다.
  *
- *   runnable_sum = grq->avg.load_sum / grq->load.weight 
+ *   runnable_sum = grq->avg.load_sum / grq->load.weight
  */
         /*
          * Estimate the new unweighted runnable_sum of the gcfs_rq by
@@ -4768,7 +4768,7 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
 /*
  * IAMROOT, 2022.12.31:
  * - papago
- *   removed_runnable은 removed_load의 비가중 버전이므로 removed_load_sum을 
+ *   removed_runnable은 removed_load의 비가중 버전이므로 removed_load_sum을
  *   추정하는 데 사용할 수 있습니다.
  *
  * - 감소된값을 propagate해야된다. 감소된값을 기록한다.
@@ -4827,7 +4827,7 @@ static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
 /*
  * IAMROOT, 2023.01.07:
  * - papago
- *   @se를 @cfs_rq에 첨부할 때 decay window 을 정렬해야 합니다. 그렇지 않으면 정말 이상하고 
+ *   @se를 @cfs_rq에 첨부할 때 decay window 을 정렬해야 합니다. 그렇지 않으면 정말 이상하고
  *   멋진 일이 발생할 수 있기 때문입니다.
  *   (entity 입장에서의 decay window에 대한 정렬을 의미)
  */
@@ -4843,8 +4843,8 @@ static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
 /*
  * IAMROOT, 2023.01.07:
  * - papago
- *   Hell(o) 불쾌한 물건.. 새 period_contrib를 기반으로 _sum을 다시 계산해야 합니다. 
- *   이것은 정확하지는 않지만 우리는 완전히 PELT 계층 구조 밖에 있기 때문에 _sum을 
+ *   Hell(o) 불쾌한 물건.. 새 period_contrib를 기반으로 _sum을 다시 계산해야 합니다.
+ *   이것은 정확하지는 않지만 우리는 완전히 PELT 계층 구조 밖에 있기 때문에 _sum을
  *   약간 잘라도 아무도 신경 쓰지 않습니다.
  */
     se->avg.util_sum = se->avg.util_avg * divider;
@@ -4942,7 +4942,7 @@ static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
  *    2. @cfs_rq에 대한 load avg 계산.
  *    3. @se에 대한 전파 처리.
  *    4. @se가 attach인 경우 @cfs_rq에 attach.
- *    5. decay됫거나 attach인경우 
+ *    5. decay됫거나 attach인경우
  *       cpu freq 변경시도, taskgroup에 변경을 알려야되는경우 update.
  */
 static inline void update_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
@@ -5607,7 +5607,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
 
 /*
  * IAMROOT, 2023.01.07:
- * - @curr runtime을 종료된것을 검사한다. 다 사용됬으면 
+ * - @curr runtime을 종료된것을 검사한다. 다 사용됬으면
  *   @cfs_rq의 cpu한테 reschedule 요청을 한다.
  */
 
@@ -5706,7 +5706,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 /*
  * IAMROOT, 2023.01.28:
  * - papago
- *   CPU 부하가 자체 무게의 두 배 이상인 경우 최대 슬라이스 길이를 추적합니다(즉, 주변에 더 
+ *   CPU 부하가 자체 무게의 두 배 이상인 경우 최대 슬라이스 길이를 추적합니다(즉, 주변에 더
  *   가벼운 작업만 있는 경우 추적하지 않음).
  */
     if (schedstat_enabled() &&
@@ -5757,9 +5757,9 @@ pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr)
 /*
  * IAMROOT, 2023.01.28:
  * - papago
- *   curr이 설정되어 있으면 트리에 아무 것도 없는 경우 가장 왼쪽 엔터티의 왼쪽이 여전히 
+ *   curr이 설정되어 있으면 트리에 아무 것도 없는 경우 가장 왼쪽 엔터티의 왼쪽이 여전히
  *   트리에 있는지 확인해야 합니다.
- *   
+ *
  * - curr가 left보다 왼쪽인지 확인한다. 더 왼쪽이면 left = curr.
  */
     if (!left || (curr && entity_before(curr, left)))
@@ -5812,7 +5812,7 @@ pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr)
 /*
  * IAMROOT, 2023.01.28:
  * - next를 가장 높은 우선순위로 고려한다.
- * - next가 left 보다 너무 앞서있는경우가 아니면 se를 next로 선택한다. 
+ * - next가 left 보다 너무 앞서있는경우가 아니면 se를 next로 선택한다.
  */
     if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, left) < 1) {
         /*
@@ -5874,7 +5874,7 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
 
 /*
  * IAMROOT, 2022.12.21:
- * - @curr 
+ * - @curr
  *   ex) A:33%, B:33%, C:34%
  *   A가 33%에 대한 분배 시간을 다 마치고 이함수에 진입했을때 curr는 B가 된다.
  * - queued
@@ -6006,7 +6006,7 @@ static inline u64 default_cfs_period(void)
 
 /*
  * IAMROOT, 2022.12.22:
- * - nsec 단위로 return. 기본값 5ms 
+ * - nsec 단위로 return. 기본값 5ms
  */
 static inline u64 sched_cfs_bandwidth_slice(void)
 {
@@ -6023,7 +6023,7 @@ static inline u64 sched_cfs_bandwidth_slice(void)
 /*
  * IAMROOT, 2022.12.23:
  * - papago
- *   할당량에 따라 런타임을 보충합니다. rq->lock 주변에 추가 동기화를 추가하지 
+ *   할당량에 따라 런타임을 보충합니다. rq->lock 주변에 추가 동기화를 추가하지
  *   않도록 rq->clock 대신 sched_clock_cpu를 직접 사용합니다.
  *
  *   cfs_b->잠금이 필요합니다.
@@ -6056,15 +6056,15 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
  *
  *  1) quota == RUNTIME_INF. bandwidth 사용안하는 경우
  *  cfs_b | runtime_  | cfs_b   || timer | runtime_  |
- *  qouta | remaining | runtime || 예약  | remaining | runtime 
+ *  qouta | remaining | runtime || 예약  | remaining | runtime
  *  +-----+-----------+---------++-------+-----------+--------
- *  | ~0  | -         | -       || X     | 5ms       | 유지     
+ *  | ~0  | -         | -       || X     | 5ms       | 유지
  *
  *  2) runtime_remain 이 target_runtime이 될때까지 불충분한 경우
  *     남아있는 runtime만큼 runtime_remain이 충전된다.
  *
  *  | runtime_  | cfs_b   || timer | runtime_  |
- *  | remaining | runtime || 예약  | remaining | runtime 
+ *  | remaining | runtime || 예약  | remaining | runtime
  *  +-----------+---------++-------+-----------+--------
  *  | 0ms       | 0ms     || O     | 0ms       | 0ms
  *  | 0ms       | 1ms     || O     | 1ms       | 0ms
@@ -6078,7 +6078,7 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
  *  3) runtime_remain이 target_runtime이 될때까지 충분한 경우
  *
  *  | runtime_  | cfs_b   || timer | runtime_  |
- *  | remaining | runtime || 예약  | remaining | runtime 
+ *  | remaining | runtime || 예약  | remaining | runtime
  *  +-----------+---------++-------+-----------+--------
  *  | 0ms       | 5ms     || O     | 5ms       | 0ms
  *  | 5ms       | 0ms     || O     | 5ms       | 0ms
@@ -6122,7 +6122,7 @@ static int __assign_cfs_rq_runtime(struct cfs_bandwidth *cfs_b,
 
 /*
  * IAMROOT, 2022.12.22:
- * - runtime 이미 남아있다면 amount만큼 빼준다. 그리고 뺀만큼을 
+ * - runtime 이미 남아있다면 amount만큼 빼준다. 그리고 뺀만큼을
  *   runtime_remaining에 추가한다.
  */
         if (cfs_b->runtime > 0) {
@@ -6187,7 +6187,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
  * - likely(cfs_rq->curr)
  *   현재 실행중
  * - assign_cfs_rq_runtime(cfs_rq)
- *   runtime_remain을 얻어오고 period_timer 예약 
+ *   runtime_remain을 얻어오고 period_timer 예약
  * - runtime_remain을 얻어오는데 실패했는데 실행중이면 resched_curr 요청.
  */
     /*
@@ -6501,7 +6501,7 @@ static void distribute_cfs_runtime(struct cfs_bandwidth *cfs_b)
         rq_lock_irqsave(rq, &rf);
 /*
  * IAMROOT, 2022.12.23:
- * - bandwidth 사용중인지, throttle이 남아있는지 확인 
+ * - bandwidth 사용중인지, throttle이 남아있는지 확인
  */
         if (!cfs_rq_throttled(cfs_rq))
             goto next;
@@ -6558,11 +6558,11 @@ static void distribute_cfs_runtime(struct cfs_bandwidth *cfs_b)
 /*
  * IAMROOT, 2022.12.23:
  * - papago
- *   task_group의 대역폭을 다시 채우고 cfs_rqs를 적절하게 조절 해제하는 일을 담당합니다. 마지막 기간 
- *   내에 활동이 없으면 예약이 재개될 때까지 타이머가 비활성화됩니다. cfs_b->idle은 이 상태를 추적하는 
- *   데 사용됩니다. 
+ *   task_group의 대역폭을 다시 채우고 cfs_rqs를 적절하게 조절 해제하는 일을 담당합니다. 마지막 기간
+ *   내에 활동이 없으면 예약이 재개될 때까지 타이머가 비활성화됩니다. cfs_b->idle은 이 상태를 추적하는
+ *   데 사용됩니다.
  *
- * @return 0 : timer restart. 
+ * @return 0 : timer restart.
  *         1 : timer 종료.
  *
  * 1. @cfs_b runtime refill
@@ -6590,9 +6590,9 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, u
      */
 /*
  * IAMROOT, 2022.12.23:
- * - papago 
- *  유휴는 !throttled(적자가 큰 경우)에 따라 달라지며 비활성 상태가 되면 다른 
- *  모든 작업을 연기할 수 있습니다. 
+ * - papago
+ *  유휴는 !throttled(적자가 큰 경우)에 따라 달라지며 비활성 상태가 되면 다른
+ *  모든 작업을 연기할 수 있습니다.
  *
  * - 이미 idle이 되어있는데 throttled rq도 없는 상황. timer 종료
  */
@@ -6640,8 +6640,8 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, u
 /*
  * IAMROOT, 2022.12.27:
  * - papago
- *   스로틀 해제 후 기간 동안 활동이 보장되지만 새 대역폭이 기존 대역폭 
- *   부족을 충당하기에 불충분한 경우도 포함됩니다. (조절된 entity가 있는 
+ *   스로틀 해제 후 기간 동안 활동이 보장되지만 새 대역폭이 기존 대역폭
+ *   부족을 충당하기에 불충분한 경우도 포함됩니다. (조절된 entity가 있는
  *   동안 타이머가 활성 상태를 유지하도록 합니다.).
  */
     cfs_b->idle = 0;
@@ -6899,7 +6899,7 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
              */
 /*
  * IAMROOT, 2022.12.23:
- * - 너무 자주 발생한다. 
+ * - 너무 자주 발생한다.
  *   1. period를 2배로 늘리는걸 시도 한다.
  *   2. period동안 사용할 수있는 cpu 작업양 2배로 늘린다.
  *   3. period동안 single burst를 수행하는 cpu 수행 양을 늘린다.
@@ -6950,7 +6950,7 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
  *   period를 쓰는 정도.
  *   ex) period = 1, quota = -1인 경우 (편의상 ns를 sec로 하여 1로 표현)
  *   cfs process A, B가 있는 경우 각각 50%씩 사용. (합쳐서 100%)
- *   
+ *
  *   ex) perioid = 1, quota = 0.3인 경우,
  *   cfs process A, B가 있는 경우 각각 16.66%씩 사용. (33%)
  *
@@ -6986,7 +6986,7 @@ static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 
 /*
  * IAMROOT, 2022.12.22:
- * - perioid_timer(sched_cfs_period_timer)를 cfs_b->period후에 
+ * - perioid_timer(sched_cfs_period_timer)를 cfs_b->period후에
  *   시작하도록한다.
  */
 void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
@@ -8702,7 +8702,7 @@ static unsigned long wakeup_gran(struct sched_entity *se)
  *   이제 curr가 실행되기 때문에 gran을 실시간에서 가상 시간으로 단위로 변환하십시오.
  *
  *   'curr' 대신 'se'를 사용하여 가벼운 작업에 페널티를 주어 더 쉽게 선점할 수 있습니다.
- *   즉, 'se' < 'curr'이면 결과 gran이 더 커지므로 더 가벼운 작업에 페널티를 주고, 
+ *   즉, 'se' < 'curr'이면 결과 gran이 더 커지므로 더 가벼운 작업에 페널티를 주고,
  *   otoh 'se' > 'curr'이면 결과 gran이 더 작아지므로 더 가벼운 작업에 페널티를 줍니다.
  *
  *   이것은 가장 왼쪽 작업이 버디보다 우선순위가 높을 때 버디에게 특히 중요합니다.
@@ -8734,10 +8734,10 @@ static unsigned long wakeup_gran(struct sched_entity *se)
  *
  * - curr |  se   : -1
  *
- * -      gran 
+ * -      gran
  *   se |  curr | : 0
  *
- * -      gran 
+ * -      gran
  *   se |      |  curr : 1
  */
 static int
@@ -8947,10 +8947,10 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
 /*
  * IAMROOT, 2023.01.28:
  * - papago
- *   dequeue_task_fair()의 set_next_buddy() 때문에 다음 작업이 현재 작업과 동일한 cgroup에서 
+ *   dequeue_task_fair()의 set_next_buddy() 때문에 다음 작업이 현재 작업과 동일한 cgroup에서
  *   나올 가능성이 높습니다.
  *
- *   따라서 전체 cgroup 계층 구조를 넣거나 설정하는 것을 피하고 실제로 변경되는 부분만 
+ *   따라서 전체 cgroup 계층 구조를 넣거나 설정하는 것을 피하고 실제로 변경되는 부분만
  *   변경하십시오.
  *
  * - 계층구조로 내려가면서 curr의 next를 순회한다. 최종적으로 마지막 next로 선택된것을
@@ -8968,8 +8968,8 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
 /*
  * IAMROOT, 2023.01.28:
  * - papago
- *   put_prev_entity()를 수행하지 않고 여기에 왔기 때문에 cfs_rq->curr도 고려해야 합니다. 
- *   여전히 실행 가능한 엔터티인 경우 update_curr()는 vruntime을 업데이트하고, 그렇지 않으면 
+ *   put_prev_entity()를 수행하지 않고 여기에 왔기 때문에 cfs_rq->curr도 고려해야 합니다.
+ *   여전히 실행 가능한 엔터티인 경우 update_curr()는 vruntime을 업데이트하고, 그렇지 않으면
  *   우리가 본 적이 있다는 사실을 잊어버립니다.
  */
         if (curr) {
@@ -8992,9 +8992,9 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
 /*
  * IAMROOT, 2023.01.28:
  * - papago
- *   check_cfs_rq_runtime()에 대한 이 호출은 스로틀링을 수행하고 상위 항목의 대기열에서 
+ *   check_cfs_rq_runtime()에 대한 이 호출은 스로틀링을 수행하고 상위 항목의 대기열에서
  *   제외합니다.
- *   따라서 nr_running 테스트는 실제로 정확합니다. 
+ *   따라서 nr_running 테스트는 실제로 정확합니다.
  * - throttle인지 확인한다.
  */
             if (unlikely(check_cfs_rq_runtime(cfs_rq))) {
@@ -9021,7 +9021,7 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
 /*
  * IAMROOT, 2023.01.28:
  * - papago
- *   아직 put_prev_entity를 수행하지 않았고 선택한 작업이 시작과 다른 작업인 경우 최소량의 
+ *   아직 put_prev_entity를 수행하지 않았고 선택한 작업이 시작과 다른 작업인 경우 최소량의
  *   cfs_rq를 터치해 봅니다.
  *
  * - 선택한 p(se)가 @prev가 다르다면 prev se를 put하고, 새로운 p(se)를 set한다.
@@ -9034,7 +9034,7 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
  * - se, pse가 같은 cfs_rq소속일때까지 반복하며
  *   pse를 cfs_rq에 enqueue, se를 cfs_rq에서 dequeue를 하고, se를 curr로 update한다.
  *
- *         O 
+ *         O
  *        / \
  *       O <----same_group
  *      / \
@@ -9046,12 +9046,11 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
             int se_depth = se->depth;
             int pse_depth = pse->depth;
 
-            p
 /*
  * IAMROOT, 2023.01.28:
  * - pse가 se보다 더 깊거나 같은 위치. pse를 put해준다.
  * - ex)
- *         O 
+ *         O
  *        / \
  *       O <----same_group
  *      / \
@@ -9072,7 +9071,7 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
  * IAMROOT, 2023.01.28:
  * - se가 pse보다 더 깊거나 같은 위치. curr를 update해준다.
  * - ex)
- *         O 
+ *         O
  *        / \
  *       O <----same_group
  *      / \
@@ -9152,6 +9151,11 @@ done: __maybe_unused;
     if (!rf)
         return NULL;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 아래 코드들이 balancing.
+ *   next task를 못고른 상태가 되어 idle이 되기전에 가져올수 있는 task를 찾는다.
+ */
     new_tasks = newidle_balance(rq, rf);
 
     /*
diff --git a/kernel/sched/features.h b/kernel/sched/features.h
index 7f8dace0964c..8af70bd23b03 100644
--- a/kernel/sched/features.h
+++ b/kernel/sched/features.h
@@ -74,6 +74,17 @@ SCHED_FEAT(WARN_DOUBLE_CLOCK, false)
  * IPI to that CPU and let that CPU push the RT task to where
  * it should go may be a better scenario.
  */
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   동시에 우선 순위를 낮추고 마이그레이션할 수 있고 실행 대기 중인 
+ *   RT 작업이 있는 단일 CPU가 있는 CPU의 thundering herd attack을 피하기 
+ *   위해 다른 CPU가 해당 CPU를 차지하려고 합니다. rq를 잠그고 가능하면 
+ *   대규모 경합을 생성하여 해당 CPU에 IPI를 보내고 해당 CPU가 RT 
+ *   작업을 가야 할 곳으로 푸시하도록 하는 것이 더 나은 시나리오일 
+ *   수 있습니다.
+ */
 SCHED_FEAT(RT_PUSH_IPI, true)
 #endif
 
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 245a0aef0f6a..5a0a3a7d73e2 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -314,12 +314,20 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 
 static void pull_rt_task(struct rq *this_rq);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @rq가 online이고 @prev 우선순위보다 낮다면(숫자가 낮을수록 높음) return true
+ */
 static inline bool need_pull_rt_task(struct rq *rq, struct task_struct *prev)
 {
     /* Try to pull RT tasks here if we lower this rq's prio */
     return rq->online && rq->rt.highest_prio.curr > prev->prio;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - rt overloaded task 수를 return한다.
+ */
 static inline int rt_overloaded(struct rq *rq)
 {
     return atomic_read(&rq->rd->rto_count);
@@ -401,6 +409,11 @@ static void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
     update_rt_migration(rt_rq);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - pushable_tasks가 있으면 return 1
+ */
+
 static inline int has_pushable_tasks(struct rq *rq)
 {
     return !plist_head_empty(&rq->rt.pushable_tasks);
@@ -412,6 +425,12 @@ static DEFINE_PER_CPU(struct callback_head, rt_pull_head);
 static void push_rt_tasks(struct rq *);
 static void pull_rt_task(struct rq *);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - pushable_tasks가 있으면 push를 지정(push_rt_tasks)한다.
+ *   (pull의 경우 pull_rt_task가 지정된다.)
+ *   
+ */
 static inline void rt_queue_push_tasks(struct rq *rq)
 {
     if (!has_pushable_tasks(rq))
@@ -425,22 +444,46 @@ static inline void rt_queue_pull_task(struct rq *rq)
     queue_balance_callback(rq, &per_cpu(rt_pull_head, rq->cpu), pull_rt_task);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @p를 pushable task로 enqueue한다.
+ */
 static void enqueue_pushable_task(struct rq *rq, struct task_struct *p)
 {
+/*
+ * IAMROOT, 2023.02.11:
+ * - 이미 등록된 상황일 수도 있다. 일단 삭제하고 다시 추가한다.
+ */
     plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks);
     plist_node_init(&p->pushable_tasks, p->prio);
     plist_add(&p->pushable_tasks, &rq->rt.pushable_tasks);
 
     /* Update the highest prio pushable task */
+/*
+ * IAMROOT, 2023.02.11:
+ * - highest_prio.next 갱신.
+ */
     if (p->prio < rq->rt.highest_prio.next)
         rq->rt.highest_prio.next = p->prio;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - pushable_tasks
+ *   같은 cpu에서 두개 이상의 rt task가 있는 경우 다른 cpu로 밀어내기 
+ *   위한것
+ * - pushable_tasks에 등록되있는 경우 일단 dequeue한다.
+ */
 static void dequeue_pushable_task(struct rq *rq, struct task_struct *p)
 {
     plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks);
 
     /* Update the new highest prio pushable task */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 여전시 pushable tasks가 있으면 highest prio를 기록하고 그게 아니면
+ *   max로 설정한다.
+ */
     if (has_pushable_tasks(rq)) {
         p = plist_first_entry(&rq->rt.pushable_tasks,
                       struct task_struct, pushable_tasks);
@@ -487,6 +530,10 @@ static inline void rt_queue_push_tasks(struct rq *rq)
 static void enqueue_top_rt_rq(struct rt_rq *rt_rq);
 static void dequeue_top_rt_rq(struct rt_rq *rt_rq);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - rq에 들어있는지 확인.
+ */
 static inline int on_rt_rq(struct sched_rt_entity *rt_se)
 {
     return rt_se->on_rq;
@@ -507,6 +554,33 @@ static inline int on_rt_rq(struct sched_rt_entity *rt_se)
  * Note that uclamp_min will be clamped to uclamp_max if uclamp_min
  * > uclamp_max.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   uclamp 설정을 고려하여 @cpu에서 실행할 작업 @p의 적합성을 확인합니다. 
+ *
+ *   이 검사는 uclamp_min 값이 @cpu의 용량보다 큰 이기종 시스템에서만 
+ *   중요합니다. 이기종 시스템이 아닌 경우 이 함수는 항상 true를 반환합니다.
+ *
+ *   이 함수는 @cpu의 용량이 >= uclamp_min이면 true를 반환하고 그렇지 
+ *   않으면 false를 반환합니다. 
+ *
+ *   uclamp_min > uclamp_max인 경우 uclamp_min은 uclamp_max로 고정됩니다.
+ *
+ * --- UCLAMP ---
+ * - application의 경우 background, forground등에서 동작한다.
+ *   어떤것들은 절전모드에서 조그맣게 동작하는걸 원하고,
+ *   어떤것들은 강력하게 동작하는것을 원한다.
+ *   예를들어 A라는 app이 background에서 가끔돌아도 cpu를 많이 사용해야된다 
+ *   라던가
+ *   벤치마킹 프로그램처럼 무조건 cpu를 많이 사용해야되는 것이 있다.
+ *   이러한 상황들을 위해 제한을 시킨다.
+ *   max는 Big cpu의 max freq 기준으로 정한다.
+ * --------------
+ *
+ * - @p에서 설정한 uclamp의 min/max중 @cpu의 rq가 최소값을 넘으면 
+ *   return true.
+ */
 static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu)
 {
     unsigned int min_cap;
@@ -573,6 +647,12 @@ static inline struct task_group *next_task_group(struct task_group *tg)
 #define for_each_sched_rt_entity(rt_se) \
     for (; rt_se; rt_se = rt_se->parent)
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @rt_se가 entity인지 task인지 확인한다. my_q가 있으면 entity(group)
+ *   return != NULL : group entity이며 my_q를 가져옴.
+ *          NULL    : task
+ */
 static inline struct rt_rq *group_rt_rq(struct sched_rt_entity *rt_se)
 {
     return rt_se->my_q;
@@ -1043,15 +1123,27 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)
     return idle;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - group entity이면 가장 높은 prio, task면 task prio를 return.
+ */
 static inline int rt_se_prio(struct sched_rt_entity *rt_se)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
     struct rt_rq *rt_rq = group_rt_rq(rt_se);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 자기꺼중에 가장 높은 prio를 가진것을 return.
+ */
     if (rt_rq)
         return rt_rq->highest_prio.curr;
 #endif
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - task prio가져온다.
+ */
     return rt_task_of(rt_se)->prio;
 }
 
@@ -1587,6 +1679,11 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int flags)
  * Put task to the head or the end of the run list without the overhead of
  * dequeue followed by enqueue.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - @rt_se priority list에 @head에 따라 requeue한다.
+ * - group entity의 경우엔 group entity에서 가장 높은 우선순위로 옮긴다.
+ */
 static void
 requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se, int head)
 {
@@ -1603,7 +1700,8 @@ requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se, int head)
 
 /*
  * IAMROOT, 2023.02.10:
- * - TODO
+ * - @p의 rt_se부터 시작하여 parent까지 올라가면서 @head따라 head / tail로
+ *   requeue를 한다.
  */
 static void requeue_task_rt(struct rq *rq, struct task_struct *p, int head)
 {
@@ -1616,6 +1714,11 @@ static void requeue_task_rt(struct rq *rq, struct task_struct *p, int head)
     }
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - rt의 경우 가장높은 우선순위 태스크가 한개밖에 없으면 yield가
+ *   안될 것이다.
+ */
 static void yield_task_rt(struct rq *rq)
 {
     requeue_task_rt(rq, rq->curr, 0);
@@ -1725,6 +1828,12 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
 
 static int balance_rt(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
 {
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - @p가 아직 rq에 없고, @rq(현재 task)보다 @p가(요청한 task) 
+ *   우선순위가 높다면 pull작업을 수행한다.
+ */
     if (!on_rt_rq(&p->rt) && need_pull_rt_task(rq, p)) {
         /*
          * This is OK, because current is on_cpu, which avoids it being
@@ -1732,6 +1841,13 @@ static int balance_rt(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
          * disabled avoiding further scheduler activity on it and we've
          * not yet started the picking loop.
          */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   current는 on_cpu이므로 부하 분산 및 선점/IRQ가 추가 스케줄러 활동을 
+ *   방지하기 위해 여전히 비활성화되어 있고 아직 선택 루프를 시작하지 
+ *   않았기 때문에 괜찮습니다.
+ */
         rq_unpin_lock(rq, rf);
         pull_rt_task(rq);
         rq_repin_lock(rq, rf);
@@ -1769,11 +1885,25 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag
 #endif
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - exec_start를 갱신하고 선택된 @p를 pushable에서 dequeue한다.
+ * - pick_next_task에서 불러지는 경우 @first = true
+ *   set_next_task에서는 @first = false
+ */
 static inline void set_next_task_rt(struct rq *rq, struct task_struct *p, bool first)
 {
+/*
+ * IAMROOT, 2023.02.11:
+ * - 현재 시각으로 (@rq의 clock_task)로 @p의 exec_start를 갱신한다.
+ */
     p->se.exec_start = rq_clock_task(rq);
 
     /* The running task is never eligible for pushing */
+/*
+ * IAMROOT, 2023.02.11:
+ * - @p가 선택된 상황이니, @p를 pushable task에서 dequeue한다.
+ */
     dequeue_pushable_task(rq, p);
 
     if (!first)
@@ -1784,12 +1914,25 @@ static inline void set_next_task_rt(struct rq *rq, struct task_struct *p, bool f
      * utilization. We only care of the case where we start to schedule a
      * rt task
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   이전 작업이 rt인 경우 put_prev_task()는 이미 사용률을 
+ *   업데이트했습니다. 우리는 rt 작업을 예약하기 시작하는 경우에만 
+ *   관심이 있습니다. 
+ * - 이전 task가 rt였다면 put_prev_task_rt()에서 load avg를 갱신했었다.
+ *   이전 task가 rt가 아닌 경우에만 수행한다.
+ */
     if (rq->curr->sched_class != &rt_sched_class)
         update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0);
 
     rt_queue_push_tasks(rq);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 가장 높은 우선순위주에서도 제일 앞에 있는 rt_se를 가져온다.
+ */
 static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
                            struct rt_rq *rt_rq)
 {
@@ -1798,6 +1941,11 @@ static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
     struct list_head *queue;
     int idx;
 
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - 제일 높은 priority를 가져온다.
+ */
     idx = sched_find_first_bit(array->bitmap);
     BUG_ON(idx >= MAX_RT_PRIO);
 
@@ -1807,6 +1955,10 @@ static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
     return next;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 제일 높은 priority를 가진 task를 가져온다.
+ */
 static struct task_struct *_pick_next_task_rt(struct rq *rq)
 {
     struct sched_rt_entity *rt_se;
@@ -1815,12 +1967,22 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
     do {
         rt_se = pick_next_rt_entity(rq, rt_rq);
         BUG_ON(!rt_se);
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - rt_rq가 NULL이면 @rt_se가 task라는 의미가 되여 while이 종료되며
+ *   task가 찾아지는 원리이다.
+ */
         rt_rq = group_rt_rq(rt_se);
     } while (rt_rq);
 
     return rt_task_of(rt_se);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 제일 높은 priority를 가진 task를 가져온다.
+ */
 static struct task_struct *pick_task_rt(struct rq *rq)
 {
     struct task_struct *p;
@@ -1833,6 +1995,11 @@ static struct task_struct *pick_task_rt(struct rq *rq)
     return p;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 제일높은 task를 선택한다. 선택됬으면 exec_start를 갱신하고
+ *   pushable 상황일때는 push task를 지정(queue_balance_callback)한다.
+ */
 static struct task_struct *pick_next_task_rt(struct rq *rq)
 {
     struct task_struct *p = pick_task_rt(rq);
@@ -1843,6 +2010,13 @@ static struct task_struct *pick_next_task_rt(struct rq *rq)
     return p;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 기존 태스크(@p)에 대해 다음과 같은걸 처리한다.
+ *   1. sum_exec_runtime 갱신 및 runtime 초과 처리 
+ *   2. load avg 갱신
+ *   3. 동작할 수 있는 cpu가 2개 이상인경우 pushable task로 enqueue
+ */
 static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
 {
     update_curr_rt(rq);
@@ -1853,6 +2027,13 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
      * The previous task needs to be made eligible for pushing
      * if it is still active
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - rq에 on상태이고 허락된 cpu가 2개 이상인 경우 pushable_tasks로
+ *   enqueue한다.
+ * - 이 상황이되면 rt task가 이미 2개 이상인 상황에서, 다른 rt task에
+ *   우선순위나 RR 정책에 밀려난 상황이된다.
+ */
     if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1)
         enqueue_pushable_task(rq, p);
 }
@@ -1893,6 +2074,27 @@ static struct task_struct *pick_highest_pushable_task(struct rq *rq, int cpu)
 
 static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 가장 낮은 우선순위를 가진 cpu rq를 선택한다. 
+ *   idle -> cfs만 있는 rq -> rt task 순으로 낮을 것이다.
+ *
+ * - task의 우선순위범위내(최저 우선순위 부터 tsak 우선순위까지)에서
+ *   cpupri와 겹치며 uclamp조건을 만족하는 cpu를 lowest_mask에 기록한다.
+ *   최종적으로 선택하는 조건은 다음 우선순위로 따른다.
+ *   1. task cpu (l1 cache공유) :
+ *      task가 동작했던 cpu가 lowest_mask에 있는경우
+ *   2. this cpu (l2 cache 이상 공유) :
+ *      this cpu가 lowest_mask에 있고 해당 domain span에 포함되있는경우
+ *   3. best cpu(l2 cache 이상 공유) :
+ *      lowest_mask에 있고 해당 domain span에 포함되있는경우.
+ *   4. domain에서 못찾은 경우 :
+ *      lowest_mask에 this cpu가 있는 경우
+ *   5. this cpu도 lowest_mask에 없는 경우 :
+ *      lowest_mask에서 아무거나 한개.
+ *
+ *   5번까지 조건에도 없으면 return -1.
+ */
 static int find_lowest_rq(struct task_struct *task)
 {
     struct sched_domain *sd;
@@ -1913,16 +2115,31 @@ static int find_lowest_rq(struct task_struct *task)
      * of the CPUs when searching for the lowest_mask.
      */
     if (static_branch_unlikely(&sched_asym_cpucapacity)) {
-
+/*
+ * IAMROOT, 2023.02.11:
+ * - HMP의 경우이다.
+ * - @task의 우선순위범위에서 cpupri 범위와 겹치는 cpu를 찾아서
+ *   uclamp 범위에 적합한지 검사(rt_task_fits_capacity)하여 
+ *   lowest_mask에 기록한다.
+ */
         ret = cpupri_find_fitness(&task_rq(task)->rd->cpupri,
                       task, lowest_mask,
                       rt_task_fits_capacity);
     } else {
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @task의 우선순위범위에서 cpupri 범위와 겹치는 cpu를 찾아서 겹치는걸
+ *   lowest_mask에 기록한다.
+ */
         ret = cpupri_find(&task_rq(task)->rd->cpupri,
                   task, lowest_mask);
     }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 위에서 못찾았다. return -1
+ */
     if (!ret)
         return -1; /* No targets found */
 
@@ -1934,6 +2151,21 @@ static int find_lowest_rq(struct task_struct *task)
      * We prioritize the last CPU that the task executed on since
      * it is most likely cache-hot in that location.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   이 시점에서 우리는 시스템에서 가장 낮은 우선 순위 작업을 나타내는 
+ *   CPU 마스크를 만들었습니다. 이제 우리는 선호도와 토폴로지를 기반으로 
+ *   최고의 것을 선택하려고 합니다. 
+ *
+ *   작업이 실행된 마지막 CPU는 해당 위치에서 캐시 핫일 가능성이 높기 
+ *   때문에 우선 순위를 지정합니다.
+ *
+ *  - @task의 cpu가 lowest_mask에 존재한다면 cache hot이라고 
+ *  생각하여 즉시 task cpu로 return한다.
+ *  - 마지막에 동작한 task가 task의 cpu에 기록되있으므로 가능하면 
+ *    @task의 cpu와 같은게 좋다.
+ */
     if (cpumask_test_cpu(cpu, lowest_mask))
         return cpu;
 
@@ -1941,11 +2173,24 @@ static int find_lowest_rq(struct task_struct *task)
      * Otherwise, we consult the sched_domains span maps to figure
      * out which CPU is logically closest to our hot cache data.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - current cpu가 lowest_mask에 속해있지 않은지를 검사한다.
+ */
     if (!cpumask_test_cpu(this_cpu, lowest_mask))
         this_cpu = -1; /* Skip this_cpu opt if not among lowest */
 
     rcu_read_lock();
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - 밑에서부터 위로 올라간다.
+ */
     for_each_domain(cpu, sd) {
+/*
+ * IAMROOT, 2023.02.11:
+ * - SD_WAKE_AFFINE이 있는 domain을 찾는다.
+ */
         if (sd->flags & SD_WAKE_AFFINE) {
             int best_cpu;
 
@@ -1953,18 +2198,31 @@ static int find_lowest_rq(struct task_struct *task)
              * "this_cpu" is cheaper to preempt than a
              * remote processor.
              */
+/*
+ * IAMROOT, 2023.02.11:
+ * - current cpu를 선택할수 있는 상황에서 sd에 current cpu가 포함되있다면
+ *   바로 선택한다.
+ */
             if (this_cpu != -1 &&
                 cpumask_test_cpu(this_cpu, sched_domain_span(sd))) {
                 rcu_read_unlock();
                 return this_cpu;
             }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 위의 상황이 아니라면 best_cpu를 찾는다.(그냥 적당히 숝서대로찾는다)
+ */
             best_cpu = cpumask_any_and_distribute(lowest_mask,
                                   sched_domain_span(sd));
             if (best_cpu < nr_cpu_ids) {
                 rcu_read_unlock();
                 return best_cpu;
             }
+/*
+ * IAMROOT, 2023.02.11:
+ * - 여기까지 왔으면 sd에 소속되있지 않다. 상위 domain으로 간다.
+ */
         }
     }
     rcu_read_unlock();
@@ -1974,17 +2232,35 @@ static int find_lowest_rq(struct task_struct *task)
      * just give the caller *something* to work with from the compatible
      * locations.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - domain에서 못찾았으면, lowest_mask에 current cpu가 있엇을 경우 그냥
+ *   current cpu로 선택한다.
+ */
     if (this_cpu != -1)
         return this_cpu;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - lowest_mask에서 아무거나 고른다.
+ */
     cpu = cpumask_any_distribute(lowest_mask);
     if (cpu < nr_cpu_ids)
         return cpu;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - lowest도 못찾앗다..
+ */
     return -1;
 }
 
 /* Will lock the rq it finds */
+/*
+ * IAMROOT, 2023.02.11:
+ * - @task보다 우선순위가 낮은 lowest_rq를 찾는다.
+ *   찾아지면 double lock 건채로 lowest_rq return.
+ */
 static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
 {
     struct rq *lowest_rq = NULL;
@@ -1994,6 +2270,10 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
     for (tries = 0; tries < RT_MAX_TRIES; tries++) {
         cpu = find_lowest_rq(task);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 찾는데 실패했거나 rq cpu와 같으면 break.
+ */
         if ((cpu == -1) || (cpu == rq->cpu))
             break;
 
@@ -2005,6 +2285,15 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
              * retrying does not release any lock and is unlikely
              * to yield a different result.
              */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   대상 rq에는 우선 순위가 같거나 더 높은 작업이 있으며 재시도해도 
+ *   잠금이 해제되지 않으며 다른 결과가 나올 가능성이 없습니다.
+. 
+ * - lowest를 찾았는데 lowest가 @task보다 우선순위가 높은 상태.
+ *   그냥 빠져나간다.
+ */
             lowest_rq = NULL;
             break;
         }
@@ -2017,18 +2306,37 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
              * migrated already or had its affinity changed.
              * Also make sure that it wasn't scheduled on its rq.
              */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   실행 대기열을 잠금 해제해야 했습니다. 그 동안 작업이 이미 
+ *   마이그레이션되었거나 선호도가 변경되었을 수 있습니다.
+ *   또한 rq에서 예약되지 않았는지 확인하십시오.
+ *
+ * - double lock을 얻는 중에 경합이 발생됬다. 변동이 발생됬을수도
+ *   있는 상황이라 확인해야된다.
+ */
             if (unlikely(task_rq(task) != rq ||
                      !cpumask_test_cpu(lowest_rq->cpu, &task->cpus_mask) ||
                      task_running(rq, task) ||
                      !rt_task(task) ||
                      !task_on_rq_queued(task))) {
-
+/*
+ * IAMROOT, 2023.02.11:
+ * - 바뀐 상황. break.
+ */
                 double_unlock_balance(rq, lowest_rq);
                 lowest_rq = NULL;
                 break;
             }
         }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 경합이 발생안했거나 경합이 발햇어도 조건에 맞는 상황.
+ *   lock을 얻은 상태에서 다시한번 우선순위 비교를 해본다.
+ *   task보다 낮은 우선순위가 찾아졌으면 break.
+ */
         /* If this rq is still suitable use it. */
         if (lowest_rq->rt.highest_prio.curr > task->prio)
             break;
@@ -2041,6 +2349,10 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
     return lowest_rq;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - pushable task를 한개 빼온다.
+ */
 static struct task_struct *pick_next_pushable_task(struct rq *rq)
 {
     struct task_struct *p;
@@ -2066,20 +2378,47 @@ static struct task_struct *pick_next_pushable_task(struct rq *rq)
  * running task can migrate over to a CPU that is running a task
  * of lesser priority.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   현재 CPU에 RT 작업이 두 개 이상 있는 경우 실행되지 않는 작업이 
+ *   우선 순위가 낮은 작업을 실행 중인 CPU로 마이그레이션할 수 있는지 
+ *   확인합니다.
+ * @pull push_rt_tasks에서는 fasle
+ */
 static int push_rt_task(struct rq *rq, bool pull)
 {
     struct task_struct *next_task;
     struct rq *lowest_rq;
     int ret = 0;
 
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - overload가 안된경우(2개 미만의 task가 있는 경우) push
+ *   할 필요가 없다.
+ */
     if (!rq->rt.overloaded)
         return 0;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - push할 task를 한개 고른다.
+ */
     next_task = pick_next_pushable_task(rq);
     if (!next_task)
         return 0;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - TODO
+ */
 retry:
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - migrate가 안되는 tasdk들은
+ */
     if (is_migration_disabled(next_task)) {
         struct task_struct *push_task = NULL;
         int cpu;
@@ -2087,6 +2426,10 @@ static int push_rt_task(struct rq *rq, bool pull)
         if (!pull || rq->push_busy)
             return 0;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 아에 못찾았거나 rq의 cpu와 같은경우 return 0.
+ */
         cpu = find_lowest_rq(rq->curr);
         if (cpu == -1 || cpu == rq->cpu)
             return 0;
@@ -2097,6 +2440,15 @@ static int push_rt_task(struct rq *rq, bool pull)
          * to this other CPU, instead attempt to push the current
          * running task on this CPU away.
          */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   @next_task보다 우선 순위가 낮은 CPU를 찾았으므로 실행 중이어야 합니다.
+ *   그러나 이를 다른 CPU로 마이그레이션할 수는 없으며 대신 이 CPU에서
+ *   현재 실행 중인 작업을 밀어내려고 시도합니다.
+ *   
+ * - @rq->curr가 push가 가능하면 stop을 시킨후 꺼낸다. (push_cpu_stop 실행)
+ */
         push_task = get_push_task(rq);
         if (push_task) {
             raw_spin_rq_unlock(rq);
@@ -2108,6 +2460,10 @@ static int push_rt_task(struct rq *rq, bool pull)
         return 0;
     }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - TODO
+ */
     if (WARN_ON(next_task == rq->curr))
         return 0;
 
@@ -2172,6 +2528,10 @@ static int push_rt_task(struct rq *rq, bool pull)
     return ret;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - TODO
+ */
 static void push_rt_tasks(struct rq *rq)
 {
     /* push_rt_task will return true if it moved an RT */
@@ -2222,6 +2582,48 @@ static void push_rt_tasks(struct rq *rq)
  * the rt_loop_next will cause the iterator to perform another scan.
  *
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   우선 순위가 높은 작업이 CPU에서 예약되고 우선 순위가 낮은 작업이 
+ *   예약되면 우선 순위가 더 높은 RT 작업이 현재 CPU에서 실행 중이기 
+ *   때문에 다른 CPU에서 실행 대기 중인 RT 작업이 있는지 확인합니다.
+ *   이 경우 여러 RT 작업이 대기열에 있는(오버로드된) CPU는 실행되지 
+ *   않는 대기열에 있는 RT 작업 중 하나를 실행할 수 있는 CPU가 열렸음을 
+ *   알려야 합니다. 
+ *
+ *   과부하된 RT 작업이 있는 모든 CPU는 현재 실행 대기 중인 작업의 우선 
+ *   순위가 가장 높은 CPU를 알 수 있는 방법이 없기 때문에 알림을 받아야 
+ *   합니다. CPU가 많은 컴퓨터에서 수행할 때 대기 시간이 길어지는 것으로 
+ *   나타난 이러한 각 CPU에서 스핀록을 시도하는 대신 CPU에 IPI를 보내 
+ *   실행 대기 중인 과부하된 RT 작업을 푸시하도록 합니다.
+ *
+ *   각 CPU에 IPI를 보내는 것만으로도 문제가 됩니다. 많은 수의 CPU 
+ *   머신에서와 같이 이것은 CPU에서 IPI 스톰을 유발할 수 있습니다. 
+ *   우선 순위가 낮은 작업을 동시에 수행합니다.
+ *
+ *   각 루트 도메인에는 RT 과부하 작업으로 모든 CPU를 반복할 수 있는 
+ *   자체 irq 작업 기능이 있습니다. 과부하된 RT 작업이 있는 모든 CPU는 
+ *   우선 순위를 낮추는 CPU가 하나 이상 있는 경우 확인해야 하므로 실행 
+ *   대기 중인 RT 작업을 푸시 오프하려고 시도하는 단일 irq 작업 반복기가 
+ *   있습니다.
+ *
+ *   CPU가 우선 순위가 낮은 작업을 예약하면 과부하된 RT 작업이 있는 
+ *   각 CPU로 이동하는 irq 작업 반복자를 시작합니다.
+ *   우선 순위가 낮은 작업을 예약하는 첫 번째 CPU만 프로세스를 시작하기 
+ *   때문에 rto_start 변수가 증가하고 원자 결과가 1인 경우 해당 CPU는 
+ *   rto_lock을 사용하려고 시도합니다.
+ *   이렇게 하면 프로세스가 우선 순위가 낮은 작업을 예약하는 모든 
+ *   CPU를 처리하므로 잠금에 대한 높은 경합이 방지됩니다.
+ *
+ *   우선 순위가 낮은 작업을 예약하는 모든 CPU는 rt_loop_next 변수를 
+ *   증가시킵니다. 이렇게 하면 irq 작업 반복자가 CPU가 새로운 낮은 우선 
+ *   순위 작업을 예약할 때마다 반복자가 스캔 중에 있더라도 모든 RT 
+ *   오버로드 CPU를 확인합니다. rt_loop_next를 증가시키면 반복자가 다른 
+ *   스캔을 수행하게 됩니다.
+ *
+ * - rto_mask중에서 그전(rto_cpu)의 next cpu를 고른다.
+ */
 static int rto_next_cpu(struct root_domain *rd)
 {
     int next;
@@ -2240,9 +2642,34 @@ static int rto_next_cpu(struct root_domain *rd)
      * the rto_lock held, but any CPU may increment the rto_loop_next
      * without any locking.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   IPI RT 푸시를 시작할 때 rto_cpu는 -1로 설정되고 rt_next_cpu()는 
+ *   단순히 rto_mask에서 발견된 첫 번째 CPU를 반환합니다.
+ *
+ *   rto_next_cpu()가 rto_cpu가 유효한 CPU로 호출되면 rto_mask에서 
+ *   발견된 다음 CPU를 반환합니다.
+ *
+ *   rto_mask에 남아 있는 CPU가 더 이상 없으면 rto_loop 및 
+ *   rto_loop_next에 대해 확인합니다. rto_loop는 rto_lock이 유지된 
+ *   상태에서만 업데이트되지만 모든 CPU는 잠금 없이 rto_loop_next를 
+ *   증가시킬 수 있습니다.
+ */
     for (;;) {
 
         /* When rto_cpu is -1 this acts like cpumask_first() */
+/*
+ * IAMROOT, 2023.02.11:
+ * - -1부터 시작한다. rto_mask중에서 다음에 선택할 cpu를 정한다.
+ *
+ * - rto_cpu가 -1인 경우
+ *   IPI RT push를 시작하였다. rto_mask에서 발견도니 첫번째 cpu로
+ *   return될 것이다.
+ *
+ * - rto_cpu가 유효한 cpu번호 인경우
+ *   rto_cpu의 다음 cpu로 정해진다.
+ */
         cpu = cpumask_next(rd->rto_cpu, rd->rto_mask);
 
         rd->rto_cpu = cpu;
@@ -2250,6 +2677,13 @@ static int rto_next_cpu(struct root_domain *rd)
         if (cpu < nr_cpu_ids)
             return cpu;
 
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - rto_cpu가 유효한 cpu번호 인경우에 대해서 만약 rto_mask에 더 이상 
+ *   남아있는 cpu가 없으면 아래로 진입한다.
+ *   rto_cpu를 다시 -1로 설정한다.
+ */
         rd->rto_cpu = -1;
 
         /*
@@ -2258,6 +2692,17 @@ static int rto_next_cpu(struct root_domain *rd)
          *
          * Matches WMB in rt_set_overload().
          */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   ACQUIRE는 @next 값이 관찰되기 전에 이루어진 @rto_mask 변경 사항을 
+ *   확인하도록 합니다.
+ *
+ *   rt_set_overload()에서 WMB와 일치합니다.
+ *
+ * - loop가 일어나면 rto_loop와 비교한다. 변경이 발생됬으면 갱신하고
+ *   다시 loop로 동작한다. 그게 아닌 경우 return -1
+ */
         next = atomic_read_acquire(&rd->rto_loop_next);
 
         if (rd->rto_loop == next)
@@ -2279,6 +2724,12 @@ static inline void rto_start_unlock(atomic_t *v)
     atomic_set_release(v, 0);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - IPI RT 푸시 상태인경우 cpu를 골라와서 해당 cpu에 ipi work on을 해준다.
+ * - pull 이 필요한 cpu가 overload된 cpu에 대해서 자신한테 push를 하라는 
+ *   ipi를 보내는 상황이다.
+ */
 static void tell_cpu_to_push(struct rq *rq)
 {
     int cpu = -1;
@@ -2298,6 +2749,17 @@ static void tell_cpu_to_push(struct rq *rq)
      * update to loop_next, and nothing needs to be done here.
      * Otherwise it is finishing up and an ipi needs to be sent.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   rto_cpu는 잠금 상태에서 업데이트됩니다. 유효한 CPU가 있는 경우 
+ *   IPI는 여전히 실행 중이고 loop_next에 대한 업데이트로 인해 계속 
+ *   실행되며 여기서 수행할 작업은 없습니다.
+ *   그렇지 않으면 완료되고 ipi를 보내야 합니다.
+ *
+ * - rto_cpu < 0 : *IPI RT 푸시를 시작한 상태. 이 경우
+ *   cpu를 골라 온다.
+ */
     if (rq->rd->rto_cpu < 0)
         cpu = rto_next_cpu(rq->rd);
 
@@ -2305,6 +2767,12 @@ static void tell_cpu_to_push(struct rq *rq)
 
     rto_start_unlock(&rq->rd->rto_loop_start);
 
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - 위에서 cpu가 골라졌으면 해당 cpu에 ipi work on을 해준다.
+ *   ex) rto_push_irq_work_func
+ */
     if (cpu >= 0) {
         /* Make sure the rd does not get freed while pushing */
         sched_get_rd(rq->rd);
@@ -2313,6 +2781,12 @@ static void tell_cpu_to_push(struct rq *rq)
 }
 
 /* Called from hardirq context */
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - @rq의 모든 pushable task를 push하고, 그 다음 cpu한테도
+ *   (있을 경우) irq work on 요청을 한다.
+ */
 void rto_push_irq_work_func(struct irq_work *work)
 {
     struct root_domain *rd =
@@ -2326,6 +2800,10 @@ void rto_push_irq_work_func(struct irq_work *work)
      * We do not need to grab the lock to check for has_pushable_tasks.
      * When it gets updated, a check is made if a push is possible.
      */
+/*
+ * IAMROOT, 2023.02.11:
+ * - push task를 전부 push 한다.
+ */
     if (has_pushable_tasks(rq)) {
         raw_spin_rq_lock(rq);
         while (push_rt_task(rq, true))
@@ -2336,6 +2814,10 @@ void rto_push_irq_work_func(struct irq_work *work)
     raw_spin_lock(&rd->rto_lock);
 
     /* Pass the IPI to the next rt overloaded queue */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 다음 cpu한테도 push 작업을 하게 한다.
+ */
     cpu = rto_next_cpu(rd);
 
     raw_spin_unlock(&rd->rto_lock);
@@ -2350,6 +2832,10 @@ void rto_push_irq_work_func(struct irq_work *work)
 }
 #endif /* HAVE_RT_PUSH_IPI */
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 
+ */
 static void pull_rt_task(struct rq *this_rq)
 {
     int this_cpu = this_rq->cpu, cpu;
@@ -2368,6 +2854,11 @@ static void pull_rt_task(struct rq *this_rq)
     smp_rmb();
 
     /* If we are the only overloaded CPU do nothing */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 현재 cpu에 overloaded 되있다면 return.
+ *   즉 자기가 overload를 시켜놓은 상태.
+ */
     if (rt_overload_count == 1 &&
         cpumask_test_cpu(this_rq->cpu, this_rq->rd->rto_mask))
         return;
@@ -2655,7 +3146,11 @@ static inline void watchdog(struct rq *rq, struct task_struct *p) { }
  */
 /*
  * IAMROOT, 2023.02.10:
- * - ING. requeue_task_rt 할차례
+ * - 1. exec_runtime 및 rt_runtime 누적
+ *   2. rt_runtime 초과에 따른 reschedule 처리
+ *   3. load sun / avg update
+ *   4. runtime balance
+ *   5. SCHED_RR 처리.
  */
 static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
 {
@@ -2703,14 +3198,13 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
     for_each_sched_rt_entity(rt_se) {
 /*
  * IAMROOT, 2023.02.10:
- * - prev != next 라면 유일한 task가 아니라는 의미. 
- *   task가 한개면 그것만 돌리면 되므로 task가 두개이상이여야
- *   rescheule을 하는 의미가 있다.
+ * - prev != next 라면 유일한 rt entity가 아니라는 의미. 
+ *   즉 같은 우선순위의 entity가 두개이상일때 reschedule을 한다.
  */
         if (rt_se->run_list.prev != rt_se->run_list.next) {
 /*
  * IAMROOT, 2023.02.10:
- * - @p를 rq의 tail에 넣고 rescheduled 요청을 한다. 제일 뒤의 순서로
+ * - @p를 rt_rq의 tail에 넣고 rescheduled 요청을 한다. 제일 뒤의 순서로
  *   옮기는 개념.
  */
             requeue_task_rt(rq, p, 0);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e855e4f571c9..0841d2248e1d 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -883,6 +883,11 @@ struct rt_rq {
 #ifdef CONFIG_SMP
     unsigned int        rt_nr_migratory;
     unsigned int        rt_nr_total;
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - 두개 이상의 rt_task가 있는 경우 1.
+ */
     int            overloaded;
     struct plist_head    pushable_tasks;
 
@@ -1050,6 +1055,10 @@ struct perf_domain {
  */
 struct root_domain {
     atomic_t        refcount;
+/*
+ * IAMROOT, 2023.02.11:
+ * - rt overloaded task 숫자
+ */
     atomic_t        rto_count;
     struct rcu_head        rcu;
     /*
@@ -1096,6 +1105,10 @@ struct root_domain {
     raw_spinlock_t        rto_lock;
     /* These are only updated and read within rto_lock */
     int            rto_loop;
+/*
+ * IAMROOT, 2023.02.11:
+ * - IPI RT 푸시를 시작할 때 rto_cpu는 -1로 설정된다.
+ */
     int            rto_cpu;
     /* These atomics are updated outside of a lock */
     atomic_t        rto_loop_next;
@@ -1308,6 +1321,10 @@ struct rq {
     struct sched_domain __rcu    *sd;
 
     unsigned long        cpu_capacity;
+/*
+ * IAMROOT, 2023.02.11:
+ * - 현재 cpu성능.
+ */
     unsigned long        cpu_capacity_orig;
 
     struct callback_head    *balance_callback;
@@ -1454,6 +1471,10 @@ static inline int cpu_of(struct rq *rq)
 
 #define MDF_PUSH    0x01
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - migration이 안되는 task면 return true.
+ */
 static inline bool is_migration_disabled(struct task_struct *p)
 {
 #ifdef CONFIG_SMP
@@ -1836,6 +1857,10 @@ static inline u64 rq_clock(struct rq *rq)
     return rq->clock;
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 현재시각
+ */
 static inline u64 rq_clock_task(struct rq *rq)
 {
     lockdep_assert_rq_held(rq);
@@ -2075,6 +2100,12 @@ init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
 
 #ifdef CONFIG_SMP
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @func를 등록시켜준다.
+ * - @func : push_rt_tasks
+ *           pull_rt_task
+ */
 static inline void
 queue_balance_callback(struct rq *rq,
                struct callback_head *head,
@@ -2103,7 +2134,29 @@ queue_balance_callback(struct rq *rq,
  */
 /*
  * IAMROOT, 2022.09.03:
- * - tree 구조로 되있다. sched domain 위로 올라간다.
+ */
+/*
+ * IAMROOT, 2023.02.11:
+ * ----
+ * - schedule domain
+ *   -- SMT  : l1 cache 공유 
+ *   -- MC   : l2 cache 공유
+ *   -- DIE  : l3 cache 공유
+ *   -- NUMA : memory 공유 numa level 1, 2, 3, 4로 세분화되기도한다.
+ *   ex) SMT :  0, 1, MC : 0, 1, 2, 3, DIE : 0, 1, 2, 3, 4, 5, 6, 7
+ *   이라고 가정.
+ *   0번 cpu기준으로 SMT의 1번이 가장 가깝고 그다음 MC의 2, 3이 가깝고
+ *   그다음 DIE의 4, 5, 6, 7이 가까울것이다.
+ *   이런 묶음으로 domain을 구성하여 가까운 cpu를 찾아가는 개념.
+ *
+ *   -- 자기가 속한 domain은 span을 보고 금방 알아낸다.
+ *
+ * - schedule group
+ *   -- cgroup의 group schedule과는 다른 개념.
+ *   -- schedule domain의 아래 단계 개념
+ * ---
+ * - tree 구조로 되있다. sched domain 위로(SMT -> MC -> DIE -> NUMA)
+ *   올라간다.
  */
 #define for_each_domain(cpu, __sd) \
     for (__sd = rcu_dereference_check_sched_domain(cpu_rq(cpu)->sd); \
@@ -2692,6 +2745,11 @@ static inline void put_prev_task(struct rq *rq, struct task_struct *prev)
     prev->sched_class->put_prev_task(rq, prev);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - exec_start를 갱신하고 선택된 @p를 pushable에서 dequeue한다.
+ *   ex) rt : set_next_task_rt()
+ */
 static inline void set_next_task(struct rq *rq, struct task_struct *next)
 {
     next->sched_class->set_next_task(rq, next, false);
@@ -2770,18 +2828,35 @@ extern void trigger_load_balance(struct rq *rq);
 
 extern void set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask, u32 flags);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @rq->curr가 움직일수있는 상태인지 확인한다. 가능하면 ref를 얻고 
+ *   return task.
+ */
 static inline struct task_struct *get_push_task(struct rq *rq)
 {
     struct task_struct *p = rq->curr;
 
     lockdep_assert_rq_held(rq);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 이미 누군가 push를 할려고한다.
+ */
     if (rq->push_busy)
         return NULL;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 이 task은 허락된 cpu가 한개밖에 없어 이동을 못한다.
+ */
     if (p->nr_cpus_allowed == 1)
         return NULL;
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - migrate disable
+ */
     if (p->migration_disabled)
         return NULL;
 
@@ -3049,6 +3124,19 @@ extern void double_rq_lock(struct rq *rq1, struct rq *rq2);
  * reduces latency compared to the unfair variant below.  However, it
  * also adds more overhead and therefore may reduce throughput.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   fair double_lock_balance: 모든 호출에서 추가 원자적 작업을 강제하는 
+ *   비용으로 공정한 방식으로 두 rq-> 잠금을 안전하게 획득합니다. 이렇게 
+ *   하면 이 아키텍처에서 spinlock_t와 동일한 기본 정책을 사용하여 
+ *   double_lock을 획득할 수 있으므로 아래의 불공평한 변형에 비해 대기 
+ *   시간이 줄어듭니다. 그러나 더 많은 오버헤드가 추가되므로 처리량이 
+ *   줄어들 수 있습니다.
+ *
+ * - double lock을 얻는다. preempt은 무조건 경합한다.
+ *  return 1.
+ */
 static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
     __releases(this_rq->lock)
     __acquires(busiest->lock)
@@ -3068,6 +3156,17 @@ static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
  * grant the double lock to lower CPUs over higher ids under contention,
  * regardless of entry order into the function.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - papago
+ *   Unfair double_lock_balance: 진입 시 잠금이 이미 적절한 순서로 되어 
+ *   있는 경우 추가적인 원자적 작업을 제거하여 대기 시간을 희생하여 
+ *   처리량을 최적화합니다. 이것은 더 낮은 CPU ID를 선호하며 함수에 대한 
+ *   항목 순서에 관계없이 경합 중인 더 높은 ID보다 더 낮은 CPU에 이중 
+ *   잠금을 부여합니다.
+ *
+ * - double lock을 얻는다. 경합없이 얻으면 return 0. 있으면 return 1.
+ */
 static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
     __releases(this_rq->lock)
     __acquires(busiest->lock)
@@ -3095,6 +3194,11 @@ static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
 /*
  * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - double lock 획득.
+ * - double lock을 얻는다. 경합없이 얻으면 return 0. 있으면 return 1.
+ */
 static inline int double_lock_balance(struct rq *this_rq, struct rq *busiest)
 {
     lockdep_assert_irqs_disabled();
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 905b40d6ad8c..1eea6dbc9c06 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -508,6 +508,10 @@ void rq_attach_root(struct rq *rq, struct root_domain *rd)
         call_rcu(&old_rd->rcu, free_rootdomain);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - ref up
+ */
 void sched_get_rd(struct root_domain *rd)
 {
     atomic_inc(&rd->refcount);
@@ -667,6 +671,11 @@ DEFINE_PER_CPU(struct sched_domain_shared __rcu *, sd_llc_shared);
 DEFINE_PER_CPU(struct sched_domain __rcu *, sd_numa);
 DEFINE_PER_CPU(struct sched_domain __rcu *, sd_asym_packing);
 DEFINE_PER_CPU(struct sched_domain __rcu *, sd_asym_cpucapacity);
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - HMP로 동작하는 경우.
+ */
 DEFINE_STATIC_KEY_FALSE(sched_asym_cpucapacity);
 
 static void update_top_cache_domain(int cpu)
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 05ee3eaecb5f..e2d7720c17e5 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -75,12 +75,21 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
 }
 
 /* signal completion unless @done is NULL */
+/*
+ * IAMROOT, 2023.02.11:
+ * - @done에 대해서 complete를 해준다.
+ */
 static void cpu_stop_signal_done(struct cpu_stop_done *done)
 {
     if (atomic_dec_and_test(&done->nr_todo))
         complete(&done->completion);
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @work에 @stopper->works를 추가한다.
+ *   @wakeq에 @stopper task를 추가한다.
+ */
 static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
                     struct cpu_stop_work *work,
                     struct wake_q_head *wakeq)
@@ -90,6 +99,11 @@ static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
 }
 
 /* queue @work to @stopper.  if offline, @work is completed immediately */
+/*
+ * IAMROOT, 2023.02.11:
+ * - stop queue work에 @work를 넣고 깨운다.
+ *   동작중인 task를 강제로 stop시키고 빼오기 위함이다
+ */
 static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 {
     struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
@@ -100,12 +114,23 @@ static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
     preempt_disable();
     raw_spin_lock_irqsave(&stopper->lock, flags);
     enabled = stopper->enabled;
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - enable : queue work동작을 한다.,
+ *   work->done : 기존 작업이 done인 상태. complete전송.
+ *  
+ */
     if (enabled)
         __cpu_stop_queue_work(stopper, work, &wakeq);
     else if (work->done)
         cpu_stop_signal_done(work->done);
     raw_spin_unlock_irqrestore(&stopper->lock, flags);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - stopper를 깨운다.
+ */
     wake_up_q(&wakeq);
     preempt_enable();
 
@@ -381,6 +406,10 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
  * true if cpu_stop_work was queued successfully and @fn will be called,
  * false otherwise.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - stopper는 cpu_stopper_thread함수를 통해서 work의 @fn을 호출할것이다.
+ */
 bool stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
             struct cpu_stop_work *work_buf)
 {
@@ -539,8 +568,7 @@ extern void sched_set_stop_task(int cpu, struct task_struct *stop);
 
 static void cpu_stop_create(unsigned int cpu)
 {
-    sched_set_stop_task(cpu, per_cpu(cpu_stopper.thread, cpu));
-}
+    sched_set_stop_task(cpu, per_cpu(cpu_stopper.thread, cpu)); }
 
 static void cpu_stop_park(unsigned int cpu)
 {
@@ -549,6 +577,10 @@ static void cpu_stop_park(unsigned int cpu)
     WARN_ON(!list_empty(&stopper->works));
 }
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - @cpu에 대한 stopper를 enable하고 thread를 unpark한다.
+ */
 void stop_machine_unpark(int cpu)
 {
     struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
@@ -567,6 +599,14 @@ static struct smp_hotplug_thread cpu_stop_threads = {
     .selfparking        = true,
 };
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - cpu_stopper 초기화. smpboot_register_percpu_thread()함수에서 
+ *   thread가 만들어지고, stopper실행시 cpu_stopper_thread()을 통해
+ *   cpu_stop_work에 등록되는 fn들이 호출될것이다.
+ * - ps -ef를 통해서 migration/X가 항상 있는게 확인된다.
+ * - stopper thread는 deadline보다도 높은 우선순위를 가진다.
+ */
 static int __init cpu_stop_init(void)
 {
     unsigned int cpu;
diff --git a/lib/cpumask.c b/lib/cpumask.c
index a0434997fd0e..134a1ad9a650 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -260,18 +260,35 @@ static DEFINE_PER_CPU(int, distribute_cpu_mask_prev);
  *
  * Returns >= nr_cpu_ids if the intersection is empty.
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 이전에 사용한 cpu의 next번호를 @src1p, @src2p의 and에서 찾는다.
+ */
 int cpumask_any_and_distribute(const struct cpumask *src1p,
                    const struct cpumask *src2p)
 {
     int next, prev;
 
     /* NOTE: our first selection will skip 0. */
+/*
+ * IAMROOT, 2023.02.11:
+ * - 이전에 선택한 cpu의 next를 src1p, src2p가 겹치는 것중에서 고른다.
+ */
     prev = __this_cpu_read(distribute_cpu_mask_prev);
 
     next = cpumask_next_and(prev, src1p, src2p);
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - 못찾앗으면 그냥 겹치는것중에 처음것을 고른다.
+ */
     if (next >= nr_cpu_ids)
         next = cpumask_first_and(src1p, src2p);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - 찾앗으면 prev로 기록한다.
+ */
     if (next < nr_cpu_ids)
         __this_cpu_write(distribute_cpu_mask_prev, next);
 
diff --git a/lib/plist.c b/lib/plist.c
index 0d86ed7a76ac..f18ec2c50402 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -109,11 +109,28 @@ void plist_add(struct plist_node *node, struct plist_head *head)
  * @node:    &struct plist_node pointer - entry to be removed
  * @head:    &struct plist_head pointer - list head
  */
+/*
+ * IAMROOT, 2023.02.11:
+ * - plist(priority list)
+ *   우선순위가 동일한것을 생략한 list한개와, 모두 포함되있는 list 한개가
+ *   있는 개념의 list.
+ * - node_list, prio_list에서 각각 한개씩 지운다.
+ *   단 prio_list에서 삭제함으로써 비워지게 되면 다음 node를 추가한다.
+ */
 void plist_del(struct plist_node *node, struct plist_head *head)
 {
     plist_check_head(head);
 
+/*
+ * IAMROOT, 2023.02.11:
+ * - node단위의 prio_list 에서 
+ */
     if (!list_empty(&node->prio_list)) {
+
+/*
+ * IAMROOT, 2023.02.11:
+ * - 2개 이상인 경우에 next가 empty인 경우 prio_list 한개를 next에 옮긴다.
+ */
         if (node->node_list.next != &head->node_list) {
             struct plist_node *next;
 
 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 617
» [커널 18차] 90주차 kkr 2023.02.13 63
181 [커널 19차] 38 주차 Min 2023.02.11 44
180 [커널 19차] 37 주차 Min 2023.02.04 478
179 [커널 19차] 36 주차 Min 2023.01.28 85
178 [커널 18차] 88주차 kkr 2023.01.28 54
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 101
172 [커널 19차] 33 주차 Min 2022.12.31 50
171 [커널 17차] 117 ~ 119주차 ㅇㅇㅇ 2022.12.25 60
170 [커널 19차] 31 주차 Min 2022.12.17 63
169 [커널 19차] 30 주차 Min 2022.12.10 61
168 [커널 17차] 112 ~ 116주차 ㅇㅇㅇ 2022.12.05 71
167 [커널 18차] 80주차 kkr 2022.12.03 154
166 [커널 19차] 28 ~ 29 주차 Min 2022.12.03 35
165 [커널 19차] 27 주차 Min 2022.11.22 82
164 [커널 18차] 78주차 kkr 2022.11.19 181
163 [커널 19차] 25 ~ 26 주차 Min 2022.11.14 70
XE Login