aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--idlestat.c27
-rw-r--r--topology.c63
-rw-r--r--topology.h4
-rw-r--r--tracefile_idlestat.c8
4 files changed, 92 insertions, 10 deletions
diff --git a/idlestat.c b/idlestat.c
index f52bd0b..22a9781 100644
--- a/idlestat.c
+++ b/idlestat.c
@@ -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))
diff --git a/topology.c b/topology.c
index 63d4899..39b07bd 100644
--- a/topology.c
+++ b/topology.c
@@ -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];
diff --git a/topology.h b/topology.h
index 5eba04e..84e5bc1 100644
--- a/topology.h
+++ b/topology.h
@@ -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;