[커널 18차] 113주차

2023.07.22 22:21

kkr 조회 수:78

RCU 시작.

git : https://github.com/iamroot18/5.10/commit/1e6b7727f601fd52d5457025bf541bd1440edd37

diff --git a/iamroot18/rcu/README.md b/iamroot18/rcu/README.md
index 78d2c5d30077..7f984463adcc 100644
--- a/iamroot18/rcu/README.md
+++ b/iamroot18/rcu/README.md
@@ -12,3 +12,6 @@ http://www2.rdrop.com/users/paulmck/RCU/RCU.2018.11.21c.PSU-full.pdf
 
 4. Tiny-RCU Code Walkthrough on LWN.net
 https://lwn.net/Articles/323929/#Tiny-RCU%20Code%20Walkthrough
+
+5. 문c블로그
+http://jake.dothome.co.kr/rcu/
diff --git a/include/linux/rcu_segcblist.h b/include/linux/rcu_segcblist.h
index 3db96c4f45fd..b10ca1d7881f 100644
--- a/include/linux/rcu_segcblist.h
+++ b/include/linux/rcu_segcblist.h
@@ -57,9 +57,21 @@ struct rcu_cblist {
  * are already ready to invoke) or for RCU_NEXT_TAIL (whose callbacks have
  * not yet been assigned a grace-period number).
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 제일 앞에 있는 segment.
+ */
 #define RCU_DONE_TAIL        0    /* Also RCU_WAIT head. */
 #define RCU_WAIT_TAIL        1    /* Also RCU_NEXT_READY head. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 마지막 segment 전 segment
+ */
 #define RCU_NEXT_READY_TAIL    2    /* Also RCU_NEXT head. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 마지막 segment
+ */
 #define RCU_NEXT_TAIL        3
 #define RCU_CBLIST_NSEGS    4
 
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 612cc57da815..00a5dd48423f 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -36,6 +36,13 @@
 #include <linux/cpumask.h>
 
 #define ULONG_CMP_GE(a, b)    (ULONG_MAX / 2 >= (a) - (b))
+/*
+ * IAMROOT, 2023.07.22:
+ * - a < b
+ *   a = 1, b = 2 => true 
+ *   b = 2, a = 1 => false
+ *   b = 1, b = 1 => false
+ */
 #define ULONG_CMP_LT(a, b)    (ULONG_MAX / 2 < (a) - (b))
 #define ulong2long(a)        (*(long *)(&(a)))
 #define USHORT_CMP_GE(a, b)    (USHRT_MAX / 2 >= (unsigned short)((a) - (b)))
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
index 24b5f2c2de87..0a60fe88d78f 100644
--- a/kernel/rcu/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -21,6 +21,10 @@
  */
 
 #define RCU_SEQ_CTR_SHIFT    2
+/*
+ * IAMROOT, 2023.07.22:
+ * - 0b11
+ */
 #define RCU_SEQ_STATE_MASK    ((1 << RCU_SEQ_CTR_SHIFT) - 1)
 
 /*
@@ -84,6 +88,22 @@ static inline void rcu_seq_end(unsigned long *sp)
  * power of the number of low-order bits reserved for state, then rounded up to
  * the next value in which the state bits are all zero.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   rcu_seq_snap - 업데이트 측 시퀀스 번호의 스냅샷을 찍습니다.
+ *
+ *   이 함수는 현재 시간 이후 전체 유예 기간이 경과했음을 나타내는 유예 기간 
+ *   시퀀스 번호의 가장 빠른 값을 반환합니다. 유예 기간 시퀀스 번호가 이 값에 
+ *   도달하면 현재 시간 이전에 등록된 모든 콜백을 호출하는 것이 안전합니다. 
+ *   이 값은 현재 유예 기간 숫자에 상태용으로 예약된 하위 비트 수의 2제곱을 
+ *   더한 다음 상태 비트가 모두 0인 다음 값으로 반올림됩니다.
+ *
+ * - @sp값보다 조금 더 뒤의 값을 snap값(1 or 2칸뒤)으로 사용한다.
+ *   ex) sp == 4 => 8 (idle이라 안정적인 상태. + 1칸만 하면되면 개념)
+ *       sp == 5 => 12 (complete가 안된상태. +1칸만으론 global과 
+ *       cpu가 너무 가깝다. 그래서 2칸뒤로 하는 개념.)
+ */
 static inline unsigned long rcu_seq_snap(unsigned long *sp)
 {
     unsigned long s;
@@ -94,6 +114,10 @@ static inline unsigned long rcu_seq_snap(unsigned long *sp)
 }
 
 /* Return the current value the update side's sequence number, no ordering. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - return @*sp
+ */
 static inline unsigned long rcu_seq_current(unsigned long *sp)
 {
     return READ_ONCE(*sp);
@@ -120,6 +144,18 @@ static inline bool rcu_seq_done(unsigned long *sp, unsigned long s)
 /*
  * Has a grace period completed since the time the old gp_seq was collected?
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - @new가 complete됬으면 return true.
+ * - @new의 하위 2bit를 제외하고 비교한다. old < new 
+ *
+ * - 하위 2bit는 idle / gp 여부. 상위는 seq개념. 다음과 같이 생각될수있다.
+ *
+ * - 0------1----4-------5 ------8 ...
+ *   | idle | gp | idle  | gp    |
+ *
+ * - old = 5 new = 8 => 4에 대한 gp는 완료됬다. return true
+ */
 static inline bool rcu_seq_completed_gp(unsigned long old, unsigned long new)
 {
     return ULONG_CMP_LT(old, new & ~RCU_SEQ_STATE_MASK);
diff --git a/kernel/rcu/rcu_segcblist.c b/kernel/rcu/rcu_segcblist.c
index aaa111237b60..f40b3fff14ce 100644
--- a/kernel/rcu/rcu_segcblist.c
+++ b/kernel/rcu/rcu_segcblist.c
@@ -79,6 +79,10 @@ struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp)
 }
 
 /* Set the length of an rcu_segcblist structure. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - @rsclp->len = v;
+ */
 static void rcu_segcblist_set_len(struct rcu_segcblist *rsclp, long v)
 {
 #ifdef CONFIG_RCU_NOCB_CPU
@@ -107,18 +111,30 @@ long rcu_segcblist_n_segment_cbs(struct rcu_segcblist *rsclp)
 }
 
 /* Set the length of a segment of the rcu_segcblist structure. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - seglen[seg] = v;
+ */
 static void rcu_segcblist_set_seglen(struct rcu_segcblist *rsclp, int seg, long v)
 {
     WRITE_ONCE(rsclp->seglen[seg], v);
 }
 
 /* Increase the numeric length of a segment by a specified amount. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - @seg에 해당하는 seglen을 +v 한다.
+ */
 static void rcu_segcblist_add_seglen(struct rcu_segcblist *rsclp, int seg, long v)
 {
     WRITE_ONCE(rsclp->seglen[seg], rsclp->seglen[seg] + v);
 }
 
 /* Move from's segment length to to's segment. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - @from의 len을 @to으로 옮긴다.
+ */
 static void rcu_segcblist_move_seglen(struct rcu_segcblist *rsclp, int from, int to)
 {
     long len;
@@ -135,6 +151,10 @@ static void rcu_segcblist_move_seglen(struct rcu_segcblist *rsclp, int from, int
 }
 
 /* Increment segment's length. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - @seg에 해당하는 seglen을 1증가시킨다.
+ */
 static void rcu_segcblist_inc_seglen(struct rcu_segcblist *rsclp, int seg)
 {
     rcu_segcblist_add_seglen(rsclp, seg, 1);
@@ -207,6 +227,46 @@ static void rcu_segcblist_inc_seglen(struct rcu_segcblist *rsclp, int seg)
  * so that the module unloading operation is completely safe.
  *
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   rcu_segcblist 구조의 숫자 길이를 지정된 양(음수일 수 있음)만큼 늘립니다. 
+ *   이로 인해 ->len 필드가 구조의 실제 콜백 수와 일치하지 않을 수 있습니다.
+ *   이 증가는 전후 호출자 액세스와 관련하여 완전히 정렬됩니다.
+ *
+ *   그렇다면 도대체 왜 ->len 필드에 대한 업데이트 전후에 메모리 배리어가 
+ *   필요한 걸까요??? 그 이유는 rcu_barrier()가 각 CPU의 ->len 필드를 잠그지 
+ *   않고 샘플링하고 주어진 CPU의 필드가 0이면 해당 CPU의 IPI를 방지하기 
+ *   때문입니다.
+ *   이것은 물론 대기 및 콜백 호출과 경쟁할 수 있습니다.
+ *   이러한 경쟁 중 하나를 올바르게 처리하지 못하면 rcu_barrier()가 대기해야 
+ *   하는 콜백이 실제로 대기열에 있는 CPU를 IPI하는 데 실패하는 rcu_barrier()가 
+ *   발생할 수 있습니다. 그리고 rcu_barrier()가 그러한 콜백을 기다리는 데 
+ *   실패하면 특정 커널 모듈을 언로드하면 코드가 커널에 더 이상 존재하지 
+ *   않는 함수가 호출됩니다.
+ *
+ *   따라서 1->0 및 0->1에서 ->len 전환은 목록 수정 및 rcu_barrier() 모두와 
+ *   관련하여 신중하게 정렬해야 합니다. 
+ *
+ *   큐잉 케이스는 CASE 1이고 호출 케이스는 CASE 2입니다.
+ *
+ *   사례 1:
+ *   CPU 0에는 대기 중인 콜백이 없지만 CPU 1이 rcu_barrier()를 호출하는 
+ *   것처럼 call_rcu()를 호출한다고 가정합니다. CPU 0의 ->len 필드는 
+ *   0->1에서 전환되며 이는 신중하게 처리해야 하는 전환 중 하나입니다. 
+ *   ->len 업데이트 후 및 rcu_barrier() 시작 시 전체 메모리 배리어가 없으면 
+ *   다음과 같은 일이 발생할 수 있습니다.
+ *
+ *   CPU 0                CPU 1
+ *
+ *   call_rcu().
+ *                      rcu_barrier() sees ->len as 0.
+ *   set ->len = 1.
+ *                      rcu_barrier() does nothing.
+ *                      module is unloaded.
+ *   
+ *
+ */
 void rcu_segcblist_add_len(struct rcu_segcblist *rsclp, long v)
 {
 #ifdef CONFIG_RCU_NOCB_CPU
@@ -226,6 +286,15 @@ void rcu_segcblist_add_len(struct rcu_segcblist *rsclp, long v)
  * callbacks on the structure.  This increase is fully ordered with respect
  * to the callers accesses both before and after.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *  rcu_segcblist 구조체의 숫자 길이를 1 늘립니다.
+ *  이로 인해 ->len 필드가 구조의 실제 콜백 수와 일치하지 않을 수 있습니다. 
+ *  이 증가는 전후 호출자 액세스와 관련하여 완전히 정렬됩니다.
+ *
+ * - @rsclp len을 1 증가시킨다.
+ */
 void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp)
 {
     rcu_segcblist_add_len(rsclp, 1);
@@ -234,6 +303,11 @@ void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp)
 /*
  * Initialize an rcu_segcblist structure.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 원형리스트초기화,
+ *   seglen의 모든값과 len을 0으로 초기화하고 SEGCBLIST_ENABLED을 set한다.
+ */
 void rcu_segcblist_init(struct rcu_segcblist *rsclp)
 {
     int i;
@@ -287,6 +361,10 @@ bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp)
  * Does the specified rcu_segcblist structure contain callbacks that
  * are still pending, that is, not yet ready to be invoked?
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - DONE구간 이후의 대기중인 cb이 있으면 true.
+ */
 bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp)
 {
     return rcu_segcblist_is_enabled(rsclp) &&
@@ -339,13 +417,46 @@ bool rcu_segcblist_nextgp(struct rcu_segcblist *rsclp, unsigned long *lp)
  * for rcu_barrier() to sometimes post callbacks needlessly, but
  * absolutely not OK for it to ever miss posting a callback.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   지정된 rcu_segcblist 구조에 지정된 콜백을 큐에 넣고 필요에 
+ *   따라 계정을 업데이트합니다. ->len 필드는 잠기지 않고 액세스할 
+ *   수 있으므로 WRITE_ONCE()입니다.
+ *   ->len 필드는 rcu_barrier()와 그 친구들이 이 구조에 콜백을 
+ *   게시해야 하는지 여부를 결정하는 데 사용되며, rcu_barrier()가 
+ *   때때로 불필요하게 콜백을 게시하는 것은 괜찮지만 콜백 게시를 
+ *   놓치는 것은 절대 좋지 않습니다.
+ *
+ * - @rsclp의 마지막에 @rhp를 추가한다.
+ */
 void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp,
                struct rcu_head *rhp)
 {
+/*
+ * IAMROOT, 2023.07.22:
+ * - len++
+ */
     rcu_segcblist_inc_len(rsclp);
+/*
+ * IAMROOT, 2023.07.22:
+ * - RCU_NEXT_TAIL len++
+ */
     rcu_segcblist_inc_seglen(rsclp, RCU_NEXT_TAIL);
+/*
+ * IAMROOT, 2023.07.22:
+ * - @rhp가 end이므로 next를 NULL로 한다.
+ */
     rhp->next = NULL;
+/*
+ * IAMROOT, 2023.07.22:
+ * - end인 @rhp을 마지막 node로 설정한다.
+ */
     WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rhp);
+/*
+ * IAMROOT, 2023.07.22:
+ * - end였던 node의 next끝에 rhp를 연결한다.
+ */
     WRITE_ONCE(rsclp->tails[RCU_NEXT_TAIL], &rhp->next);
 }
 
@@ -479,11 +590,24 @@ void rcu_segcblist_insert_pend_cbs(struct rcu_segcblist *rsclp,
  * Advance the callbacks in the specified rcu_segcblist structure based
  * on the current value passed in for the grace-period counter.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   gp 카운터에 대해 전달된 현재 값을 기반으로 지정된 rcu_segcblist 
+ *   구조에서 콜백을 진행합니다.
+ *
+ * - complete된 seq이하구간들중 wait, ready구간만 done으로 옮긴다.
+ *   next_ready구간은 seq에 관계없이 wait로 옮긴다.
+ */
 void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
 {
     int i, j;
 
     WARN_ON_ONCE(!rcu_segcblist_is_enabled(rsclp));
+/*
+ * IAMROOT, 2023.07.22:
+ * - 완료 구간 이후가 비어있으면 return.
+ */
     if (rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL))
         return;
 
@@ -491,7 +615,36 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
      * Find all callbacks whose ->gp_seq numbers indicate that they
      * are ready to invoke, and put them into the RCU_DONE_TAIL segment.
      */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papgo
+ *   ->gp_seq 번호가 호출 준비가 되었음을 나타내는 모든 콜백을 찾아 
+ *   RCU_DONE_TAIL 세그먼트에 넣습니다.
+ * - wait 구간 부터 마지막 전까지 done으로 옮기고, 개수도 옮긴다.
+ */
     for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++) {
+/*
+ * IAMROOT, 2023.07.22:
+ * - 이미 완료 됬다면 break.
+ * - ex) @seq를 20라고 가정. 
+ *   
+ *     DONE WAIT NEXT_READY NEXT      DONE WAIT NEXT_READY NEXT
+ *      12  16       20      24  =>    12                   24
+ *                                     16
+ *                                     20
+ *
+ *   20이하를 DONE으로 이동
+ *
+ * - ex) @seq를 20라고 가정. 20보다 높은 NEXT_READY는 WAIT,
+ *     20는 DONE으로 이동
+ *   
+ *     DONE WAIT NEXT_READY NEXT        DONE WAIT NEXT_READY NEXT
+ *      16  20       24      28   =>     16         24        28
+ *                                       20
+ *   20이하를 DONE으로 이동
+ *
+ *   list개념적으론 위와 비슷해지지만 20미만은 이제 없어질것이다.
+ */
         if (ULONG_CMP_LT(seq, rsclp->gp_seq[i]))
             break;
         WRITE_ONCE(rsclp->tails[RCU_DONE_TAIL], rsclp->tails[i]);
@@ -499,10 +652,27 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
     }
 
     /* If no callbacks moved, nothing more need be done. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - wait부터 break가 발생했으면 할게없다. return.
+ */
     if (i == RCU_WAIT_TAIL)
         return;
-
+/*
+ * IAMROOT, 2023.07.22:
+ * - ptr을 옮기기 시작한다.
+ */
     /* Clean up tail pointers that might have been misordered above. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 옮긴 seg를 done tail로 가리킨다. 즉 empty로 만드는것
+ * - WAIT까지 처리한경우 i = 2(NEXT_READY)
+ *   WAIT -> DONE
+ *   
+ * - NEXT_READY까지 처리 i = 3(NEXT)
+ *   WAIT -> DONE
+ *   NEXT_READY -> DONE
+ */
     for (j = RCU_WAIT_TAIL; j < i; j++)
         WRITE_ONCE(rsclp->tails[j], rsclp->tails[RCU_DONE_TAIL]);
 
@@ -512,9 +682,33 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
      * callbacks.  The overall effect is to copy down the later pointers
      * into the gap that was created by the now-ready segments.
      */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   콜백이 이동되었으므로 이제 호출할 준비가 된 콜백 목록의 중간을 
+ *   가리키는 잘못 정렬된 ->tails[] 포인터를 정리하십시오. 전반적인 효과는 
+ *   나중 포인터를 지금 준비된 세그먼트에 의해 생성된 간격으로 복사하는 
+ *   것입니다.
+ *
+ * - i = 2 로 끝났을때 NEXT_READY를 WAIT자리로 이동시키기 위한 코드.
+ *   for문자체가 큰 의미는 없다.
+ */
     for (j = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++, j++) {
+/*
+ * IAMROOT, 2023.07.22:
+ * - next로 향해있으면 대상이 아니다.
+ *   ex) WAIT까지 처리한경우 i = 2(NEXT_READY) 에서
+ *   WAIT -> DONE의 처리를 위해서 했지만
+ *   NEXT_READY는 건드리지 않았다.
+ *   만약 NEXT_READY -> NEXT를 가리키고 있다면 여기서 break.
+ *   그게 아니라면 WAIT로 옮겨갈것이다.
+ */
         if (rsclp->tails[j] == rsclp->tails[RCU_NEXT_TAIL])
             break;  /* No more callbacks. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - DONE <- WAIT, WAIT <- NEXT_READY로 옮긴다. len도 같이 옮긴다.
+ */
         WRITE_ONCE(rsclp->tails[j], rsclp->tails[i]);
         rcu_segcblist_move_seglen(rsclp, i, j);
         rsclp->gp_seq[j] = rsclp->gp_seq[i];
@@ -536,6 +730,11 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
  * ready to invoke.  Returns true if there are callbacks that won't be
  * ready to invoke until seq, false otherwise.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ * - ING
+ */
 bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq)
 {
     int i, j;
diff --git a/kernel/rcu/rcu_segcblist.h b/kernel/rcu/rcu_segcblist.h
index 04af88ed4fde..0a1401b0b0f4 100644
--- a/kernel/rcu/rcu_segcblist.h
+++ b/kernel/rcu/rcu_segcblist.h
@@ -58,6 +58,8 @@ struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp);
  *   카운트는 나중에 업데이트됩니다.
  *
  *   따라서 rcu_segcblist_n_cbs()를 대신 사용해야 하는 경우가 많습니다.
+ *
+ * - @rsclp가 비어있으면 return true
  */
 static inline bool rcu_segcblist_empty(struct rcu_segcblist *rsclp)
 {
@@ -69,6 +71,8 @@ static inline bool rcu_segcblist_empty(struct rcu_segcblist *rsclp)
  * IAMROOT, 2023.07.17:
  * - papago
  *   분할된 콜백 목록의 콜백 수를 반환합니다. 
+ *
+ * - call 개수 반환.
  */
 static inline long rcu_segcblist_n_cbs(struct rcu_segcblist *rsclp)
 {
@@ -79,6 +83,10 @@ static inline long rcu_segcblist_n_cbs(struct rcu_segcblist *rsclp)
 #endif
 }
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - @rsclp에 flags set.
+ */
 static inline void rcu_segcblist_set_flags(struct rcu_segcblist *rsclp,
                        int flags)
 {
@@ -91,6 +99,10 @@ static inline void rcu_segcblist_clear_flags(struct rcu_segcblist *rsclp,
     rsclp->flags &= ~flags;
 }
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - flags에 @flags가 존재하면 return true.
+ */
 static inline bool rcu_segcblist_test_flags(struct rcu_segcblist *rsclp,
                         int flags)
 {
@@ -106,6 +118,8 @@ static inline bool rcu_segcblist_test_flags(struct rcu_segcblist *rsclp,
  * - papago
  *   예를 들어 지정된 rcu_segcblist가 활성화되어 오프라인 CPU에 해당하지
  *   않습니까? 
+ *
+ * - @rsclp 에서 SEGCBLIST_ENABLED이 있으면 return true.
  */
 static inline bool rcu_segcblist_is_enabled(struct rcu_segcblist *rsclp)
 {
@@ -128,6 +142,10 @@ static inline bool rcu_segcblist_is_offloaded(struct rcu_segcblist *rsclp)
     return false;
 }
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - offload되있으면 true. 아니면 false
+ */
 static inline bool rcu_segcblist_completely_offloaded(struct rcu_segcblist *rsclp)
 {
     int flags = SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP | SEGCBLIST_OFFLOADED;
@@ -148,6 +166,8 @@ static inline bool rcu_segcblist_completely_offloaded(struct rcu_segcblist *rscl
  * - papago
  *   지정된 rcu_segcblist 구조의 지정된 세그먼트를 따르는 모든 세그먼트에
  *   콜백이 비어 있습니까? (지정된 세그먼트에는 콜백이 포함될 수 있습니다.) 
+ *
+ * - @seg index에대한 seg가 비었다면 return true.
  */
 static inline bool rcu_segcblist_restempty(struct rcu_segcblist *rsclp, int seg)
 {
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 60b976fbe603..9fe4620a96d8 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -74,6 +74,10 @@
 
 /* Data structures. */
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - rcu pcpu 
+ */
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, rcu_data) = {
     .dynticks_nesting = 1,
     .dynticks_nmi_nesting = DYNTICK_IRQ_NONIDLE,
@@ -98,6 +102,11 @@ static struct rcu_state rcu_state = {
 static bool dump_tree;
 module_param(dump_tree, bool, 0444);
 /* By default, use RCU_SOFTIRQ instead of rcuc kthreads. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - PREEMPT_RT가 아니면 사용.(default true)
+ *   PREEPRT_RT kernel이면 미사용
+ */
 static bool use_softirq = !IS_ENABLED(CONFIG_PREEMPT_RT);
 #ifndef CONFIG_PREEMPT_RT
 module_param(use_softirq, bool, 0444);
@@ -133,7 +142,7 @@ int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
  *   따라서 이 변수가 RCU_SCHEDULER_INACTIVE일 때 RCU는 단 하나의 작업만 
  *   있다고 가정할 수 있으므로 RCU가 (예를 들어) synchronize_rcu()를 간단한 
  *   barrier()로 최적화할 수 있습니다. 이 변수가 RCU_SCHEDULER_INIT이면 RCU는 
- *   실제 유예 기간을 감지하는 데 필요한 모든 작업을 실제로 수행해야 합니다. 
+ *   실제 gp을 감지하는 데 필요한 모든 작업을 실제로 수행해야 합니다. 
  *   이 변수는 또한 lockdep-RCU 오류 검사에서 부팅 시 가양성을 억제하는 데 
  *   사용됩니다. 마지막으로 생성된 모든 kthread를 포함하여 RCU가 완전히 
  *   초기화된 후 RCU_SCHEDULER_INIT에서 RCU_SCHEDULER_RUNNING으로 전환됩니다.
@@ -507,6 +516,10 @@ static int rcu_is_cpu_rrupt_from_idle(void)
 
 #define DEFAULT_RCU_BLIMIT (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) ? 1000 : 10)
                 // Maximum callbacks per rcu_do_batch ...
+/*
+ * IAMROOT, 2023.07.22:
+ * - 100 ~ 10000개의 pending callback 개수 한도.
+ */
 #define DEFAULT_MAX_RCU_BLIMIT 10000 // ... even during callback flood.
 static long blimit = DEFAULT_RCU_BLIMIT;
 #define DEFAULT_RCU_QHIMARK 10000 // If this many pending, ignore blimit.
@@ -516,6 +529,10 @@ static long qlowmark = DEFAULT_RCU_QLOMARK;
 #define DEFAULT_RCU_QOVLD_MULT 2
 #define DEFAULT_RCU_QOVLD (DEFAULT_RCU_QOVLD_MULT * DEFAULT_RCU_QHIMARK)
 static long qovld = DEFAULT_RCU_QOVLD; // If this many pending, hammer QS.
+/*
+ * IAMROOT, 2023.07.22:
+ * - qoverload calc.
+ */
 static long qovld_calc = -1;      // No pre-initialization lock acquisitions!
 
 module_param(blimit, long, 0444);
@@ -1245,6 +1262,18 @@ static void rcu_disable_urgency_upon_qs(struct rcu_data *rdp)
  * Make notrace because it can be called by the internal functions of
  * ftrace, and making this notrace removes unnecessary recursion calls.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   rcu_is_watching - RCU가 현재 CPU가 유휴 상태가 아니라고 생각하는지 확인
+ *
+ *   RCU가 실행 중인 CPU를 감시하는 경우 true를 반환합니다. 즉, 이 CPU가 안전하게
+ *   RCU 읽기 측 임계 섹션에 들어갈 수 있습니다. 즉, 현재 CPU가 유휴 루프에 
+ *   있지 않거나 인터럽트 또는 NMI 처리기에 있는 경우 true를 반환합니다.
+ *
+ *   ftrace의 내부 함수에 의해 호출될 수 있으므로 notrace를 만들고 이 
+ *   notrace를 만들면 불필요한 재귀 호출이 제거됩니다.
+ */
 notrace bool rcu_is_watching(void)
 {
     bool ret;
@@ -1623,6 +1652,19 @@ static void rcu_gp_kthread_wake(void)
  *
  * The caller must hold rnp->lock with interrupts disabled.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   공간이 있으면 이 CPU에서 아직 할당되지 않은 모든 콜백에 ->gp_seq 
+ *   번호를 할당합니다. 또한 이전에 너무 보수적인 것으로 입증된 ->gp_seq 
+ *   번호가 할당된 모든 콜백을 가속화합니다. 이는 RCU가 유휴 상태일 때 
+ *   콜백에 ->gp_seq 번호가 할당되었지만 루트가 아닌 rcu_node 구조를 
+ *   참조하는 경우 발생할 수 있습니다. 이 함수는 멱등적이므로 반복해서 
+ *   호출해도 문제가 되지 않습니다. RCU gp kthread를 깨워야 
+ *   한다는 플래그를 반환합니다.
+ *
+ *   호출자는 인터럽트가 비활성화된 상태에서 rnp->lock을 유지해야 합니다.
+ */
 static bool rcu_accelerate_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
 {
     unsigned long gp_seq_req;
@@ -1647,6 +1689,17 @@ static bool rcu_accelerate_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
      * accelerating callback invocation to an earlier grace-period
      * number.
      */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   콜백은 종종 불완전한 gp 정보로 등록됩니다. 정확한 정보를 
+ *   얻으려면 전역 잠금을 획득해야 한다는 사실에 관한 것... 따라서 
+ *   RCU는 주어진 콜백이 호출할 준비가 되는 gp 번호를 보수적으로 
+ *   추정합니다. 다음 코드는 이 추정치를 확인하고 가능한 경우 이를 
+ *   개선하여 이전 gp 번호에 대한 콜백 호출을 가속화합니다.
+ *
+ * - 전역 seq의 snap값을 가져온다. 보통 같거나 한칸(4)차 이하.
+ */
     gp_seq_req = rcu_seq_snap(&rcu_state.gp_seq);
     if (rcu_segcblist_accelerate(&rdp->cblist, gp_seq_req))
         ret = rcu_start_this_gp(rnp, rdp, gp_seq_req);
@@ -1699,12 +1752,30 @@ static void rcu_accelerate_cbs_unlocked(struct rcu_node *rnp,
  *
  * The caller must hold rnp->lock with interrupts disabled.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   gp이 완료된 모든 콜백을 RCU_DONE_TAIL 하위 목록으로 
+ *   이동한 다음 나머지 하위 목록을 압축하고 ->gp_seq 번호를 
+ *   RCU_NEXT_TAIL 하위 목록의 모든 콜백에 할당합니다. 이 함수는 
+ *   멱등적이므로 반복적으로 호출해도 문제가 되지 않습니다. 너무 자주 
+ *   호출되지 않는 한...
+ *   RCU gp kthread를 깨워야 하는 경우 true를 반환합니다.
+ *
+ *   호출자는 인터럽트가 비활성화된 상태에서 rnp->lock을 유지해야 합니다.
+ *
+ * - 
+ */
 static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
 {
     rcu_lockdep_assert_cblist_protected(rdp);
     raw_lockdep_assert_held_rcu_node(rnp);
 
     /* If no pending (not yet ready to invoke) callbacks, nothing to do. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - pending중인 cb가 없다면 return false.
+ */
     if (!rcu_segcblist_pend_cbs(&rdp->cblist))
         return false;
 
@@ -1712,6 +1783,15 @@ static bool rcu_advance_cbs(struct rcu_node *rnp, struct rcu_data *rdp)
      * Find all callbacks whose ->gp_seq numbers indicate that they
      * are ready to invoke, and put them into the RCU_DONE_TAIL sublist.
      */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   ->gp_seq 번호가 호출 준비가 되었음을 나타내는 모든 콜백을 찾아 
+ *   RCU_DONE_TAIL 하위 목록에 넣습니다.
+ *
+ * - accelerate를 위해서 완료된 @rnp->gp_seq이하의 cb를 done으로 옮긴다.
+ *   next_ready구간은 wait로 옮긴다.
+ */
     rcu_segcblist_advance(&rdp->cblist, rnp->gp_seq);
 
     /* Classify any remaining callbacks. */
@@ -1752,6 +1832,16 @@ static void rcu_strict_gp_check_qs(void)
  * structure corresponding to the current CPU, and must have irqs disabled.
  * Returns true if the grace-period kthread needs to be awakened.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   CPU 로컬 rcu_data 상태를 업데이트하여 gp의 시작과 끝을 
+ *   기록합니다. 호출자는 현재 CPU에 해당하는 리프 rcu_node 구조의 -> 
+ *   잠금을 보유해야 하며 irqs를 비활성화해야 합니다.
+ *   gp kthread를 깨워야 하는 경우 true를 반환합니다.
+ *
+ * - 
+ */
 static bool __note_gp_changes(struct rcu_node *rnp, struct rcu_data *rdp)
 {
     bool ret = false;
@@ -1760,10 +1850,18 @@ static bool __note_gp_changes(struct rcu_node *rnp, struct rcu_data *rdp)
 
     raw_lockdep_assert_held_rcu_node(rnp);
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - seq 변화 없으면 return.
+ */
     if (rdp->gp_seq == rnp->gp_seq)
         return false; /* Nothing to do. */
 
     /* Handle the ends of any preceding grace periods first. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - gp_seq가 완료됬거나
+ */
     if (rcu_seq_completed_gp(rdp->gp_seq, rnp->gp_seq) ||
         unlikely(READ_ONCE(rdp->gpwrap))) {
         if (!offloaded)
@@ -1799,6 +1897,10 @@ static bool __note_gp_changes(struct rcu_node *rnp, struct rcu_data *rdp)
     return ret;
 }
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - gp과 시작과 끝을 검사한다.
+ */
 static void note_gp_changes(struct rcu_data *rdp)
 {
     unsigned long flags;
@@ -1807,12 +1909,22 @@ static void note_gp_changes(struct rcu_data *rdp)
 
     local_irq_save(flags);
     rnp = rdp->mynode;
+/*
+ * IAMROOT, 2023.07.22:
+ * - this cpu와 상위 node seq가 변화가 없으면 바뀐게 없다는것 + 
+ *   한바퀴 돈게 아니라면 return.
+ */
     if ((rdp->gp_seq == rcu_seq_current(&rnp->gp_seq) &&
          !unlikely(READ_ONCE(rdp->gpwrap))) || /* w/out lock. */
         !raw_spin_trylock_rcu_node(rnp)) { /* irqs already off, so later. */
         local_irq_restore(flags);
         return;
     }
+/*
+ * IAMROOT, 2023.07.22:
+ * - gp seq에 변화가 생긴것을 상위 node seq를 보고 확인했다.
+ */
+
     needwake = __note_gp_changes(rnp, rdp);
     raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
     rcu_strict_gp_check_qs();
@@ -2456,6 +2568,14 @@ rcu_report_qs_rdp(struct rcu_data *rdp)
  * Otherwise, see if this CPU has just passed through its first
  * quiescent state for this grace period, and record that fact if so.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   이 CPU가 아직 인식하지 못하는 새로운 gp이 있는지 확인하고, 
+ *   그렇다면 로컬 rcu_data 상태를 설정하십시오.
+ *   그렇지 않으면 이 gp동안 이 CPU가 첫 번째 qs를 
+ *   통과했는지 확인하고 해당 사실을 기록하십시오.
+ */
 static void
 rcu_check_quiescent_state(struct rcu_data *rdp)
 {
@@ -2480,6 +2600,10 @@ rcu_check_quiescent_state(struct rcu_data *rdp)
      * Tell RCU we are done (but rcu_report_qs_rdp() will be the
      * judge of that).
      */
+/*
+ * IAMROOT, 2023.07.22:
+ * - this cpu가 qs라는것을 report
+ */
     rcu_report_qs_rdp(rdp);
 }
 
@@ -2835,6 +2959,10 @@ static void strict_work_handler(struct work_struct *work)
 }
 
 /* Perform RCU core processing work for the current CPU.  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 
+ */
 static __latent_entropy void rcu_core(void)
 {
     unsigned long flags;
@@ -2848,6 +2976,10 @@ static __latent_entropy void rcu_core(void)
     WARN_ON_ONCE(!rdp->beenonline);
 
     /* Report any deferred quiescent states if preemption enabled. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - SKIP
+ */
     if (!(preempt_count() & PREEMPT_MASK)) {
         rcu_preempt_deferred_qs(current);
     } else if (rcu_preempt_need_deferred_qs(current)) {
@@ -2883,6 +3015,10 @@ static __latent_entropy void rcu_core(void)
         queue_work_on(rdp->cpu, rcu_gp_wq, &rdp->strict_work);
 }
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - RCU_SOFTIRQ
+ */
 static void rcu_core_si(struct softirq_action *h)
 {
     rcu_core();
@@ -2914,6 +3050,10 @@ static void invoke_rcu_core_kthread(void)
 /*
  * Wake up this CPU's rcuc kthread to do RCU core processing.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - RCU_SOFTIRQ callback(rcu_core_si()) 실행한다.
+ */
 static void invoke_rcu_core(void)
 {
     if (!cpu_online(smp_processor_id()))
@@ -2997,6 +3137,10 @@ static int __init rcu_spawn_core_kthreads(void)
 /*
  * Handle any core-RCU processing required by a call_rcu() invocation.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - RCU_SOFTIRQ를 invoke한다.
+ */
 static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head,
                 unsigned long flags)
 {
@@ -3018,6 +3162,19 @@ static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head,
      * invoking rcu_force_quiescent_state() if the newly enqueued callback
      * is the only one waiting for a grace period to complete.
      */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   콜백이 너무 많거나 대기 시간이 너무 긴 경우 gp을 강제
+ *   적용합니다.
+ *   히스테리시스를 적용하고 다른 CPU가 최근에 
+ *   rcu_force_quiescent_state()를 호출한 경우 
+ *   rcu_force_quiescent_state()를 호출하지 마십시오. 또한 새로 
+ *   대기열에 추가된 콜백이 gp이 완료되기를 기다리는 유일한 
+ *   콜백인 경우 rcu_force_quiescent_state()를 호출하지 마십시오.
+ *
+ * - 너무 많이 cb가 쌓여있다. 강제로 fqs(force qs)를 한다.
+ */
     if (unlikely(rcu_segcblist_n_cbs(&rdp->cblist) >
              rdp->qlen_last_fqs_check + qhimark)) {
 
@@ -3052,11 +3209,24 @@ static void rcu_leak_callback(struct rcu_head *rhp)
  * number of queued RCU callbacks.  The caller must hold the leaf rcu_node
  * structure's ->lock.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   해당 CPU의 대기 중인 RCU 콜백 수를 기준으로 현재 CPU에 해당하는 리프 
+ *   rcu_node 구조의 ->cbovldmask 비트를 확인하고 필요한 경우 업데이트합니다. 
+ *   호출자는 리프 rcu_node 구조의 -> 잠금을 보유해야 합니다.
+ *
+ * - overload면 grpmask를 set, 아니면 unset한다.
+ */
 static void check_cb_ovld_locked(struct rcu_data *rdp, struct rcu_node *rnp)
 {
     raw_lockdep_assert_held_rcu_node(rnp);
     if (qovld_calc <= 0)
         return; // Early boot and wildcard value set.
+/*
+ * IAMROOT, 2023.07.22:
+ * - overload됬으면 
+ */
     if (rcu_segcblist_n_cbs(&rdp->cblist) >= qovld_calc)
         WRITE_ONCE(rnp->cbovldmask, rnp->cbovldmask | rdp->grpmask);
     else
@@ -3075,10 +3245,36 @@ static void check_cb_ovld_locked(struct rcu_data *rdp, struct rcu_node *rnp)
  * be holding ->nocb_lock to do this check, which is too heavy for a
  * common-case operation.
  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - papago
+ *   해당 CPU의 대기 중인 RCU 콜백 수를 기준으로 현재 CPU에 해당하는 
+ *   리프 rcu_node 구조의 ->cbovldmask 비트를 확인하고 필요한 경우 
+ *   업데이트합니다. 잠금을 유지할 필요는 없지만 호출자는 인터럽트를 
+ *   비활성화해야 합니다.
+ *
+ *   이 함수는 각각의 gp이 이미 종료된 많은 콜백이 있을 
+ *   가능성을 무시합니다. 이 생략은 이 검사를 수행하기 위해 
+ *   ->nocb_lock을 유지해야 하는 CB가 없는 CPU가 필요하기 때문에 
+ *   일반적인 경우 작업에 너무 무겁습니다.
+ *
+ * - overload여부에 따라 @rnp->cbovldmask에 rdp->grpmask를 set / unset 갱신.
+ *   이미 되있으면 아무것도 안한다.
+ */
 static void check_cb_ovld(struct rcu_data *rdp)
 {
     struct rcu_node *const rnp = rdp->mynode;
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - 다음과 같은경우 return.
+ *   1. qovld_calc이 아직 미설정이거나,
+ *     초기화안됨.
+ *   2. @rdp cb len >=  qovld_calc &&  (rnp->cbovldmask) & rdp->grpmask)
+ *     overload가 됬고 이미 overload가 되있으면
+ *   3. @rdp cb len <  qovld_calc && !(rnp->cbovldmask) & rdp->grpmask)
+ *     overload가 안됬고 overload 표시도 안되있으면
+ */
     if (qovld_calc <= 0 ||
         ((rcu_segcblist_n_cbs(&rdp->cblist) >= qovld_calc) ==
          !!(READ_ONCE(rnp->cbovldmask) & rdp->grpmask)))
@@ -3089,6 +3285,11 @@ static void check_cb_ovld(struct rcu_data *rdp)
 }
 
 /* Helper function for call_rcu() and friends.  */
+/*
+ * IAMROOT, 2023.07.22:
+ * - @head에 @func에 대한 node를 한개 추가하고 RCU_SOFTIRQ를
+ *   invoke한다.
+ */
 static void
 __call_rcu(struct rcu_head *head, rcu_callback_t func)
 {
@@ -3120,6 +3321,10 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
     rdp = this_cpu_ptr(&rcu_data);
 
     /* Add the callback to our list. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - SEGCBLIST_ENABLED 가 안켜져있으면 여기서 enable한다.
+ */
     if (unlikely(!rcu_segcblist_is_enabled(&rdp->cblist))) {
         // This can trigger due to call_rcu() from offline CPU:
         WARN_ON_ONCE(rcu_scheduler_active != RCU_SCHEDULER_INACTIVE);
@@ -3130,11 +3335,24 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
             rcu_segcblist_init(&rdp->cblist);
     }
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - overload 여부 update
+ */
     check_cb_ovld(rdp);
+
+/*
+ * IAMROOT, 2023.07.22:
+ * - nocb인경우 return이거나 lock을 올수도있다. 기본값을 nocb를 사용안한다.
+ */
     if (rcu_nocb_try_bypass(rdp, head, &was_alldone, flags))
         return; // Enqueued onto ->nocb_bypass, so just leave.
     // If no-CBs CPU gets here, rcu_nocb_try_bypass() acquired ->nocb_lock.
     rcu_segcblist_enqueue(&rdp->cblist, head);
+/*
+ * IAMROOT, 2023.07.22:
+ * - debug
+ */
     if (__is_kvfree_rcu_offset((unsigned long)func))
         trace_rcu_kvfree_callback(rcu_state.name, head,
                      (unsigned long)func,
@@ -3197,11 +3415,11 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
 /*
  * IAMROOT, 2023.07.21:
  * - papago
- *   call_rcu() - 유예 기간 후 호출을 위해 RCU 콜백을 대기시킵니다.
+ *   call_rcu() - gp 후 호출을 위해 RCU 콜백을 대기시킵니다.
  *   @head: RCU 업데이트를 대기하는 데 사용할 구조입니다.
- *   @func: 유예 기간 후에 호출되는 실제 콜백 함수.
+ *   @func: gp 후에 호출되는 실제 콜백 함수.
  *
- *   콜백 함수는 전체 유예 기간이 경과한 후, 즉 기존의 모든 RCU 읽기 측 임계 
+ *   콜백 함수는 전체 gp이 경과한 후, 즉 기존의 모든 RCU 읽기 측 임계 
  *   섹션이 완료된 후 호출됩니다. 그러나 콜백 함수는 call_rcu()가 호출된 
  *   후에 시작된 RCU 읽기 측 임계 섹션과 동시에 실행될 수 있습니다.
  *
@@ -3211,7 +3429,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
  *   여기에는 하드웨어 인터럽트 핸들러, softirq 핸들러 및 NMI 핸들러가 
  *   포함됩니다.
  *
- *   모든 CPU는 유예 기간이 기존의 모든 RCU 읽기 측 중요 섹션을 넘어 
+ *   모든 CPU는 gp이 기존의 모든 RCU 읽기 측 중요 섹션을 넘어 
  *   연장된다는 데 동의해야 합니다. CPU가 두 개 이상인 시스템에서 이것은 
  *   "func()"가 호출될 때 각 CPU가 call_rcu() 호출보다 먼저 시작되는 마지막 
  *   RCU 읽기 측 임계 섹션의 끝 이후로 전체 메모리 장벽을 실행했음을 의미합니다. 
@@ -3228,6 +3446,8 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
  *   경우에만 해당).
  *
  *   이러한 메모리 순서 보장의 구현은 여기에 설명되어 있습니다. 
+ *
+ *   - @head에 @func에 대한 node를 추가하고 RCU_SOFTIRQ를 invoke한다.
  */
 void call_rcu(struct rcu_head *head, rcu_callback_t func)
 {
@@ -3840,13 +4060,13 @@ void __init kfree_rcu_scheduler_running(void)
 /*
  * IAMROOT, 2023.07.21:
  * - papago
- *   초기 부팅 중에 차단 유예 기간 대기는 자동으로 유예 기간을 의미합니다. 
+ *   초기 부팅 중에 차단 gp 대기는 자동으로 gp을 의미합니다. 
  *   나중에 이것은 PREEMPTION의 경우가 아닙니다.
  *
- *   그러나 컨텍스트 전환은 !PREEMPTION에 대한 유예 기간이기 때문에 
+ *   그러나 컨텍스트 전환은 !PREEMPTION에 대한 gp이기 때문에 
  *   synchronize_rcu() 또는 synchronize_rcu_expedited()를 실행하는 동안 어느 
- *   시점에 온라인 CPU가 하나만 있는 경우 차단 유예 기간 대기는 자동으로 
- *   유예 기간을 의미합니다. 온라인에 여러 개의 CPU가 있다고 잘못 표시해도 
+ *   시점에 온라인 CPU가 하나만 있는 경우 차단 gp 대기는 자동으로 
+ *   gp을 의미합니다. 온라인에 여러 개의 CPU가 있다고 잘못 표시해도 
  *   괜찮습니다. 실제로는 전체 시간 동안 CPU가 한 개뿐이었는데 약간의 오버헤드가 
  *   추가될 뿐입니다.
  *   RCU는 여전히 올바르게 작동합니다.
@@ -3932,9 +4152,9 @@ static int rcu_blocking_is_gp(void)
 /*
  * IAMROOT, 2023.07.21:
  * - papago
- *   synchronize_rcu - 유예 기간이 경과할 때까지 기다립니다.
+ *   synchronize_rcu - gp이 경과할 때까지 기다립니다.
  *
- *   전체 유예 기간이 경과한 후, 즉 현재 실행 중인 모든 RCU 읽기 측 임계 섹션이
+ *   전체 gp이 경과한 후, 즉 현재 실행 중인 모든 RCU 읽기 측 임계 섹션이
  *   완료된 후 제어가 호출자에게 반환됩니다. 그러나 synchronize_rcu()에서
  *   반환되면 호출자는 synchronize_rcu()가 대기하는 동안 시작된 새로운 RCU 읽기
  *   측 임계 섹션과 동시에 실행될 수 있습니다.
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 305cf6aeb408..43864cbe95f0 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -156,10 +156,18 @@ struct rcu_data {
     union rcu_noqs    cpu_no_qs;    /* No QSes yet for this CPU. */
     bool        core_needs_qs;    /* Core waits for quiescent state. */
     bool        beenonline;    /* CPU online at least once. */
+/*
+ * IAMROOT, 2023.07.22:
+ * - 1바퀴 돌은지에 대한 여부
+ */
     bool        gpwrap;        /* Possible ->gp_seq wrap. */
     bool        exp_deferred_qs; /* This CPU awaiting a deferred QS? */
     bool        cpu_started;    /* RCU watching this onlining CPU. */
     struct rcu_node *mynode;    /* This CPU's leaf of hierarchy */
+/*
+ * IAMROOT, 2023.07.22:
+ * - cpu가 속한 group에대한 bitmask
+ */
     unsigned long grpmask;        /* Mask to apply to leaf qsmask. */
     unsigned long    ticks_this_gp;    /* The number of scheduling-clock */
                     /*  ticks this CPU has handled */
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 4809ceffe565..008021498c83 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -13,6 +13,10 @@
 
 #include "../locking/rtmutex_common.h"
 
+/*
+ * IAMROOT, 2023.07.22:
+ * - PASS
+ */
 static bool rcu_rdp_is_offloaded(struct rcu_data *rdp)
 {
     /*

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 627
228 [커널 20차] 20주차 [2] 이민찬 2023.09.17 182
227 [커널 20차] 19주차 이민찬 2023.09.10 103
226 [커널 20차] 18주차 이민찬 2023.09.03 85
225 [커널 20차] 17주차 이민찬 2023.08.27 129
224 [커널 20차] 16주차 이민찬 2023.08.20 132
223 [커널 19차] 64 주차 Min 2023.08.19 91
222 [커널 20차] 15주차 이민찬 2023.08.13 126
221 [커널 19차] 63 주차 Min 2023.08.12 60
220 [커널 19차] 62 주차 Min 2023.08.05 79
219 [커널 20차] 13주차 이민찬 2023.07.30 106
218 [커널 19차] 61 주차 Min 2023.07.30 45
217 [커널 20차] 12주차 이민찬 2023.07.22 87
216 [커널 19차] 59 ~ 60 주차 Min 2023.07.22 37
» [커널 18차] 113주차 kkr 2023.07.22 78
214 [커널20차] 11주차 이경재 2023.07.15 86
213 [커널20차] 10주차 이경재 2023.07.09 90
212 [커널20차] 9주차 이경재 2023.07.02 85
211 [커널 19차] 58 주차 Min 2023.07.01 41
210 [커널 19차] 56 ~ 57 주차 Min 2023.06.25 40
209 [커널 18차] 109주차 kkr 2023.06.24 33
XE Login