调度器14—CPU拓扑结构和调度域建立-2-相关调试
一、拓扑相关调试
基于msm-5.4
1. sched_debug 开关
前提需要使能 CONFIG_SCHED_DEBUG,此时会导出一个 /sys/kernel/debug/sched_debug 文件,它会控制全局变量 sched_debug_enabled 的值,后者在 kernel/sched/topology.c 中唯一使用。
定义端:
late_initcall //sched/debug.c sched_init_debug //sched/debug.c debugfs_create_bool("sched_debug", 0644, NULL, &sched_debug_enabled); //这个类似函数 /sys/kernel/debug/sched_debug
使用端:
static int __init sched_debug_setup(char *str) //topology.c { sched_debug_enabled = true; return 0; } early_param("sched_debug", sched_debug_setup); static inline bool sched_debug(void) { return sched_debug_enabled; } sched_domain_debug(*sd, cpu) //topology.c if (!sched_debug_enabled) return; printk(KERN_DEBUG "CPU%d attaching sched-domain(s):\n", cpu); pd_init(cpu) //topology.c if (sched_debug()) pr_info("%s: no EM found for CPU%d\n", __func__, cpu); perf_domain_debug //topology.c if(sched_debug()) printk(KERN_DEBUG "root_domain %*pbl:", cpumask_pr_args(cpu_map)); printk(KERN_CONT " pd%d:{ cpus=%*pbl nr_cstate=%d }", ...); partition_sched_domains_locked //topology.c sched_energy_set(bool has_eas) //topology.c 使能或关闭EAS都有打印 if (sched_debug()) pr_info("%s: stopping EAS\n", __func__); static_branch_disable_cpuslocked(&sched_energy_present); if (sched_debug()) pr_info("%s: starting EAS\n", __func__); static_branch_enable_cpuslocked(&sched_energy_present);
只要 echo 1 > /sys/kernel/debug/sched_debug 使能了 sched_debug_enabled,会有一个 debug 等级的打印, 默认是关闭的。如:
[43337.992111] (4)[28299:kworker/4:2] domain-0: span=0-3 level=MC [43337.992116] (4)[28299:kworker/4:2] groups: 0:{ span=0 cap=748 }, 1:{ span=1 cap=586 }, 2:{ span=2 cap=784 }, 3:{ span=3 cap=752 } [43337.992132] (4)[28299:kworker/4:2] domain-1: span=0-4 level=DIE [43337.992137] (4)[28299:kworker/4:2] groups: 0:{ span=0-3 cap=2870 }, 4:{ span=4 cap=1023 } [43337.992147] (4)[28299:kworker/4:2]CPU1 attaching sched-domain(s): [43337.992151] (4)[28299:kworker/4:2] domain-0: span=0-3 level=MC [43337.992206] (4)[28299:kworker/4:2] groups: 1:{ span=1 cap=586 }, 2:{ span=2 cap=784 }, 3:{ span=3 cap=752 }, 0:{ span=0 cap=748 } [43337.992221] (4)[28299:kworker/4:2] domain-1: span=0-4 level=DIE [43337.992225] (4)[28299:kworker/4:2] groups: 0:{ span=0-3 cap=2870 }, 4:{ span=4 cap=1023 } [43337.992238] (4)[28299:kworker/4:2]CPU2 attaching sched-domain(s): [43337.992243] (4)[28299:kworker/4:2] domain-0: span=0-3 level=MC [43337.992250] (4)[28299:kworker/4:2] groups: 2:{ span=2 cap=784 }, 3:{ span=3 cap=752 }, 0:{ span=0 cap=748 }, 1:{ span=1 cap=586 } [43337.992267] (4)[28299:kworker/4:2] domain-1: span=0-4 level=DIE [43337.992272] (4)[28299:kworker/4:2] groups: 0:{ span=0-3 cap=2870 }, 4:{ span=4 cap=1023 } [43337.992282] (4)[28299:kworker/4:2]CPU3 attaching sched-domain(s): [43337.992285] (4)[28299:kworker/4:2] domain-0: span=0-3 level=MC [43337.992290] (4)[28299:kworker/4:2] groups: 3:{ span=3 cap=752 }, 0:{ span=0 cap=748 }, 1:{ span=1 cap=586 }, 2:{ span=2 cap=784 } [43337.992305] (4)[28299:kworker/4:2] domain-1: span=0-4 level=DIE [43337.992310] (4)[28299:kworker/4:2] groups: 0:{ span=0-3 cap=2870 }, 4:{ span=4 cap=1023 } [43337.992326] (4)[28299:kworker/4:2]CPU4 attaching sched-domain(s): [43337.992329] (4)[28299:kworker/4:2] domain-0: span=0-4 level=DIE [43337.992334] (4)[28299:kworker/4:2] groups: 4:{ span=4 cap=1023 }, 0:{ span=0-3 cap=2870 } [43337.992391] (4)[28299:kworker/4:2]root_domain 0-4: pd4:{ cpus=4-7 nr_cstate=1 } pd0:{ cpus=0-3 nr_cstate=1 } [43337.992398] (4)[28299:kworker/4:2]sched_energy_set: starting EAS
2. /proc/sys/kernel/sched_domain
这是一个目录,用来导出 sd 的信息,目录结构如下:
8295:/proc/sys/kernel/sched_domain # ls cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7 8295:/proc/sys/kernel/sched_domain # ls cpu0 domain0 domain1 8295:/proc/sys/kernel/sched_domain # ls cpu0/do domain0/ domain1/ 8295:/proc/sys/kernel/sched_domain # ls cpu0/domain0/ busy_factor cache_nice_tries flags imbalance_pct max_interval max_newidle_lb_cost min_interval name
文件导出代码:
//kernel/sched/debug.c static struct ctl_table sd_ctl_dir[] = { { .procname = "sched_domain", .mode = 0555, }, {} }; static struct ctl_table sd_ctl_root[] = { { .procname = "kernel", .mode = 0555, .child = sd_ctl_dir, }, {} }; static void set_table_entry(struct ctl_table *entry, const char *procname, void *data, int maxlen, umode_t mode, proc_handler *proc_handler) { entry->procname = procname; entry->data = data; entry->maxlen = maxlen; entry->mode = mode; entry->proc_handler = proc_handler; } static struct ctl_table *sd_alloc_ctl_domain_table(struct sched_domain *sd) { struct ctl_table *table = kcalloc(9, sizeof(struct ctl_table), GFP_KERNEL);; if (table == NULL) return NULL; set_table_entry(&table[0], "min_interval", &sd->min_interval, sizeof(long), 0644, proc_doulongvec_minmax); set_table_entry(&table[1], "max_interval", &sd->max_interval, sizeof(long), 0644, proc_doulongvec_minmax); set_table_entry(&table[2], "busy_factor", &sd->busy_factor, sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[3], "imbalance_pct", &sd->imbalance_pct, sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[4], "cache_nice_tries", &sd->cache_nice_tries, sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[5], "flags", &sd->flags, sizeof(int), 0444, proc_dointvec_minmax); //是10进制打印的 set_table_entry(&table[6], "max_newidle_lb_cost", &sd->max_newidle_lb_cost, sizeof(long), 0644, proc_doulongvec_minmax); set_table_entry(&table[7], "name", sd->name, CORENAME_MAX_SIZE, 0444, proc_dostring); /* &table[8] is terminator */ return table; } static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu) { struct ctl_table *entry, *table; struct sched_domain *sd; int domain_num = 0, i; char buf[32]; for_each_domain(cpu, sd) domain_num++; entry = table = kcalloc(domain_num + 1, sizeof(struct ctl_table), GFP_KERNEL); if (table == NULL) return NULL; i = 0; for_each_domain(cpu, sd) { snprintf(buf, 32, "domain%d", i); entry->procname = kstrdup(buf, GFP_KERNEL); entry->mode = 0555; entry->child = sd_alloc_ctl_domain_table(sd); entry++; i++; } return table; } static cpumask_var_t sd_sysctl_cpus; static struct ctl_table_header *sd_sysctl_header; void register_sched_domain_sysctl(void) { static struct ctl_table *cpu_entries; cpu_entries = kcalloc(num_possible_cpus() + 1, sizeof(struct ctl_table), GFP_KERNEL); cpu_idx = kcalloc(nr_cpu_ids, sizeof(struct ctl_table*), GFP_KERNEL); struct ctl_table *e = cpu_entries; for_each_possible_cpu(i) { cpu_idx[i] = e; e++; } for_each_cpu(i, sd_sysctl_cpus) { struct ctl_table *e = cpu_idx[i]; if (e->child) sd_free_ctl_entry(&e->child); if (!e->procname) { snprintf(buf, 32, "cpu%d", i); e->procname = kstrdup(buf, GFP_KERNEL); } e->mode = 0555; e->child = sd_alloc_ctl_cpu_table(i); //建立关联 } /* 一次性在sysctl下注册一个目录 */ sd_sysctl_header = register_sysctl_table(sd_ctl_root); }
posted on 2026-03-11 14:10 Hello-World3 阅读(6) 评论(0) 收藏 举报
浙公网安备 33010602011771号