[커널 18차] 99주차
2023.04.16 18:29
스케쥴러 로드밸런스 진행중
git : https://github.com/iamroot18/5.10/commit/f3df1d06d49a6dff3dd8435fc2f41fafe98cc78b
https://github.com/iamroot18/5.10/commit/0172167f91e4ebb58ecd5a8452ea80f9b98c407c
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 359d00fab3f8..9385641d58ef 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -948,15 +948,31 @@ static int __init parse_dt_topology(void)
struct cpu_topology cpu_topology[NR_CPUS];
EXPORT_SYMBOL_GPL(cpu_topology);
+/*
+ * IAMROOT, 2023.04.15:
+ * - @cpu가 속한 node에서 시작하여 core_sibling, llc_sibling이 각각 포함되있는지
+ * 검사해 해당 cpu-list가 전부 속해있다면 해당 cpu-list로 대체해서 return한다.
+ * - arm64기준으로는 같은 cluster 내의 core cpumask.
+ */
const struct cpumask *cpu_coregroup_mask(int cpu)
{
const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu));
/* Find the smaller of NUMA, core or LLC siblings */
+/*
+ * IAMROOT, 2023.04.15:
+ * - sibling이 core_mask에 다 포함되있는거면 sibling으로 대체한다.
+ */
if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) {
/* not numa in package, lets use the package siblings */
core_mask = &cpu_topology[cpu].core_sibling;
}
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - llc(last level cache)가 있는경우 llc_sibling이 완전히 core_mask에 포함되있는지 검사한다.
+ * 포함되면 llc_sibling으로 대체한다.
+ */
if (cpu_topology[cpu].llc_id != -1) {
if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask))
core_mask = &cpu_topology[cpu].llc_sibling;
diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h
index cc2959142171..f6ba9576c2e9 100644
--- a/include/linux/arch_topology.h
+++ b/include/linux/arch_topology.h
@@ -73,6 +73,10 @@ static inline unsigned long topology_get_thermal_pressure(int cpu)
void topology_set_thermal_pressure(const struct cpumask *cpus,
unsigned long th_pressure);
+/*
+ * IAMROOT, 2023.04.15:
+ * - arm64는 smt가 현재 없다. thread_id와 thread_sibling은 설정이 안될것이다.
+ */
struct cpu_topology {
int thread_id;
int core_id;
@@ -80,6 +84,12 @@ struct cpu_topology {
int llc_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - cache를 공유하는 list.
+ * last level cache
+ */
cpumask_t llc_sibling;
};
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 6bffa02a7b9c..03a0394da2ba 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -316,6 +316,10 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool
*
* After the loop, cpu is >= nr_cpu_ids.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - mask1 & mask2를 한후 iterate
+ */
#define for_each_cpu_and(cpu, mask1, mask2) \
for ((cpu) = -1; \
(cpu) = cpumask_next_and((cpu), (mask1), (mask2)), \
@@ -488,6 +492,11 @@ static inline void cpumask_xor(struct cpumask *dstp,
*
* If *@dstp is empty, returns 0, else returns 1
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - @src2p를 먼저 not을 한후 @src1p와 and한다.
+ * *src1p & ~*src2p
+ */
static inline int cpumask_andnot(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h
index 47f9167a04af..13e307474fa1 100644
--- a/include/linux/sched/isolation.h
+++ b/include/linux/sched/isolation.h
@@ -5,6 +5,11 @@
#include <linux/init.h>
#include <linux/tick.h>
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - housekeeping_isolcpus_setup() 참고
+ */
enum hk_flags {
HK_FLAG_TIMER = 1,
HK_FLAG_RCU = (1 << 1),
diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
index fd0e62bdb315..0d6751c8a6c2 100644
--- a/include/linux/sched/topology.h
+++ b/include/linux/sched/topology.h
@@ -81,6 +81,17 @@ struct sched_domain {
struct sched_domain __rcu *parent; /* top domain must be null terminated */
struct sched_domain __rcu *child; /* bottom domain must be null terminated */
struct sched_group *groups; /* the balancing groups of the domain */
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - sd_init()등에서 초기화 하는게 보인다.
+ * - sd_init()에서의 사용 초기값들
+ * min_interval : cpu개수를 기준으로 결정된다. cpu 3개 = 3ms.
+ * max_interval : min_interval * 2로 결정된다.
+ * imbalance_pct : load balance을 할때 특정 기준값을 넘으면 balance를 수행하라는 한계값.
+ * 117을 기본으로 사용했다.
+ * balance_interval : cpu개수를 기준으로 결정된다.
+ */
unsigned long min_interval; /* Minimum balance interval ms */
unsigned long max_interval; /* Maximum balance interval ms */
unsigned int busy_factor; /* less balancing by factor if busy */
@@ -178,6 +189,11 @@ bool cpus_share_cache(int this_cpu, int that_cpu);
typedef const struct cpumask *(*sched_domain_mask_f)(int cpu);
typedef int (*sched_domain_flags_f)(void);
+/*
+ * IAMROOT, 2023.04.15:
+ * - overlap이 될수있는 schedule domain topology level.
+ * numa topology에만 해당된다.
+ */
#define SDTL_OVERLAP 0x01
struct sd_data {
@@ -187,6 +203,29 @@ struct sd_data {
struct sched_group_capacity *__percpu *sgc;
};
+/*
+ * IAMROOT, 2023.04.15:
+ * - topology level 구성. 총 9단계로 구성된다.
+ * distance단계부턴 cpu가 겹칠수 있다. 겹칠수있는 sdt는 SDTL_OVERLAP
+ *
+ * mask | sd_flags | flags |
+ * +----------+----------------+--------------------+----------------+--------------+
+ * | 종료확인 | NULL | - | - | - |
+ * +----------+----------------+--------------------+----------------+--------------|
+ * | | 30(distance) | | | |
+ * | | 25 | | | |
+ * | NUMA | 20 | sd_numa_mask | cpu_numa_flags | SDTL_OVERLAP |
+ * | | 15 | | | |
+ * | | 10(local node) | | | 0 |
+ * +----------+----------------+--------------------+----------------+--------------+
+ * | | die | cpu_cpu_mask | NULL | 0 |
+ * | default | mc | cpu_coregroup_mask | cpu_core_flags | 0 |
+ * | | smt | cpu_smt_mask | cpu_smt_flags | 0 |
+ * +----------+----------------+--------------------+----------------+--------------+
+ * - default_topology 참고
+ * - ps)
+ * smt는 arm에는 없고 intel, amd, powerpc에만 현재 존재한다.
+ */
struct sched_domain_topology_level {
sched_domain_mask_f mask;
sched_domain_flags_f sd_flags;
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 8b6750021ca4..2f69424f434d 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -215,12 +215,20 @@ static inline int cpu_to_mem(int cpu)
#endif
#if defined(CONFIG_SCHED_SMT) && !defined(cpu_smt_mask)
+/*
+ * IAMROOT, 2023.04.15:
+ * - arm64는 현재 smt가 없다.
+ */
static inline const struct cpumask *cpu_smt_mask(int cpu)
{
return topology_sibling_cpumask(cpu);
}
#endif
+/*
+ * IAMROOT, 2023.04.15:
+ * - @cpu가 속한 node의 cpumask를 return한다.
+ */
static inline const struct cpumask *cpu_cpu_mask(int cpu)
{
return cpumask_of_node(cpu_to_node(cpu));
diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
index 7f06eaf12818..0d14df472d60 100644
--- a/kernel/sched/isolation.c
+++ b/kernel/sched/isolation.c
@@ -11,7 +11,18 @@
DEFINE_STATIC_KEY_FALSE(housekeeping_overridden);
EXPORT_SYMBOL_GPL(housekeeping_overridden);
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - housekeeping_setup() 참고.
+ * isolate cpu가 아닌 cpu-list
+ */
static cpumask_var_t housekeeping_mask;
+/*
+ * IAMROOT, 2023.04.15:
+ * - housekeeping_setup() 참고.
+ * isolate 종류(HK_FLAG_DOMAIN)
+ */
static unsigned int housekeeping_flags;
bool housekeeping_enabled(enum hk_flags flags)
@@ -37,6 +48,12 @@ int housekeeping_any_cpu(enum hk_flags flags)
}
EXPORT_SYMBOL_GPL(housekeeping_any_cpu);
+/*
+ * IAMROOT, 2023.04.15:
+ * - housekeeping_flags에 flags가 set되있으면 해당 flags로 housekeeping 설정이 있다는 뜻.
+ * housekeeping이 cpu-list를 reteurn한다.
+ * flag가 없다면 cpu_possible_mask(전체 cpu라는 뜻) return.
+ */
const struct cpumask *housekeeping_cpumask(enum hk_flags flags)
{
if (static_branch_unlikely(&housekeeping_overridden))
@@ -77,11 +94,23 @@ void __init housekeeping_init(void)
WARN_ON_ONCE(cpumask_empty(housekeeping_mask));
}
+/*
+ * IAMROOT, 2023.04.15:
+ * - @str format은 다음과 같은 상황이였는데
+ * Format: [flag-list,]<cpu-list>
+ * 이전에 flag-list를 건너 뛴 상태이므로 cpu-list만 남겨져 있다.
+ * (ex, 1,2,10-15)
+ * 이 string을 bitmap으로 만든다.
+ */
static int __init housekeeping_setup(char *str, enum hk_flags flags)
{
cpumask_var_t non_housekeeping_mask;
cpumask_var_t tmp;
+/*
+ * IAMROOT, 2023.04.15:
+ * - flag가 설정된 cpu들이 non_housekeeping_mask에 설정된다.
+ */
alloc_bootmem_cpumask_var(&non_housekeeping_mask);
if (cpulist_parse(str, non_housekeeping_mask) < 0) {
pr_warn("Housekeeping: nohz_full= or isolcpus= incorrect CPU range\n");
@@ -90,11 +119,26 @@ static int __init housekeeping_setup(char *str, enum hk_flags flags)
}
alloc_bootmem_cpumask_var(&tmp);
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - 기존에 한번도 설정한적이 없는경우.
+ */
if (!housekeeping_flags) {
alloc_bootmem_cpumask_var(&housekeeping_mask);
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - cpu-list 범위 밖 cpu들을 housekeeping_mask에 저장한다.
+ */
cpumask_andnot(housekeeping_mask,
cpu_possible_mask, non_housekeeping_mask);
+/*
+ * IAMROOT, 2023.04.15:
+ * - 전부 present된 cpu들만 flag가 set되있다면 평범하게 동작할수있는 cpu가 1개도
+ * 없는 개념이 되는 상황이다. 거기에 대한 예외처리.
+ */
cpumask_andnot(tmp, cpu_present_mask, non_housekeeping_mask);
if (cpumask_empty(tmp)) {
pr_warn("Housekeeping: must include one present CPU, "
@@ -102,7 +146,19 @@ static int __init housekeeping_setup(char *str, enum hk_flags flags)
__cpumask_set_cpu(smp_processor_id(), housekeeping_mask);
__cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
}
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - 한번이라도 설정한경우, cpu 검사만을 하고 flag를 추가하는 식으로 진행한다.
+ */
} else {
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - tmp에서는 non_housekeeping_mask이 설정안된 cpu들만 남게된다.
+ * present_mask를 통해 최소 1개의 cpu라도 있도록 예외처리를 하고,
+ * 최종적으로 non_housekeeping_mask가 설정이 안된 possible cpu만이 tmp에 남게된다.
+ */
cpumask_andnot(tmp, cpu_present_mask, non_housekeeping_mask);
if (cpumask_empty(tmp))
__cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
@@ -145,6 +201,41 @@ static int __init housekeeping_nohz_full_setup(char *str)
}
__setup("nohz_full=", housekeeping_nohz_full_setup);
+/*
+ * IAMROOT, 2023.04.15:
+ * - admin-guide/kernel-parameters.txt 참고 (papago)
+ * nohz
+ * 단일 작업이 실행될 때 틱을 비활성화합니다.
+ *
+ * 나머지 1Hz 틱은 작업 대기열로 오프로드되며, 작업 대기열은
+ * /sys/devices/virtual/workqueue/cpumask sysfs 파일을 통해 구성된
+ * 전역 작업 대기열의 선호도를 통해 또는 아래에 설명된 '도메인' 플래그를
+ * 사용하여 하우스키핑에 연결해야 합니다.
+ *
+ * 참고: 기본적으로 글로벌 작업 대기열은 모든 CPU에서 실행되므로
+ * 개별 CPU를 보호하려면 부팅 후 'cpumask' 파일을 수동으로 구성해야 합니다.
+ *
+ * domain
+ * 일반 SMP 밸런싱 및 스케줄링 알고리즘에서 격리합니다.
+ * 이 방법으로 도메인 격리를 수행하는 것은 되돌릴 수 없습니다.
+ * isolcpus를 통해 격리된 CPU를 도메인으로 다시 가져올 수 없습니다.
+ * cpuset.sched_load_balance 파일을 통해 스케줄러 로드 밸런싱을
+ * 비활성화하려면 대신 cpuset를 사용하는 것이 좋습니다.
+ * CPU가 언제든지 격리된 세트 안팎으로 이동할 수 있는 훨씬 더 유연한
+ * 인터페이스를 제공합니다.
+ *
+ * CPU 선호도 syscalls 또는 cpuset을 통해 격리된 CPU로 프로세스를
+ * 이동하거나 분리할 수 있습니다.
+ * <cpu number>는 0에서 시작하고 최대값은 시스템의 CPU 수 - 1입니다.
+ *
+ * - flags가 없으면 domain이 기본값이다.
+ * ex) isolcpus=1,5,10-30 -> 23개의 cpu가 domain에 참여하지 않는다는뜻.
+ *
+ * - @str format은 다음과 같다.
+ * Format: [flag-list,]<cpu-list>
+ * flag-list에서 미리 관련 flag를 정리해서 설정한후, cpu-list만 남겨
+ * cpu-list string으로 bitmap을 만드는 구조가 된다.
+ */
static int __init housekeeping_isolcpus_setup(char *str)
{
unsigned int flags = 0;
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 3801c754de2b..8bb900307334 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -588,6 +588,11 @@ void init_defrootdomain(void)
atomic_set(&def_root_domain.refcount, 1);
}
+/*
+ * IAMROOT, 2023.04.15:
+ * - rootdomain에 대한 default값을 하나 할당하고 초기화해서 return한다.
+ * isolate cpu를 제외한 모든 cpu들이 기본적으로 root domain에 참가한다.
+ */
static struct root_domain *alloc_rootdomain(void)
{
struct root_domain *rd;
@@ -1309,6 +1314,16 @@ struct asym_cap_data {
* capacity.
* The lifespan of data is unlimited.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - asym_cpu_capacity_update_data()참고
+ * - ex) CPU0~3 : 1024, CPU4-7 : 436 인 경우
+ * 1024, 436에 대한 node가 존재한다.
+ * node1->capacity = 1024;
+ * node1->cpus = cpu bitmaps에 cpu 0~3 set.
+ * node2->capacity = 436;
+ * node2->cpus = cpu bitmaps에 cpu 4~7 set.
+ */
static LIST_HEAD(asym_cap_list);
#define cpu_capacity_span(asym_data) to_cpumask((asym_data)->cpus)
@@ -1317,6 +1332,21 @@ static LIST_HEAD(asym_cap_list);
* Verify whether there is any CPU capacity asymmetry in a given sched domain.
* Provides sd_flags reflecting the asymmetry scope.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - papago
+ * 지정된 sched 도메인에 CPU 용량 비대칭이 있는지 확인합니다.
+ * 비대칭 범위를 반영하는 sd_flags를 제공합니다.
+ * - ex) 0,1 = 1024 capacity, 0,2 = 512 capacity, asym_cap_list에 전부있다고 가정
+ *
+ * SMT 0,1 / 2,3 -> 0,1 : count 1, miss 1
+ * 2,3 : count 1, miss 1
+ * 각각 동일한 cpu capacity의 그룹이므로 비대칭이 아니다.
+ * return 0.
+ * DIE 0,1,2,3 -> count 2, miss 0
+ * 다른 cpu capacity에 있기 때문에 비대칭이다. return
+ * return SD_ASYM_CPUCAPACITY | SD_ASYM_CPUCAPACITY_FULL
+ */
static inline int
asym_cpu_capacity_classify(const struct cpumask *sd_span,
const struct cpumask *cpu_map)
@@ -1330,6 +1360,15 @@ asym_cpu_capacity_classify(const struct cpumask *sd_span,
* CPUs capacities). Take into account CPUs that might be offline:
* skip those.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - papago
+ * 이 도메인에 걸쳐 있는 고유한 CPU 용량의 수를 계산합니다(sched_domain
+ * CPU 마스크를 사용 가능한 CPU 용량을 나타내는 마스크와 비교).
+ * 오프라인일 수 있는 CPU를 고려하십시오.
+ * 건너 뛰십시오.
+ * - span이 포함되있으면 count, topology범위를 벗어난거라면 miss가 된다.
+ */
list_for_each_entry(entry, &asym_cap_list, link) {
if (cpumask_intersects(sd_span, cpu_capacity_span(entry)))
++count;
@@ -1351,16 +1390,29 @@ asym_cpu_capacity_classify(const struct cpumask *sd_span,
}
+/*
+ * IAMROOT, 2023.04.15:
+ * - @cpu의 capacity와 동일한게 이미 asym_cap_list에 있는지 확인하고, 없으면
+ * 추가한다. 처리후 해당 entry의 cpu bitmap에 @cpu를 set한다.
+ */
static inline void asym_cpu_capacity_update_data(int cpu)
{
unsigned long capacity = arch_scale_cpu_capacity(cpu);
struct asym_cap_data *entry = NULL;
+/*
+ * IAMROOT, 2023.04.15:
+ * - 해당 capactiy에 대해 이미 존재하면 cpu bitmap에만 cpu set..
+ */
list_for_each_entry(entry, &asym_cap_list, link) {
if (capacity == entry->capacity)
goto done;
}
+/*
+ * IAMROOT, 2023.04.15:
+ * - 자료구조를 할당하고 asym_cap_list에 추가한다.
+ */
entry = kzalloc(sizeof(*entry) + cpumask_size(), GFP_KERNEL);
if (WARN_ONCE(!entry, "Failed to allocate memory for asymmetry data\n"))
return;
@@ -1380,6 +1432,8 @@ static inline void asym_cpu_capacity_update_data(int cpu)
* - google-translate
* cpu capacities로 그룹화된 CPU의 빌드업/업데이트 목록 업데이트에는 CPU 토폴로지 변경을
* 나타내는 상태로 sched 도메인을 재구축하라는 명시적 요청이 필요합니다.
+ *
+ * - cpu capacity별 자료구조인 asym_cap_list를 설정한다.
*/
static void asym_cpu_capacity_scan(void)
{
@@ -1389,9 +1443,18 @@ static void asym_cpu_capacity_scan(void)
list_for_each_entry(entry, &asym_cap_list, link)
cpumask_clear(cpu_capacity_span(entry));
+/*
+ * IAMROOT, 2023.04.15:
+ * - HK_FLAG_DOMAIN이 set되있다면 isolate가 안된 cpu들에 한한 iterate를 하면서,
+ * 해당 cpu capacity에 대해 asym_cap_list에 추가한다
+ */
for_each_cpu_and(cpu, cpu_possible_mask, housekeeping_cpumask(HK_FLAG_DOMAIN))
asym_cpu_capacity_update_data(cpu);
+/*
+ * IAMROOT, 2023.04.15:
+ * - 해당 cpapcity에 대한 cpu가 한개도 없으면 그냥 entry를 지워버린다.
+ */
list_for_each_entry_safe(entry, next, &asym_cap_list, link) {
if (cpumask_empty(cpu_capacity_span(entry))) {
list_del(&entry->link);
@@ -1403,6 +1466,10 @@ static void asym_cpu_capacity_scan(void)
* Only one capacity value has been detected i.e. this system is symmetric.
* No need to keep this data around.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - 단일 capacity면 관리할 필요가없으므로(모든 cpu가 같다는것.) 그냥 다 지워버린다.
+ */
if (list_is_singular(&asym_cap_list)) {
entry = list_first_entry(&asym_cap_list, typeof(*entry), link);
list_del(&entry->link);
@@ -1467,16 +1534,30 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
}
}
+/*
+ * IAMROOT, 2023.04.15:
+ * - sdt(schedule domain topology)별 pcpu 할당 및 초기화,
+ * @d에 대한 schedule domain, root domain 초기화.
+ */
static enum s_alloc
__visit_domain_allocation_hell(struct s_data *d, const struct cpumask *cpu_map)
{
memset(d, 0, sizeof(*d));
+/*
+ * IAMROOT, 2023.04.15:
+ * - 각 sdt별 pcp할당 및 초기화.
+ */
if (__sdt_alloc(cpu_map))
return sa_sd_storage;
d->sd = alloc_percpu(struct sched_domain *);
if (!d->sd)
return sa_sd_storage;
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - rootdomain 생성.
+ */
d->rd = alloc_rootdomain();
if (!d->rd)
return sa_sd;
@@ -1510,10 +1591,21 @@ static void claim_allocations(int cpu, struct sched_domain *sd)
enum numa_topology_type sched_numa_topology_type;
static int sched_domains_numa_levels;
+/*
+ * IAMROOT, 2023.04.15:
+ * - build중인 schedule domain 표시
+ */
static int sched_domains_curr_level;
int sched_max_numa_distance;
static int *sched_domains_numa_distance;
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - sched_domains_numa_masks[distance][node id] = nodemask
+ * - sched_init_numa()에서 만들어진다.
+ * - node id를 기준으로 distance이하의 인접 node에대한 nodemask가 설정된다.
+ */
static struct cpumask ***sched_domains_numa_masks;
int __read_mostly node_reclaim_distance = RECLAIM_DISTANCE;
@@ -1542,6 +1634,10 @@ static unsigned long __read_mostly *sched_numa_onlined_nodes;
SD_NUMA | \
SD_ASYM_PACKING)
+/*
+ * IAMROOT, 2023.04.15:
+ * -
+ */
static struct sched_domain *
sd_init(struct sched_domain_topology_level *tl,
const struct cpumask *cpu_map,
@@ -1556,13 +1652,37 @@ sd_init(struct sched_domain_topology_level *tl,
/*
* Ugly hack to pass state to sd_numa_mask()...
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - 현재 진행중인 sdl을 표시해놓는 개념이다.
+ */
sched_domains_curr_level = tl->numa_level;
#endif
+/*
+ * IAMROOT, 2023.04.15:
+ * - tl별 mask함수에서 @@cpu에 맞는 mask를 가져오고, 해당 mask의 weight를 가져온다.
+ * ex) cpu_smt_mask,
+ * cpu_coregroup_mask,
+ * cpu_cpu_mask,
+ * sd_numa_mask
+ */
sd_weight = cpumask_weight(tl->mask(cpu));
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - cpu_numa_flags : SD_NUMA
+ * cpu_core_flags : SD_SHARE_PKG_RESOURCES
+ * cpu_smt_flags : D_SHARE_CPUCAPACITY | SD_SHARE_PKG_RESOURCES
+ */
if (tl->sd_flags)
sd_flags = (*tl->sd_flags)();
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - 검사처리.
+ */
if (WARN_ONCE(sd_flags & ~TOPOLOGY_SD_FLAGS,
"wrong sd_flags in topology description\n"))
sd_flags &= TOPOLOGY_SD_FLAGS;
@@ -1671,6 +1791,11 @@ static struct sched_domain_topology_level default_topology[] = {
static struct sched_domain_topology_level *sched_domain_topology =
default_topology;
+/*
+ * IAMROOT, 2023.04.15:
+ * - schedule domain topology level만큼을 iterate한다.
+ * - sched_domain_topology_level 참고
+ */
#define for_each_sd_topology(tl) \
for (tl = sched_domain_topology; tl->mask; tl++)
@@ -1684,6 +1809,32 @@ void set_sched_topology(struct sched_domain_topology_level *tl)
#ifdef CONFIG_NUMA
+/*
+ * IAMROOT, 2023.04.15:
+ * - @sched_domains_curr_level를 기준으로 @cpu가 속한 node에 대한
+ * sched_domains_numa_masks를 return한다.
+ *
+ * - ex) A, B, C, D는 node 이름.
+
+ * A-- 20 -- B
+ * | |
+ * 15 20
+ * | |
+ * C-- 20 -- D
+ *
+ *
+ * 1. 요청한 cpu가 node A에 있고,
+ * sched_domains_curr_level = 1(1 == 15라는 의미)인 경우.
+ * node A, node C에 포함된 cpu들(cpumask) return.
+ *
+ * 2. 요청한 cpu가 node C에 있고,
+ * sched_domains_curr_level = 2(2 == 20라는 의미)인 경우.
+ * node A, node C, node D에 포함된 cpu들(cpumask) return.
+ *
+ * 3. 요청한 cpu가 node D에 있고,
+ * sched_domains_curr_level = 2(2 == 20라는 의미)인 경우.
+ * node C, node D, node B에 포함된 cpu들(cpumask) return.
+ */
static const struct cpumask *sd_numa_mask(int cpu)
{
return sched_domains_numa_masks[sched_domains_curr_level][cpu_to_node(cpu)];
@@ -2004,10 +2155,14 @@ void sched_init_numa(void)
* [0][1] -> distance 10, node 1 = 0b0010
* [0][2] -> distance 10, node 2 = 0b0100
* [0][3] -> distance 10, node 3 = 0b1000
- * [1][0] -> distance 15, node 0 = 0b0010
- * [1][1] -> distance 15, node 1 = 0b0001
- * [1][2] -> distance 15, node 2 = 0b1000
- * [1][3] -> distance 15, node 3 = 0b0100
+ * [1][0] -> distance 15, node 0 = 0b0011
+ * [1][1] -> distance 15, node 1 = 0b0011
+ * [1][2] -> distance 15, node 2 = 0b1100
+ * [1][3] -> distance 15, node 3 = 0b1100
+ * [2][0] -> distance 20, node 0 = 0b0111
+ * [2][1] -> distance 20, node 1 = 0b0011
+ * [2][2] -> distance 20, node 2 = 0b1101
+ * [2][3] -> distance 20, node 3 = 0b1100
* ...
*/
/* Compute default topology size */
@@ -2180,14 +2335,23 @@ int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
#endif /* CONFIG_NUMA */
+/*
+ * IAMROOT, 2023.04.15:
+ * - sdt level만큼의 pcpu를 생성 및 초기화한다.
+ */
static int __sdt_alloc(const struct cpumask *cpu_map)
{
struct sched_domain_topology_level *tl;
int j;
+
for_each_sd_topology(tl) {
struct sd_data *sdd = &tl->data;
+/*
+ * IAMROOT, 2023.04.15:
+ * - pcpu를 할당한다.
+ */
sdd->sd = alloc_percpu(struct sched_domain *);
if (!sdd->sd)
return -ENOMEM;
@@ -2204,6 +2368,11 @@ static int __sdt_alloc(const struct cpumask *cpu_map)
if (!sdd->sgc)
return -ENOMEM;
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - 만든 pcpu에 대해서 초기화를 수행한다.
+ */
for_each_cpu(j, cpu_map) {
struct sched_domain *sd;
struct sched_domain_shared *sds;
@@ -2285,6 +2454,10 @@ static void __sdt_free(const struct cpumask *cpu_map)
}
}
+/*
+ * IAMROOT, 2023.04.15:
+ * -
+ */
static struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl,
const struct cpumask *cpu_map, struct sched_domain_attr *attr,
struct sched_domain *child, int cpu)
@@ -2319,6 +2492,11 @@ static struct sched_domain *build_sched_domain(struct sched_domain_topology_leve
* Ensure topology masks are sane, i.e. there are no conflicts (overlaps) for
* any two given CPUs at this (non-NUMA) topology level.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - sanity check. 설정이 잘못됬는지 확인한다. overlap이 없는 level인데 overlap이
+ * 된것을 확인한다.
+ */
static bool topology_span_sane(struct sched_domain_topology_level *tl,
const struct cpumask *cpu_map, int cpu)
{
@@ -2334,6 +2512,14 @@ static bool topology_span_sane(struct sched_domain_topology_level *tl,
* breaking the sched_group lists - i.e. a later get_group() pass
* breaks the linking done for an earlier span.
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - papago
+ * NUMA가 아닌 수준은 부분적으로 겹칠 수 없습니다. 완전히 같거나
+ * 완전히 분리되어야 합니다. 그렇지 않으면 sched_group 목록이 깨질 수
+ * 있습니다. 즉, 나중에 get_group() 패스가 이전 범위에 대해 수행된
+ * 연결을 깨뜨립니다.
+ */
for_each_cpu(i, cpu_map) {
if (i == cpu)
continue;
@@ -2343,6 +2529,14 @@ static bool topology_span_sane(struct sched_domain_topology_level *tl,
* remove CPUs, which only lessens our ability to detect
* overlaps
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * - papago
+ * 우리가 만들려는 토폴로지와 정확히 일치하도록 'cpu_map'을 사용하여
+ * 모든 마스크를 '및' 해야 하지만 이렇게 하면 CPU만 제거할 수 있으므로
+ * 겹침을 감지하는 능력이 줄어들 뿐입니다.
+ * - 겹치면 안된다.
+ */
if (!cpumask_equal(tl->mask(cpu), tl->mask(i)) &&
cpumask_intersects(tl->mask(cpu), tl->mask(i)))
return false;
@@ -2355,6 +2549,10 @@ static bool topology_span_sane(struct sched_domain_topology_level *tl,
* Build sched domains for a given set of CPUs and attach the sched domains
* to the individual CPUs
*/
+/*
+ * IAMROOT, 2023.04.15:
+ * -
+ */
static int
build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *attr)
{
@@ -2475,6 +2673,10 @@ int __weak arch_update_cpu_topology(void)
return 0;
}
+/*
+ * IAMROOT, 2023.04.15:
+ * - @ndoms개수만큼을 만들고, 해당 ndoms에 cpumask를 생성한다.
+ */
cpumask_var_t *alloc_sched_domains(unsigned int ndoms)
{
int i;
@@ -2523,11 +2725,26 @@ int sched_init_domains(const struct cpumask *cpu_map)
* - arm64에서는 아무것도 안한다.
*/
arch_update_cpu_topology();
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - asym cpu에 대한 자료구조 설정
+ */
asym_cpu_capacity_scan();
ndoms_cur = 1;
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - 일단 1개를 만든다. 실패할경우 fallback_doms를 사용한다.
+ */
doms_cur = alloc_sched_domains(ndoms_cur);
if (!doms_cur)
doms_cur = &fallback_doms;
+
+/*
+ * IAMROOT, 2023.04.15:
+ * - @cpu_map & housekeeping를 대상으로 build를 진행한다.
+ */
cpumask_and(doms_cur[0], cpu_map, housekeeping_cpumask(HK_FLAG_DOMAIN));
err = build_sched_domains(doms_cur[0], NULL);
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 629 |
208 | [커널20차] 8주차 | 이경재 | 2023.06.24 | 74 |
207 | [커널20차] 7주차 | 이경재 | 2023.06.18 | 78 |
206 | [커널 18차] 108주차 | kkr | 2023.06.17 | 52 |
205 | [커널 20차] 4주차 | 김희찬 | 2023.06.12 | 79 |
204 | [커널 19차] 55 주차 | Min | 2023.06.10 | 28 |
203 | [커널 19차] 54 주차 | Min | 2023.06.03 | 34 |
202 | [커널 18차] 106주차 | kkr | 2023.06.03 | 66 |
201 | [커널 20차] 3주차 | 김희찬 | 2023.06.03 | 73 |
200 | [커널 19차] 52 ~ 53 주차 | Min | 2023.05.27 | 55 |
199 | [커널 20차] 2주차 | 김희찬 | 2023.05.20 | 141 |
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 |
» | [커널 18차] 99주차 | kkr | 2023.04.16 | 78 |
190 | [커널 19차] 47 주차 | Min | 2023.04.15 | 41 |
189 | [커널 19차] 45, 46 주차 | Min | 2023.04.10 | 59 |
.