本文共 2749 字,大约阅读时间需要 9 分钟。
cpu的调度域可以分为下面3类。目前arm都是用的mcstatic struct sched_domain_topology_level default_topology[] = {#ifdef CONFIG_SCHED_SMT { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },#endif#ifdef CONFIG_SCHED_MC { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },#endif { cpu_cpu_mask, SD_INIT_NAME(DIE) }, { NULL, },};static struct sched_domain_topology_level *sched_domain_topology = default_topology;在下面的函数中都cpu的域进行初始化可以看到域的初始化分为4部分static intbuild_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *attr){ enum s_alloc alloc_state; struct sched_domain *sd; struct s_data d; struct rq *rq = NULL; int i, ret = -ENOMEM; alloc_state = __visit_domain_allocation_hell(&d, cpu_map); if (alloc_state != sa_rootdomain) goto error; /* Set up domains for CPUs specified by the cpu_map: */ #针对cpu_map中的cpu 来是指cpu domain for_each_cpu(i, cpu_map) { struct sched_domain_topology_level *tl; sd = NULL; for_each_sd_topology(tl) { #为每个cpubuild 调度域 sd = build_sched_domain(tl, cpu_map, attr, sd, i); #正常情况下sched_domain_topology应该等于default_topology,这里每个cpu设置调度域 if (tl == sched_domain_topology) *per_cpu_ptr(d.sd, i) = sd; if (tl->flags & SDTL_OVERLAP) sd->flags |= SD_OVERLAP; #cpu_map中每个cpu 都是指调度域后,退出这个for循环 if (cpumask_equal(cpu_map, sched_domain_span(sd))) break; } } /* Build the groups for the domains */ #为每个cpu 设置group for_each_cpu(i, cpu_map) { for (sd = *per_cpu_ptr(d.sd, i); sd; sd = sd->parent) { sd->span_weight = cpumask_weight(sched_domain_span(sd)); if (sd->flags & SD_OVERLAP) { if (build_overlap_sched_groups(sd, i)) goto error; } else { #主要是设置sd->group if (build_sched_groups(sd, i)) goto error; } } }#从上面可知每个cpu都有一个domain->groups /* Calculate CPU capacity for physical packages and nodes */ for (i = nr_cpumask_bits-1; i >= 0; i--) { if (!cpumask_test_cpu(i, cpu_map)) continue; for (sd = *per_cpu_ptr(d.sd, i); sd; sd = sd->parent) { claim_allocations(i, sd); #设置调度域中group中的每个cpu的能力 init_sched_groups_capacity(i, sd); } }#下面为么个rq attach domain /* Attach the domains */ rcu_read_lock(); for_each_cpu(i, cpu_map) { #得到每个cpu的running queue rq = cpu_rq(i); #每个cpu的调度域 sd = *per_cpu_ptr(d.sd, i); /* Use READ_ONCE()/WRITE_ONCE() to avoid load/store tearing: */ #如rq中表示cpucapacity的值大于调度域中表示cpu capacity,则更新调度域中的cpu的capacity if (rq->cpu_capacity_orig > READ_ONCE(d.rd->max_cpu_capacity)) WRITE_ONCE(d.rd->max_cpu_capacity, rq->cpu_capacity_orig); #将sd 作为cpu的base domain cpu_attach_domain(sd, d.rd, i); } rcu_read_unlock(); #用于debug是显示cpu的最大的capacity if (rq && sched_debug_enabled) { pr_info("span: %*pbl (max cpu_capacity = %lu)\n", cpumask_pr_args(cpu_map), rq->rd->max_cpu_capacity); } ret = 0;error: __free_domain_allocs(&d, alloc_state, cpu_map); return ret;}
转载地址:http://qjnmi.baihongyu.com/