diff options
-rw-r--r-- | idlestat.c | 27 | ||||
-rw-r--r-- | topology.c | 63 | ||||
-rw-r--r-- | topology.h | 4 | ||||
-rw-r--r-- | tracefile_idlestat.c | 8 |
4 files changed, 92 insertions, 10 deletions
@@ -352,7 +352,7 @@ static void release_init_pstates(struct init_pstates *initp) free(initp); } -static struct init_pstates *build_init_pstates(void) +static struct init_pstates *build_init_pstates(struct cpu_topology *topo) { struct init_pstates *initp; int nrcpus, cpu; @@ -378,6 +378,9 @@ static struct init_pstates *build_init_pstates(void) char *fpath; unsigned int *freq = &(freqs[cpu]); + if (!cpu_is_online(topo, cpu)) + continue; + if (asprintf(&fpath, CPUFREQ_CURFREQ_PATH_FORMAT, cpu) < 0) { release_init_pstates(initp); return NULL; @@ -390,7 +393,8 @@ static struct init_pstates *build_init_pstates(void) return initp; } -static void output_pstates(FILE *f, struct init_pstates *initp, int nrcpus, +static void output_pstates(FILE *f, struct init_pstates *initp, + int nrcpus, struct cpu_topology *topo, double ts) { int cpu; @@ -401,7 +405,10 @@ static void output_pstates(FILE *f, struct init_pstates *initp, int nrcpus, ts_usec = (ts - ts_sec) * USEC_PER_SEC; for (cpu = 0; cpu < nrcpus; cpu++) { - freq = initp? initp->freqs[cpu] : 0; + if (!cpu_is_online(topo, cpu)) + continue; + + freq = initp ? initp->freqs[cpu] : 0; fprintf(f, "%16s-%-5d [%03d] .... %5lu.%06lu: cpu_frequency: " "state=%u cpu_id=%d\n", "idlestat", getpid(), cpu, ts_sec, ts_usec, freq, cpu); @@ -931,7 +938,8 @@ static void write_cstate_info(FILE *f, char *name, int target) fprintf(f, "\t%d\n", target); } -void output_cstate_info(FILE *f, int nrcpus) { +void output_cstate_info(FILE *f, struct cpu_topology * topo, int nrcpus) +{ struct cpuidle_cstates *cstates; int i, j; @@ -939,6 +947,9 @@ void output_cstate_info(FILE *f, int nrcpus) { assert(!is_err(cstates)); for (i=0; i < nrcpus; i++) { + if (!cpu_is_online(topo, i)) + continue; + fprintf(f, "cpuid %d:\n", i); for (j=0; j < MAXCSTATE ; j++) { write_cstate_info(f, cstates[i].cstate[j].name, @@ -1281,17 +1292,17 @@ static int idlestat_store(const char *path, double start_ts, double end_ts, output_cpu_topo_info(cpu_topo, f); /* output c-states information */ - output_cstate_info(f, ret); + output_cstate_info(f, cpu_topo, ret); /* emit initial pstate changes */ if (initp) - output_pstates(f, initp, initp->nrcpus, start_ts); + output_pstates(f, initp, initp->nrcpus, cpu_topo, start_ts); ret = idlestat_file_for_each_line(TRACE_FILE, f, store_line); /* emit final pstate changes */ if (initp) - output_pstates(f, NULL, initp->nrcpus, end_ts); + output_pstates(f, NULL, initp->nrcpus, cpu_topo, end_ts); fclose(f); @@ -1494,7 +1505,7 @@ int main(int argc, char *argv[], char *const envp[]) if (get_trace_ts(&start_ts) == -1) goto err_restore_trace_options; - initp = build_init_pstates(); + initp = build_init_pstates(cpu_topo); /* Start the recording */ if (idlestat_trace_enable(true)) @@ -84,6 +84,12 @@ int add_topo_info(struct cpu_topology *topo_list, struct topology_info *info) struct cpu_core *s_core; struct cpu_cpu *s_cpu = NULL; struct list_head *ptr; + int *new_online_cpus; + + assert(info != NULL); + assert(info->physical_id >= 0); + assert(info->core_id >= 0); + assert(info->cpu_id >= 0); /* add cpu physical info */ ptr = check_exist_from_head(&topo_list->physical_head, @@ -149,9 +155,35 @@ int add_topo_info(struct cpu_topology *topo_list, struct topology_info *info) /* Add to the list (really a set) of all contained cpus in s_phy */ list_add_tail(&s_cpu->list_phy_enum, &s_phy->cpu_enum_head); + /* Add this cpu to the list of online cpus */ + if (topo_list->online_array_size <= info->cpu_id) { + new_online_cpus = realloc(topo_list->online_cpus, + sizeof(int) * (info->cpu_id + 1) ); + if (new_online_cpus == NULL) + return error(__func__); + + memset(new_online_cpus + topo_list->online_array_size, + 0, + sizeof(int) * + (info->cpu_id + 1 - topo_list->online_array_size)); + topo_list->online_cpus = new_online_cpus; + topo_list->online_array_size = info->cpu_id + 1; + } + topo_list->online_cpus[info->cpu_id] = 1; + return 0; } +int cpu_is_online(struct cpu_topology *topo, int cpuid) +{ + assert(cpuid >= 0); + + if (topo->online_array_size <= cpuid) + return 0; + + return topo->online_cpus[cpuid]; +} + struct cpu_physical *cpu_to_cluster(int cpuid, struct cpu_topology *topo) { struct cpu_physical *phy; @@ -302,6 +334,7 @@ static struct cpu_topology *topo_folder_scan(char *path, folder_filter_t filter) struct dirent dirent, *direntp; struct stat s; int ret; + int is_online; struct cpu_topology *result = NULL; dir = opendir(path); @@ -335,6 +368,32 @@ static struct cpu_topology *topo_folder_scan(char *path, folder_filter_t filter) if (strncmp(direntp->d_name, "cpu", 3)) continue; + /* + * Some cpu(s) may be offline. Before trying to figure + * out the topology entry, see if the cpu is online. + * The boot cpu (cpu0) is always online, so skip the check + * for that. + */ + if (!strcmp(direntp->d_name, "cpu0")) { + is_online = 1; + } else { + ret = asprintf(&newpath, "%s/%s/%s", basedir, + direntp->d_name, "online"); + if (ret < 0) + goto out_free_basedir; + + ret = read_int(newpath, &is_online); + free(newpath); + if (ret < 0) + goto out_free_basedir; + } + + if (!is_online) { + verbose_fprintf(stderr, 1, "Warning: %s is offline\n", + direntp->d_name); + continue; + } + ret = asprintf(&newpath, "%s/%s/%s", basedir, direntp->d_name, "topology"); if (ret < 0) @@ -483,6 +542,7 @@ int release_cpu_topo_info(struct cpu_topology *topo) /* Free alloced memory */ free_cpu_topology(&topo->physical_head); + free(topo->online_cpus); free(topo); return 0; @@ -818,6 +878,9 @@ int setup_topo_states(struct cpuidle_datas *datas) /* Map cpu state arrays into topology structures */ for (i = 0; i < datas->nrcpus; i++) { + if (!cpu_is_online(topo, i)) + continue; + s_cpu = find_cpu_point(topo, i); if (s_cpu) { s_cpu->cstates = &datas->cstates[i]; @@ -70,6 +70,8 @@ struct cpu_physical { struct cpu_topology { struct list_head physical_head; + int *online_cpus; + int online_array_size; }; extern struct cpu_topology *alloc_cpu_topo_info(void); @@ -81,6 +83,8 @@ extern void assign_baseline_in_topo(struct cpuidle_datas *datas); extern int release_cpu_topo_cstates(struct cpu_topology *topo); extern int dump_cpu_topo_info(struct report_ops *ops, void *report_data, int (*dump)(struct report_ops *, void *, void *, char *, void *), struct cpu_topology *topo, int cstate); +extern int cpu_is_online(struct cpu_topology *topo, int cpuid); + extern struct cpu_physical *cpu_to_cluster(int cpuid, struct cpu_topology *topo); extern struct cpu_core *cpu_to_core(int cpuid, struct cpu_topology *topo); diff --git a/tracefile_idlestat.c b/tracefile_idlestat.c index cb6f5bc..3430693 100644 --- a/tracefile_idlestat.c +++ b/tracefile_idlestat.c @@ -46,7 +46,7 @@ * * @return: per-CPU array of structs (success) or ptrerror() (error) */ -static struct cpuidle_cstates *load_and_build_cstate_info(FILE* f, char *buffer, int nrcpus) +static struct cpuidle_cstates *load_and_build_cstate_info(FILE* f, char *buffer, int nrcpus, struct cpu_topology * topo) { int cpu; struct cpuidle_cstates *cstates; @@ -66,6 +66,9 @@ static struct cpuidle_cstates *load_and_build_cstate_info(FILE* f, char *buffer, cstates[cpu].cstate_max = -1; cstates[cpu].current_cstate = -1; + if (!cpu_is_online(topo, cpu)) + continue; + if (sscanf(buffer, "cpuid %d:\n", &read_cpu) != 1 || read_cpu != cpu) { release_cstate_info(cstates, cpu); @@ -237,7 +240,8 @@ static struct cpuidle_datas * idlestat_native_load(const char *filename) goto propagate_error_free_datas; /* Read C-state information */ - datas->cstates = load_and_build_cstate_info(f, buffer, nrcpus); + datas->cstates = load_and_build_cstate_info(f, buffer, + nrcpus, datas->topo); if (is_err(datas->cstates)) goto propagate_error_free_datas; |