[커널 18차] 106주차
2023.06.03 22:18
EAS 완. select_task_rq_fair 진행중
git : https://github.com/iamroot18/5.10/commit/cfdfd1a007f3faf5d690aa6ceed651f6acd089b2
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 6436c1a5a4f5..a32496cd9fab 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -1401,13 +1401,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node);
* cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
* };
*
- * - rk3399-opp.dtsi
- * opp00 {
- * opp-hz = /bits/ 64 <408000000>;
- * opp-microvolt = <825000 825000 1250000>;
- * clock-latency-ns = <40000>;
- * };
- * -
+ * - em_perf_state 참고
*/
static int __maybe_unused _get_power(unsigned long *mW, unsigned long *kHz,
struct device *dev)
diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
index 4d3cbda57c05..14db30078fab 100644
--- a/include/linux/energy_model.h
+++ b/include/linux/energy_model.h
@@ -27,6 +27,32 @@
* 전력이 될 수 있습니다.
* @cost: 에너지 계산 중에 사용되는 이 수준과 관련된 비용 계수입니다.
* 같음: power * max_frequency / frequency
+ *
+ * - cost 사용은 em_cpu_energy() 참고
+ *
+ * - cost 계산은 _get_power(), em_create_perf_table() 함수 참고
+ * ------- ex --------
+ * - rk3399-opp.dtsi
+ * opp00 {
+ * opp-hz = /bits/ 64 <408000000>;
+ * opp-microvolt = <825000 825000 1250000>;
+ * };
+ * ..
+ * opp05 {
+ * opp-hz = /bits/ 64 <1416000000>;
+ * opp-microvolt = <1125000 1125000 1250000>;
+ * };
+ *
+ * - 가정 첫번째 408MHZ에 대한 opp를 산출
+ * 1. power 계산 예. power(mW) = (100 * mV * mV * MHZ)
+ * 100 * 825 * 825 * (408000000/1000000) = 27769500000
+ * 27769500000 / 1000000000 = 27.7695 = 27
+ *
+ * 2. frequency(kHZ) 계산 예
+ * 408000000 / 1000 = 408000
+ *
+ * 3. cost. cost = fMAX(kHZ) * power(uW) / dst_f(kHZ)
+ * 1416000 * 27000 / 408000 = 93705.8823529 = 93705
*/
struct em_perf_state {
unsigned long frequency;
@@ -154,6 +180,29 @@ void em_dev_unregister_perf_domain(struct device *dev);
* Return: the sum of the energy consumed by the CPUs of the domain assuming
* a capacity state satisfying the max utilization of the domain.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * em_cpu_energy() - 성능 도메인의 CPU가 소비하는 에너지를 추정합니다.
+ *
+ * @pd: 에너지를 추정해야 하는 성능 영역
+ * @max_util: 도메인의 CPU 중 가장 사용률이 높음
+ * @sum_util: 도메인의 모든 CPU 사용률 합계
+ * @allowed_cpu_cap: 감소된 주파수를 반영할 수 있는 @pd의 최대 허용 CPU 용량(열로 인해)
+ *
+ * 이 기능은 CPU 장치에만 사용해야 합니다. 유효성 검사가 없습니다. 즉,
+ * EM이 CPU 유형이고 cpumask가 할당된 경우입니다. 스케줄러 코드에서 꽤
+ * 자주 호출되기 때문에 검사가 없습니다.
+ *
+ * Return: 도메인의 최대 사용률을 충족하는 용량 상태를 가정하여 도메인의
+ * CPU에서 소비한 에너지의 합계입니다.
+ *
+ * @max_util max freq model 값
+ * @sum_util energy model 합값
+ * @allowed_cpu_cap 온도가 고려된 max cpu capa
+ *
+ * - @pd의 energy 소비량 추정. 수식결과는 아래 주석 참고.
+ */
static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
unsigned long max_util, unsigned long sum_util,
unsigned long allowed_cpu_cap)
@@ -173,10 +222,30 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
* max utilization to the allowed CPU capacity before calculating
* effective frequency.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 성능 상태를 예측하기 위해 성능 영역에서 가장 많이 사용되는 CPU의
+ * 사용률을 schedutil과 같이 요청된 빈도에 매핑합니다. 실제 주파수가
+ * 더 낮게 설정될 수 있다는 점도 고려하십시오(열 캡핑으로 인해).
+ * 따라서 유효 주파수를 계산하기 전에 최대 사용률을 허용된 CPU 용량으로
+ * 고정합니다.
+ *
+ * - 최대 freq를 가르키는 ps를 가져온다.
+ */
cpu = cpumask_first(to_cpumask(pd->cpus));
scale_cpu = arch_scale_cpu_capacity(cpu);
ps = &pd->table[pd->nr_perf_states - 1];
+/*
+ * IAMROOT, 2023.06.03:
+ * - 125%증가를 한후 온도가 고려된 cpu capa와 min비교를 하여 max_utll
+ * 로 결과값을 내고, 계산된 결과값의 본래 cpu capa비율만큼 ps->frequency를
+ * 줄인 값을 freq에 저장한다.
+ *
+ * - ex) max_util = 215, scale_cpu = 430, ps->frequency = 1.8G
+ * freq = 900M
+ */
max_util = map_util_perf(max_util);
max_util = min(max_util, allowed_cpu_cap);
freq = map_util_freq(max_util, ps->frequency, scale_cpu);
@@ -185,6 +254,14 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
* Find the lowest performance state of the Energy Model above the
* requested frequency.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 요청된 주파수보다 높은 에너지 모델의 가장 낮은 성능 상태를 찾습니다.
+ *
+ * - freq랑 제일 높은쪽으로 가까운 ps를 찾는다.
+ * ex) freq = 900M, ps0 = 890, ps1 = 910 일때 ps1를 고른다.
+ */
for (i = 0; i < pd->nr_perf_states; i++) {
ps = &pd->table[i];
if (ps->frequency >= freq)
@@ -233,6 +310,49 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
* pd_nrg = ------------------------ (4)
* scale_cpu
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * performance state(ps)에서 도메인의 CPU 용량은 다음과 같이 계산할 수 있습니다.
+ * ps->freq * scale_cpu
+ * ps->cap = -------------------- (1)
+ * cpu_max_freq
+ *
+ * 따라서 유휴 상태 비용(EM에서는 사용할 수 없음)을 무시하면 해당 성능
+ * 상태에서 이 CPU가 소비하는 에너지는 다음과 같이 추정됩니다.
+ * (nrg : energy)
+ *
+ * ps->power * cpu_util
+ * cpu_nrg = -------------------- (2)
+ * ps->cap
+ *
+ * 'cpu_util / ps->cap'은 바쁜 시간의 백분율을 나타냅니다.
+ *
+ * NOTE: 이 계산의 결과는 실제로 전력 단위이지만 일정 기간 동안
+ * 일정하다고 가정하기 때문에 일정 기간 동안 에너지 값으로 조작할 수 있습니다.
+ *
+ * (2)에 (1)을 삽입하면 'cpu_nrg'는 두 항의 곱으로 다시 표현할 수 있습니다.
+ *
+ * ps->power * cpu_max_freq cpu_util
+ * cpu_nrg = ------------------------ * --------- (3)
+ * ps->freq scale_cpu
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * ps->cost
+ *
+ * 첫 번째 용어는 정적이며 em_perf_state 구조체에 'ps->cost'로 저장됩니다.
+ *
+ * 도메인의 모든 CPU는 동일한 마이크로 아키텍처를 가지므로 동일한 'ps->cost'과
+ * 동일한 CPU 용량을 공유합니다. 따라서 도메인의 총 에너지
+ * (모든 CPU 에너지의 단순 합)는 다음과 같이 분해할 수 있습니다.
+ *
+ * ps->cost * \Sum cpu_util
+ * pd_nrg = ------------------------ (4)
+ * scale_cpu
+ *
+ * - ps : max_util의 값은 근전한 freq를 고를 때사용하여 ps를 골랐다.
+ * sun_util : energy model 합산값.
+ * scale_cpu : cpu최대성능
+ */
return ps->cost * sum_util / scale_cpu;
}
diff --git a/include/linux/sched/cpufreq.h b/include/linux/sched/cpufreq.h
index bdd31ab93bc5..13c7f6f041b4 100644
--- a/include/linux/sched/cpufreq.h
+++ b/include/linux/sched/cpufreq.h
@@ -23,12 +23,21 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
void cpufreq_remove_update_util_hook(int cpu);
bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy);
+/*
+ * IAMROOT, 2023.06.03:
+ * - util의 cap대비 비율만큼 freq를 증감한다.
+ * ex) util이 cap의 90%면 freq를 90%로 줄인다.
+ */
static inline unsigned long map_util_freq(unsigned long util,
unsigned long freq, unsigned long cap)
{
return freq * util / cap;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - return 125%
+ */
static inline unsigned long map_util_perf(unsigned long util)
{
return util + (util >> 2);
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 4ebcdd657def..d0376d0263b0 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -106,6 +106,7 @@ static void em_debug_remove_pd(struct device *dev) {}
/*
* IAMROOT, 2023.05.27:
+ * - em_perf_state 주석 참고
* - opp table 값을 읽어서 @pd의 table 을 할당하고 구성한다(cost 포함)
*/
static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 58d7a042c59f..3002d77e5142 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1785,6 +1785,10 @@ uclamp_eff_get(struct task_struct *p, enum uclamp_id clamp_id)
return uc_req;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - @p의 clamp_id에 대한 값을 가져온다.
+ */
unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id)
{
struct uclamp_se uc_eff;
@@ -4448,7 +4452,7 @@ void wake_up_if_idle(int cpu)
/*
* IAMROOT, 2023.05.20:
- * - 두 cpu간 llc cache 를 공유하는가?
+ * - 두 cpu간 llc(last level cache) 를 공유하는가?
*/
bool cpus_share_cache(int this_cpu, int that_cpu)
{
@@ -8591,6 +8595,10 @@ int idle_cpu(int cpu)
*
* Return: 1 if the CPU is currently idle. 0 otherwise.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - @cpu가 idle이면 return 1.
+ */
int available_idle_cpu(int cpu)
{
if (!idle_cpu(cpu))
@@ -8634,6 +8642,34 @@ struct task_struct *idle_task(int cpu)
* based on the task model parameters and gives the minimal utilization
* required to meet deadlines.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 이 함수는 주어진 선형 관계(f = u * f_max)에서 주파수 선택에 사용되는
+ * 주어진 CPU의 유효 사용률을 계산합니다.
+ *
+ * 스케줄러는 다음 메트릭을 추적합니다.
+ *
+ * cpu_util_{cfs,rt,dl,irq}()
+ * cpu_bw_dl()
+ *
+ * 여기서 cfs,rt 및 dl util 번호는 동일한 메트릭 및 동기화 창으로 추적되므로
+ * 직접 비교할 수 있습니다.
+ *
+ * cfs,rt,dl 사용률은 rq->clock_task로 측정한 실행 시간이며 IRQ 및 도용
+ * 시간과 같은 것을 제외합니다. 이러한 후자는 irq 사용률에서 발생합니다.
+ *
+ * DL 대역폭 수 otoh는 측정된 메트릭이 아니라 작업 모델 매개변수를 기반으로
+ * 계산된 값이며 데드라인을 맞추는 데 필요한 최소한의 사용률을 제공합니다.
+ *
+ * @max max cpu capa
+ * - 1. uclamp 미사용, freq 산출, rt가 동작중일때는 return max
+ * - freq 고려
+ * return clamp(cfs + rt) + dl_bw
+ *
+ * - energy 고려
+ * return cfs + rt + dl
+ */
unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
unsigned long max, enum cpu_util_type type,
struct task_struct *p)
@@ -8641,6 +8677,10 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
unsigned long dl_util, util, irq;
struct rq *rq = cpu_rq(cpu);
+/*
+ * IAMROOT, 2023.06.03:
+ * - uclamp가 없는 상황에서, freq 산출목적이고 rt_rq가 runnable이면 return max
+ */
if (!uclamp_is_used() &&
type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
return max;
@@ -8651,6 +8691,15 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
* because of inaccuracies in how we track these -- see
* update_irq_load_avg().
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * IRQ/steal time이 CPU를 포화 상태로 만드는지 확인하기 위한 조기 확인은
+ * 이러한 추적 방법이 부정확하기 때문일 수 있습니다. update_irq_load_avg()를
+ * 참조하십시오.
+ *
+ * - irq에서 사용했던 util이 max를 넘은거같다. return max.
+ */
irq = cpu_util_irq(rq);
if (unlikely(irq >= max))
return max;
@@ -8667,10 +8716,29 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
* When there are no CFS RUNNABLE tasks, clamps are released and
* frequency will be gracefully reduced with the utilization decay.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * RT/DL 작업에 소요된 시간은 CFS 작업에 '손실된' 시간으로 표시되고 동일한
+ * 메트릭을 사용하여 유효 사용률을 추적하기 때문에(PELT 창은 동기화됨) 직접
+ * 추가하여 CPU의 실제 사용률을 얻을 수 있습니다.
+ *
+ * CFS 및 RT 활용은 현재 RUNNABLE 작업에서 요청한 활용 클램프 제약 조건에
+ * 따라 강화되거나 제한될 수 있습니다.
+ *
+ * CFS RUNNABLE 작업이 없으면 클램프가 해제되고 사용률 감소에 따라 빈도가
+ * 점진적으로 감소합니다.
+ * - rt 작업시간을 보정후 freq 산정이라면 clamp.
+ * dl은 빼고, rt까지만 고려해서 clamp를 해주는개념이다.
+ */
util = util_cfs + cpu_util_rt(rq);
if (type == FREQUENCY_UTIL)
util = uclamp_rq_util_with(rq, util, p);
+/*
+ * IAMROOT, 2023.06.03:
+ * - dl은 따로 가져와서 아래에서 clamp된 rt + dl로 max를 고려한다.
+ */
dl_util = cpu_util_dl(rq);
/*
@@ -8682,6 +8750,17 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
* NOTE: numerical errors or stop class might cause us to not quite hit
* saturation when we should -- something for later.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 주파수 선택의 경우 나중에 cpu_bw_dl()을 사용하고 싶기 때문에
+ * cpu_util_dl()을 이 합계의 영구적인 부분으로 만들지는 않지만 CFS+RT+DL
+ * 합계가 포화 상태인지(예: 유휴 시간 없음) 확인해야 합니다. 유휴 시간이
+ * 없을 때 f_max를 선택합니다.
+ *
+ * NOTE: 숫자 오류 또는 중지 클래스로 인해 채도에 도달해야 할 때 채도에
+ * 도달하지 못할 수 있습니다. 나중에 설명하겠습니다.
+ */
if (util + dl_util >= max)
return max;
@@ -8689,6 +8768,13 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
* OTOH, for energy computation we need the estimated running time, so
* include util_dl and ignore dl_bw.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * OTOH, 에너지 계산을 위해 예상 실행 시간이 필요하므로 util_dl을 포함하고
+ * dl_bw를 무시합니다.
+ * - energy 고려면, dl까지 util을 고려한다.
+ */
if (type == ENERGY_UTIL)
util += dl_util;
@@ -8701,6 +8787,14 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
* U' = irq + --------- * U
* max
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 아직 유휴 시간이 있습니다. irq 메트릭을 사용하여 숫자를 더 향상시킵니다.
+ * IRQ/도용 시간은 태스크 클럭에서 숨겨지기 때문에 태스크 번호를 조정해야 합니다.
+ *
+ * - max에 대한 irq비율만큼 util을 scaling한다음에 irq를 더한다.
+ */
util = scale_irq_capacity(util, irq, max);
util += irq;
@@ -8714,6 +8808,20 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
* bw_dl as requested freq. However, cpufreq is not yet ready for such
* an interface. So, we only do the latter for now.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * DEADLINE에 필요한 대역폭은 항상 부여되어야 하는 반면, FAIR 및 RT의 경우
+ * 더 오랜 시간 동안 작업이 표시되지 않을 때 빈도를 우아하게 줄이기 위한
+ * 메커니즘으로 IDLE CPU의 차단된 활용을 사용합니다.
+ *
+ * 이상적으로는 bw_dl을 최소/보장 주파수로 설정하고 util + bw_dl을 요청
+ * 주파수로 설정하고 싶습니다. 그러나 cpufreq는 아직 이러한 인터페이스를
+ * 사용할 준비가 되어 있지 않습니다. 따라서 지금은 후자만 수행합니다.
+ *
+ * - freq일경우 bw_dl에 대한 보정을한다. 주석에선 bw_dl <= return <= util + bw_dl을
+ * 하고 싶어하지만 불가능해서 util + bw_dl만 한다는 설명이다.
+ */
if (type == FREQUENCY_UTIL)
util += cpu_bw_dl(rq);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index d6bc14d040e5..c236797379a1 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5171,6 +5171,11 @@ static inline void update_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
}
#ifndef CONFIG_64BIT
+/*
+ * IAMROOT, 2023.06.03:
+ * - load_last_update_time_copy와 last_update_time이 sync할때까지
+ * 맞춘다.
+ */
static inline u64 cfs_rq_last_update_time(struct cfs_rq *cfs_rq)
{
u64 last_update_time_copy;
@@ -5195,6 +5200,10 @@ static inline u64 cfs_rq_last_update_time(struct cfs_rq *cfs_rq)
* Synchronize entity load avg of dequeued entity without locking
* the previous rq.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - @se cfs_rq의 last_update_time으로 decay한다.
+ */
static void sync_entity_load_avg(struct sched_entity *se)
{
struct cfs_rq *cfs_rq = cfs_rq_of(se);
@@ -7617,6 +7626,10 @@ static struct {
#endif /* CONFIG_NO_HZ_COMMON */
+/*
+ * IAMROOT, 2023.06.03:
+ * - return cfs load
+ */
static unsigned long cpu_load(struct rq *rq)
{
return cfs_rq_load_avg(&rq->cfs);
@@ -7823,6 +7836,22 @@ static int wake_wide(struct task_struct *p)
* scheduling latency of the CPUs. This seems to work
* for the overloaded case.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * wake_affine()의 목적은 우리가 가장 빨리 실행할 수 있는 CPU를 빠르게
+ * 결정하는 것입니다. 속도를 위해 깨어 있는 CPU와 이전 CPU만 고려합니다.
+ *
+ * wake_affine_idle() - '지금'만 고려하여 깨우는 CPU가 캐시 affine이고
+ * 유휴 상태인지 확인합니다.
+ *
+ * wake_affine_weight() - CPU의 평균 스케줄링 대기 시간을 반영하기
+ * 위해 가중치를 고려합니다. 이것은 오버로드된 경우에 작동하는 것 같습니다.
+ *
+ * @sync WF_SYNC set여부. select_task_rq_fair() 참고
+ * - this_cpu, prev_cpu중에 cache affine cpu를 idle위주로 고려해서 선택한다.
+ * 둘다 대상이 없으면 return nr_cpumask_bits
+ */
static int
wake_affine_idle(int this_cpu, int prev_cpu, int sync)
{
@@ -7838,9 +7867,32 @@ wake_affine_idle(int this_cpu, int prev_cpu, int sync)
* a cpufreq perspective, it's better to have higher utilisation
* on one CPU.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * this_cpu가 유휴 상태이면 깨우기가 인터럽트 컨텍스트에서 발생했음을
+ * 의미합니다. 캐시가 공유된 경우에만 이동을 허용하십시오. 그렇지
+ * 않으면 인터럽트 집중 워크로드가 IO 토폴로지 또는 IRQ 선호도 설정에
+ * 따라 모든 작업을 하나의 노드로 강제 실행할 수 있습니다.
+ *
+ * prev_cpu가 유휴 상태이고 캐시 관련성이 있는 경우 마이그레이션을
+ * 피하십시오. 인터럽트의 캐시 핫 데이터가 prev_cpu의 캐시 핫 데이터보다
+ * 더 중요하다는 보장은 없으며 cpufreq 관점에서 볼 때 하나의 CPU에서 더
+ * 높은 활용도를 갖는 것이 좋습니다.
+ *
+ * - this_cpu가 idle, prev_cpu와 cache share.
+ * prev_cpu가 idle이면 prev_cpu를 우선으로 고르고, 아니면 this_cpu
+ * - prev_cpu가 idle일 경우 migrate를 안하고 기존 cpu에서 동작하는 것이
+ * l1 cache의 이득을 조금더 볼수있다고 생각한다.
+ */
if (available_idle_cpu(this_cpu) && cpus_share_cache(this_cpu, prev_cpu))
return available_idle_cpu(prev_cpu) ? prev_cpu : this_cpu;
+/*
+ * IAMROOT, 2023.06.03:
+ * - WF_SYNC참고. prev_cpu는 가능하면 sleep하러 가야된다. 그러므로 this_cpu에서
+ * worker를 동작시켜도 되는 상황이다.
+ */
if (sync && cpu_rq(this_cpu)->nr_running == 1)
return this_cpu;
@@ -7850,6 +7902,12 @@ wake_affine_idle(int this_cpu, int prev_cpu, int sync)
return nr_cpumask_bits;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * @sync WF_SYNC set여부. select_task_rq_fair() 참고
+ * - load 비율 계산을 하여 @this_cpu가 prev_cpu비해 더 여유로우면 this_cpu
+ * 결정. this_cpu를 사용못하면 return nr_cpumask_bits
+ */
static int
wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
int this_cpu, int prev_cpu, int sync)
@@ -7859,22 +7917,46 @@ wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
this_eff_load = cpu_load(cpu_rq(this_cpu));
+/*
+ * IAMROOT, 2023.06.03:
+ * - sync가 있으면 곧 sleep을 할 예정이므로 load가 감소할 것이다.
+ * 그 보정을 취한다.
+ */
if (sync) {
unsigned long current_load = task_h_load(current);
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - this cpu에 current task가 워낙 큰 load를 차지하고 있어
+ * 없어지면 thi_cpu 부하가 없는거랑 마찬가지가 되니 그냥
+ * this_cpu로 선택한다.
+ */
if (current_load > this_eff_load)
return this_cpu;
this_eff_load -= current_load;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - 새로 추가되는 @p에 대한 load를 더해본다.
+ */
task_load = task_h_load(p);
this_eff_load += task_load;
+/*
+ * IAMROOT, 2023.06.03:
+ * - WA_BIAS : default true. imbalance_pct - 100 의 절반을 보정하여
+ * 계산한다.
+ * ex) imbalance_pct = 117 -> 8을 더 보정한다.
+ */
if (sched_feat(WA_BIAS))
this_eff_load *= 100;
this_eff_load *= capacity_of(prev_cpu);
+/*
+ * IAMROOT, 2023.06.03:
+ * - 다른데로 옮겨갈 @p를 prev에서 빼준다.
+ */
prev_eff_load = cpu_load(cpu_rq(prev_cpu));
prev_eff_load -= task_load;
if (sched_feat(WA_BIAS))
@@ -7887,24 +7969,57 @@ wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
* stacking the wakee on top of the waker if no other CPU is
* idle.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 동기화된 경우 prev_eff == this_eff인 경우 select_idle_sibling()이
+ * 다른 CPU가 유휴 상태가 아닌 경우 웨이커 위에 웨이크를 쌓는 것을
+ * 고려하도록 prev_eff_load의 가중치를 조정합니다.
+ * - 동일한 점수일때 this_cpu가 더 유리하도록 한다.
+ */
if (sync)
prev_eff_load += 1;
+/*
+ * IAMROOT, 2023.06.03:
+ * - this_eff_load * prev_cpu_capa < prev_eff_load * this_cpu_capa
+ * 즉 this가 prev보다 비율적으로 덜 바쁘면 this를 선택한다.
+ * 그게 아니면 fail 처리.
+ */
return this_eff_load < prev_eff_load ? this_cpu : nr_cpumask_bits;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - 1. idle로 우선 고려. prev / this / fail
+ * 2. load 비율 고려. this / fail
+ * 3. 그외 prev
+ */
static int wake_affine(struct sched_domain *sd, struct task_struct *p,
int this_cpu, int prev_cpu, int sync)
{
int target = nr_cpumask_bits;
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - WA_IDLE default true
+ * idle인 cpu를 우선으로해서 1차적으로 결정을 한다.
+ */
if (sched_feat(WA_IDLE))
target = wake_affine_idle(this_cpu, prev_cpu, sync);
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - WA_IDLE이 없거나 있었어도 못찾았다. WA_WEIGHT default true.
+ * 위에서 못찾앗으면 load 비율을 따져 this_cpu가 prev보다 유리하면
+ * this_cpu로 선택한다.
+ */
if (sched_feat(WA_WEIGHT) && target == nr_cpumask_bits)
target = wake_affine_weight(sd, p, this_cpu, prev_cpu, sync);
schedstat_inc(p->se.statistics.nr_wakeups_affine_attempts);
+/*
+ * IAMROOT, 2023.06.03:
+ * - 못찾앗으면 prev_cpu
+ */
if (target == nr_cpumask_bits)
return prev_cpu;
@@ -8581,6 +8696,18 @@ static unsigned long cpu_util_without(int cpu, struct task_struct *p)
* Predicts what cpu_util(@cpu) would return if @p was migrated (and enqueued)
* to @dst_cpu.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * @p가 @dst_cpu로 마이그레이션(및 대기열에 포함)된 경우 cpu_util(@cpu)이 반환할
+ * 항목을 예측합니다.
+ *
+ * @cpu 평가 cpu
+ * @dst_cpu 목적 cpu
+ *
+ * - migrate 했을때의(next 상황에서의) util 예상치를 계산한다.
+ * util 과 util_est끼리 따로 계산해서 max값을 계산한다.
+ */
static unsigned long cpu_util_next(int cpu, struct task_struct *p, int dst_cpu)
{
struct cfs_rq *cfs_rq = &cpu_rq(cpu)->cfs;
@@ -8592,11 +8719,27 @@ static unsigned long cpu_util_next(int cpu, struct task_struct *p, int dst_cpu)
* the other cases, @cpu is not impacted by the migration, so the
* util_avg should already be correct.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * @p가 @cpu에서 다른 것으로 마이그레이션하는 경우 해당 기여를 제거합니다.
+ * 또는 @p가 다른 CPU에서 @cpu로 마이그레이션하는 경우 기여도를 추가합니다.
+ * 다른 경우에는 @cpu가 마이그레이션의 영향을 받지 않으므로 util_avg가 이미
+ * 정확해야 합니다.
+ * - cpu == dst_cpu 인경우는 자신(cpu)한테 이동해오는 개념이라 추가되는 개념.
+ * cpu != dst_cpu 인경우는 cpu -> dst_cpu로 가는 개념이라 빼야된다.
+ */
if (task_cpu(p) == cpu && dst_cpu != cpu)
lsub_positive(&util, task_util(p));
else if (task_cpu(p) != cpu && dst_cpu == cpu)
util += task_util(p);
+/*
+ * IAMROOT, 2023.06.03:
+ * - 증간된 util과 est를 비교해서 max로 보정한다.
+ * est가 task가 적어도 이만큼은 동작을해야되는 추정치이므로 이에 대한 고려
+ * (즉 저평가 방지)를 한다.
+ */
if (sched_feat(UTIL_EST)) {
util_est = READ_ONCE(cfs_rq->avg.util_est.enqueued);
@@ -8606,6 +8749,15 @@ static unsigned long cpu_util_next(int cpu, struct task_struct *p, int dst_cpu)
* so just add it (if needed) to "simulate" what will be
* cpu_util() after the task has been enqueued.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 깨우는 동안 작업은 아직 대기열에 추가되지 않고 rq의
+ * cfs_rq->avg.util_est.enqueued에 표시되지 않으므로 필요한 경우 추가하여
+ * 작업 후 cpu_util()이 될 것을 시뮬레이트합니다. 인큐되었습니다.
+ * - 저평가를 방지하는 개념이므로, 빼야되는 상황(dst_cpu != cpu)에 대한 처리는 안하고,
+ * 더해야되는 상황에서만 수행한다.
+ */
if (dst_cpu == cpu)
util_est += _task_util_est(p);
@@ -8622,6 +8774,17 @@ static unsigned long cpu_util_next(int cpu, struct task_struct *p, int dst_cpu)
* to compute what would be the energy if we decided to actually migrate that
* task.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * compute_energy(): @p가 @dst_cpu로 마이그레이션된 경우 @pd가 소비할
+ * 에너지를 추정합니다. compute_energy()는 작업 마이그레이션 후 @pd CPU의
+ * 사용 환경을 예측하고 에너지 모델을 사용하여 해당 작업을 실제로
+ * 마이그레이션하기로 결정한 경우 에너지가 무엇인지 계산합니다.
+ *
+ * - @p가 @dst_cpu로 migrate migrate후의 @pd에 대한 energy를 예측한다.
+ * dst_cpu == -1이면 migrate없는 상황에서의 base값.
+ */
static long
compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
{
@@ -8631,6 +8794,10 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
unsigned long _cpu_cap = cpu_cap;
int cpu;
+/*
+ * IAMROOT, 2023.06.03:
+ * - 온도 capa보정
+ */
_cpu_cap -= arch_scale_thermal_pressure(cpumask_first(pd_mask));
/*
@@ -8642,6 +8809,21 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
* If an entire pd is outside of the current rd, it will not appear in
* its pd list and will not be accounted by compute_energy().
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 현재 rd의 CPU 용량 상태는 동일한 pd에 속한 경우 다른 rd의 CPU에
+ * 의해 구동될 수 있습니다. 따라서 rd span 대신 cpu_online_mask로 pd를
+ * 마스킹하여 이러한 CPU의 사용률도 고려하십시오.
+ *
+ * 전체 pd가 현재 rd 밖에 있는 경우 pd 목록에 나타나지 않으며
+ * compute_energy()에서 계산되지 않습니다.
+ *
+ * - sum_util
+ * energy model 산출 총합
+ * - max_util
+ * max freq util model
+ */
for_each_cpu_and(cpu, pd_mask, cpu_online_mask) {
unsigned long util_freq = cpu_util_next(cpu, p, dst_cpu);
unsigned long cpu_util, util_running = util_freq;
@@ -8656,6 +8838,17 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
* while cpu_util_next is: max(cpu_util + task_util,
* cpu_util_est + _task_util_est)
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - @p가 @cpu로 migrate되는(즉 증가되는 상황) cpu에 대해서의 처리.
+ * - cpu_util_next(cpu, p, -1)
+ * dst_cpu가 없은 예측값을 가져온다.(max(cpu_util, cpu_util_est))
+ * - task_util_est(p)
+ * max(task_util, _task_util_est)
+ *
+ * - cpu_util_next에서 dst_cpu를 넣어서 계산하는 것은 task_util만
+ * 고려가 되지만, 이렇게 task_util_est를 해 좀더 load를 추가 해준다.
+ */
if (cpu == dst_cpu) {
tsk = p;
util_running =
@@ -8668,9 +8861,19 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
* is already enough to scale the EM reported power
* consumption at the (eventually clamped) cpu_capacity.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 바쁜 시간 계산: 비율(sum_util / cpu_capacity)이 (결국 고정된)
+ * cpu_capacity에서 EM 보고된 전력 소비를 확장하기에 이미 충분하기
+ * 때문에 사용률 고정이 필요하지 않습니다.
+ */
cpu_util = effective_cpu_util(cpu, util_running, cpu_cap,
ENERGY_UTIL, NULL);
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - 계산된 util을 온도가 계산된 cpu_capa와 min 비교후 sum_util에 추가한다.
+ */
sum_util += min(cpu_util, _cpu_cap);
/*
@@ -8680,6 +8883,17 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
* NOTE: in case RT tasks are running, by default the
* FREQUENCY_UTIL's utilization can be max OPP.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * Performance domain frequency: utilization 클램핑은
+ * Performance domain frequency 선택에 영향을 미치므로 반드시
+ * 고려해야 합니다.
+ * 메모: RT 작업이 실행 중인 경우 기본적으로 FREQUENCY_UTIL의
+ * utilization는 최대 OPP가 될 수 있습니다.
+ *
+ * - freq 산출은 max_util로하여 max값을 갱신한다.
+ */
cpu_util = effective_cpu_util(cpu, util_freq, cpu_cap,
FREQUENCY_UTIL, tsk);
max_util = max(max_util, min(cpu_util, _cpu_cap));
@@ -8796,6 +9010,18 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
* 2. driven DVFS : freq를 변경해서 해결거나 깨우거나 한다.
* ---------------
*
+ * @prev_cpu sleep을 햇던 cpu
+ * - ex)
+ * pd0 pd1(max 못찾음) pd2 pd3(max 못찾음)
+ * cpu0<-max1 cpu2<-prev cpu4<-max2 cpu6
+ * cpu1 cpu3 cpu5 cpu7
+ * > max를 찾은 pd0, pd2과 prev가 있는 pd1만을 대상으로 base_energy_pd값을 계산
+ * - 전력이득이 있는 cpu를 고른다.
+ * > prev가 있는 pd는 prev_delta를 산출하고, best_delta min비교해서 갱신한다.
+ * > max값이 있는 pd는 best_delta와 현재 pd를 min비교해서 best_delta,
+ * best_energy_cpu를 min 비교 갱신한다.
+ * > 최종적으로, 6%이상의 이득이 있으면 best_energy_cpu를 선택하고, 그게 아니면
+ * prev_cpu로 유지한다.
*/
static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
{
@@ -8816,6 +9042,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
* from sd_asym_cpucapacity spanning over this_cpu and prev_cpu.
*/
sd = rcu_dereference(*this_cpu_ptr(&sd_asym_cpucapacity));
+/*
+ * IAMROOT, 2023.06.03:
+ * - @prev_cpu가 포함된 sd를 parent로 올라가면서 찾는다.
+ */
while (sd && !cpumask_test_cpu(prev_cpu, sched_domain_span(sd)))
sd = sd->parent;
if (!sd)
@@ -8823,16 +9053,32 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
target = prev_cpu;
+/*
+ * IAMROOT, 2023.06.03:
+ * - 경과시간만큼 decay
+ */
sync_entity_load_avg(&p->se);
+/*
+ * IAMROOT, 2023.06.03:
+ * - sleep전에 load가 없엇으면 out. EAS포기.
+ */
if (!task_util_est(p))
goto unlock;
+/*
+ * IAMROOT, 2023.06.03:
+ * - pd 순회 -> pd에 속한 cpu순회
+ */
for (; pd; pd = pd->next) {
unsigned long cur_delta, spare_cap, max_spare_cap = 0;
bool compute_prev_delta = false;
unsigned long base_energy_pd;
int max_spare_cap_cpu = -1;
+/*
+ * IAMROOT, 2023.06.03:
+ * - pd, sd에 둘다 포함되는 cpu and @p에 허용된 cpu를 iterate 한다.
+ */
for_each_cpu_and(cpu, perf_domain_span(pd), sched_domain_span(sd)) {
if (!cpumask_test_cpu(cpu, p->cpus_ptr))
continue;
@@ -8840,6 +9086,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
util = cpu_util_next(cpu, p, cpu);
cpu_cap = capacity_of(cpu);
spare_cap = cpu_cap;
+/*
+ * IAMROOT, 2023.06.03:
+ * - 예상 사용량(util)을 빼서, 남아있는 capa를 계산(spare_cap)한다.
+ */
lsub_positive(&spare_cap, util);
/*
@@ -8849,10 +9099,29 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
* much capacity we can get out of the CPU; this is
* aligned with sched_cpu_util().
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * capacity 요청을 충족할 수 없는 CPU는 건너뜁니다.
+ * IOW, 거기에 작업을 배치하면 CPU가 과도하게 사용됩니다. uclamp를
+ * 고려하여 CPU에서 얼마나 많은 용량을 얻을 수 있는지 확인하십시오.
+ * 이것은 sched_cpu_util()과 일치합니다.
+ *
+ * - 가장 여유로은 pd를 찾고, 그 pd안에서 가장 여유로운 cpu를 찾는다.
+ * - @p가 uclamp를 사용할 경우 clamp 한다.
+ */
util = uclamp_rq_util_with(cpu_rq(cpu), util, p);
+/*
+ * IAMROOT, 2023.06.03:
+ * - util을 1.2배 해 적합한지 판별한다.
+ */
if (!fits_capacity(util, cpu_cap))
continue;
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - 이전 cpu가 대상 cpu에도 포함되어 대상이 된경우, compute_prev_delta를
+ * true로 한다.
+ */
if (cpu == prev_cpu) {
/* Always use prev_cpu as a candidate. */
compute_prev_delta = true;
@@ -8861,23 +9130,57 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
* Find the CPU with the maximum spare capacity
* in the performance domain.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 현재 순회중인 pd에서 최대 여유 용량이 있는 CPU를 찾습니다.
+ * - max값 갱신.
+ */
max_spare_cap = spare_cap;
max_spare_cap_cpu = cpu;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - for문 종료
+ */
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - pd, sd, @p->cpus와 겹치는 span의 cpus의 iterate가 끝낫는데
+ * max_spare_cap_cpu을 못찾은 pd는 skip한다. 단 prev_cpu가 있는 pd는
+ * skip하지 않는다.
+ */
if (max_spare_cap_cpu < 0 && !compute_prev_delta)
continue;
/* Compute the 'base' energy of the pd, without @p */
+/*
+ * IAMROOT, 2023.06.03:
+ * - base를 일단계산해 base끼리 합산을 한다.
+ */
base_energy_pd = compute_energy(p, -1, pd);
base_energy += base_energy_pd;
/* Evaluate the energy impact of using prev_cpu. */
+/*
+ * IAMROOT, 2023.06.03:
+ * - prev cpu가 있는 pd. prev_cpu로 energy를 계산하는데,
+ * migrate를 안하는게 이득이라고 판단하면, 완전 best를 찾으러 가는 것보다
+ * prev_cpu로 그냥 한다.
+ */
if (compute_prev_delta) {
prev_delta = compute_energy(p, prev_cpu, pd);
+/*
+ * IAMROOT, 2023.06.03:
+ * - migrate를 하지 않는게 더 energy 이득이라면 종료한다.
+ */
if (prev_delta < base_energy_pd)
goto unlock;
+/*
+ * IAMROOT, 2023.06.03:
+ * - prev_cpu가 현재 pd의 energy의 차이값을 best_delta에 min비교하여 저장한다.
+ */
prev_delta -= base_energy_pd;
best_delta = min(best_delta, prev_delta);
}
@@ -8885,8 +9188,16 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
/* Evaluate the energy impact of using max_spare_cap_cpu. */
if (max_spare_cap_cpu >= 0) {
cur_delta = compute_energy(p, max_spare_cap_cpu, pd);
+/*
+ * IAMROOT, 2023.06.03:
+ * - 여기서도 위에처럼 이득만 본다면 바로 out(예외처리 개념)
+ */
if (cur_delta < base_energy_pd)
goto unlock;
+/*
+ * IAMROOT, 2023.06.03:
+ * - 전력량이 상승하는 상태. 최소한의 상승인것을 우선순위에한다.
+ */
cur_delta -= base_energy_pd;
if (cur_delta < best_delta) {
best_delta = cur_delta;
@@ -8900,6 +9211,25 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
* Pick the best CPU if prev_cpu cannot be used, or if it saves at
* least 6% of the energy used by prev_cpu.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * prev_cpu를 사용할 수 없거나 prev_cpu에서 사용하는 에너지의 6% 이상을 절약하는
+ * 경우 최상의 CPU를 선택합니다.
+.
+ * - 여기 if문에서 target이 안바뀌면 prev_cpu가 target으로 된다.
+ * - prev_delta == ULONG_MAX. 즉 prev_cpu가 한번도 대상이 된적없음.
+ * 1. best_energy_cpu가 찾아졌었으면 그것이 cpu가 된다.
+ * 2. best_energy_cpu도 찾은적이 한번도 없으면 prev_cpu가 그냥 target이된다.
+ *
+ * - (prev_delta - best_delta) > ((prev_delta + base_energy) >> 4)
+ * 즉 prev_cpu가 찾아졌었다.
+ * prev_cpu에서보다 에너지절약이 6%이상이 되는 경우 해당 target을 return한다.
+ * - prev_delta - best_delta
+ * 옮긴후의 이득되는 delta
+ * - (prev_delta + base_energy) >> 4
+ * 옮기기전의 energy 총합의 6%
+ */
if ((prev_delta == ULONG_MAX) ||
(prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
target = best_energy_cpu;
@@ -8909,6 +9239,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
unlock:
rcu_read_unlock();
+/*
+ * IAMROOT, 2023.06.03:
+ * - return prev_cpu
+ */
return target;
}
@@ -8971,7 +9305,10 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
return new_cpu;
new_cpu = prev_cpu;
}
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - cache 친화여부를 알아온다.
+ */
want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr);
}
@@ -8981,6 +9318,13 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
* If both 'cpu' and 'prev_cpu' are part of this domain,
* cpu is a valid SD_WAKE_AFFINE target.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - cache친화를 찾아볼려고 노력을 하는상황. sd도 affine을 지원하고,
+ * prev_cpu도 포함되어있다. 즉 affine가능한 상태다.
+ * 이때 대상 cpu가 prev_cpu 아니라면, 대상 cpu로 결정할지 정한다.
+ * new_cpu는 prev_cpu or cpu로 무조건 골라진다.
+ */
if (want_affine && (tmp->flags & SD_WAKE_AFFINE) &&
cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) {
if (cpu != prev_cpu)
@@ -8990,12 +9334,22 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
break;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - sd_flag와 겹치는 sd를 찾아 계속 iterate를 수행한다.. 만약
+ * 못찾았는데, want_affine조차 없엇으면 그냥 종료한다.
+ */
if (tmp->flags & sd_flag)
sd = tmp;
else if (!want_affine)
break;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - want_affine이 없었거나, affine flag가 있는 sd를 못찾았다.
+ * ING
+ */
if (unlikely(sd)) {
/* Slow path */
new_cpu = find_idlest_cpu(sd, p, cpu, prev_cpu, sd_flag);
diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c
index 18930e71f741..2618d083052e 100644
--- a/kernel/sched/pelt.c
+++ b/kernel/sched/pelt.c
@@ -583,6 +583,10 @@ ___update_load_avg(struct sched_avg *sa, unsigned long load)
* load_avg = \Sum se->avg.load_avg
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - @now의 시각으로 decay를 목적으로 진입한다.
+ */
int __update_load_avg_blocked_se(u64 now, struct sched_entity *se)
{
if (___update_load_sum(now, &se->avg, 0, 0, 0)) {
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c92ffd3166b3..08b94f411dfa 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2627,6 +2627,10 @@ static inline int task_on_rq_migrating(struct task_struct *p)
*/
#define WF_TTWU 0x08 /* Wakeup; maps to SD_BALANCE_WAKE */
+/*
+ * IAMROOT, 2023.06.03:
+ * - waker는 wakeup을 한 후 sleep을 하러 가야된다는 뜻.
+ */
#define WF_SYNC 0x10 /* Waker goes to sleep after wakeup */
#define WF_MIGRATED 0x20 /* Internal use, task got migrated */
#define WF_ON_CPU 0x40 /* Wakee is on_cpu */
@@ -3654,6 +3658,25 @@ unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id);
* will return the correct effective uclamp value of the task even if the
* static key is disabled.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * uclamp_rq_util_with - @rq 및 @p 유효 uclamp 값을 사용하여 @util을 클램프합니다.
+ * @rq: 클램프할 rq입니다. NULL이 아니어야 합니다.
+ * @util: 클램프할 util 값입니다.
+ * @p: 클램프할 작업입니다. @rq만 고정하려는 경우 NULL이 될 수 있습니다.
+ *
+ * 전달된 @util을 최대(@rq, @p) 유효 uclamp 값으로 고정합니다.
+ *
+ * sched_uclamp_used 정적 키가 비활성화된 경우 빠른 경로의 rq 수준에서 uclamp
+ * 집계가 비활성화되어 이 작업을 NOP로 렌더링하므로 클램핑 없이 util을 반환합니다.
+ *
+ * rq 수준에서 uclamp 값을 신경 쓰지 않는다면 uclamp_eff_value()를 사용하십시오.
+ * 정적 키가 비활성화된 경우에도 작업의 올바른 유효 uclamp 값을 반환합니다.
+ *
+ * - 1. 1차적으로 UCLAMP_FLAG_IDLE이 있는 경우 @p의 min max를 사용한다.
+ * 2. 그게 아니면 @p와 @rq에 대한 min max를 비교해 최대값을 사용한다.
+ */
static __always_inline
unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
struct task_struct *p)
@@ -3672,6 +3695,12 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
* Ignore last runnable task's max clamp, as this task will
* reset it. Similarly, no need to read the rq's min clamp.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * 마지막으로 실행 가능한 작업의 최대 클램프를 무시합니다. 이 작업은
+ * 이를 재설정합니다. 마찬가지로 rq의 최소 클램프를 읽을 필요가 없습니다.
+ */
if (rq->uclamp_flags & UCLAMP_FLAG_IDLE)
goto out;
}
@@ -3684,6 +3713,12 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
* RUNNABLE tasks with _different_ clamps, we can end up with an
* inversion. Fix it now when the clamps are applied.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * CPU의 {min,max}_util 클램프는 _다른_ 클램프가 있는 RUNNABLE 작업을 고려하여 MAX
+ * 집계되므로 반전으로 끝날 수 있습니다. 클램프가 적용되면 지금 수정하십시오.
+ */
if (unlikely(min_util >= max_util))
return min_util;
@@ -3740,6 +3775,20 @@ static inline unsigned long capacity_orig_of(int cpu)
* enum is used within effective_cpu_util() to differentiate the types of
* utilization expected by the callers, and adjust the aggregation accordingly.
*/
+/*
+ * IAMROOT, 2023.06.03:
+ * - papago
+ * enum cpu_util_type - CPU 사용 유형
+ * @FREQUENCY_UTIL: 주파수 선택에 사용되는 utilization
+ * @ENERGY_UTIL: 에너지 계산 시 사용되는 utilization
+ *
+ * 모든 스케줄링 클래스(CFS/RT/DL)의 활용 신호와 IRQ 시간은 utilization에 따라 다르게
+ * 집계해야 합니다. 이 열거형은 effective_cpu_util() 내에서 호출자가 예상하는
+ * 사용 유형을 구별하고 그에 따라 집계를 조정하는 데 사용됩니다.
+ *
+ * - FREQUENCY_UTIL : 주파수 설정목적
+ * ENERGY_UTIL : 에너지 산출목적
+ */
enum cpu_util_type {
FREQUENCY_UTIL,
ENERGY_UTIL,
@@ -3748,17 +3797,28 @@ enum cpu_util_type {
unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
unsigned long max, enum cpu_util_type type,
struct task_struct *p);
-
+/*
+ * IAMROOT, 2023.06.03:
+ * - return dl bw
+ */
static inline unsigned long cpu_bw_dl(struct rq *rq)
{
return (rq->dl.running_bw * SCHED_CAPACITY_SCALE) >> BW_SHIFT;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - return dl util
+ */
static inline unsigned long cpu_util_dl(struct rq *rq)
{
return READ_ONCE(rq->avg_dl.util_avg);
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - return max(cfs util_avg, cfs util_est)
+ */
static inline unsigned long cpu_util_cfs(struct rq *rq)
{
unsigned long util = READ_ONCE(rq->cfs.avg.util_avg);
@@ -3771,6 +3831,10 @@ static inline unsigned long cpu_util_cfs(struct rq *rq)
return util;
}
+/*
+ * IAMROOT, 2023.06.03:
+ * - return rt util_avg
+ */
static inline unsigned long cpu_util_rt(struct rq *rq)
{
return READ_ONCE(rq->avg_rt.util_avg);
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 626 |
208 | [커널20차] 8주차 | 이경재 | 2023.06.24 | 74 |
207 | [커널20차] 7주차 | 이경재 | 2023.06.18 | 78 |
206 | [커널 18차] 108주차 | kkr | 2023.06.17 | 50 |
205 | [커널 20차] 4주차 | 김희찬 | 2023.06.12 | 79 |
204 | [커널 19차] 55 주차 | Min | 2023.06.10 | 28 |
203 | [커널 19차] 54 주차 | Min | 2023.06.03 | 34 |
» | [커널 18차] 106주차 | kkr | 2023.06.03 | 65 |
201 | [커널 20차] 3주차 | 김희찬 | 2023.06.03 | 73 |
200 | [커널 19차] 52 ~ 53 주차 | Min | 2023.05.27 | 55 |
199 | [커널 20차] 2주차 | 김희찬 | 2023.05.20 | 139 |
198 | [커널 19차] 51 주차 | Min | 2023.05.13 | 45 |
197 | [커널 20차] 1주차 | 김희찬 | 2023.05.13 | 193 |
196 | [커널 18차] 102주차 | kkr | 2023.05.07 | 75 |
195 | [커널 19차] 50 주차 | Min | 2023.05.07 | 31 |
194 | [커널 19차] 49 주차 | Min | 2023.04.29 | 55 |
193 | [커널 19차] 48 주차 | Min | 2023.04.23 | 83 |
192 | [커널 18차] 100주차 | kkr | 2023.04.22 | 83 |
191 | [커널 18차] 99주차 | kkr | 2023.04.16 | 77 |
190 | [커널 19차] 47 주차 | Min | 2023.04.15 | 41 |
189 | [커널 19차] 45, 46 주차 | Min | 2023.04.10 | 59 |
.