1987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 2987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Copyright (c) 2012, The Android Open Source Project 3987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * All rights reserved. 4987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * 5987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Redistribution and use in source and binary forms, with or without 6987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * modification, are permitted provided that the following conditions 7987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * are met: 8987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * * Redistributions of source code must retain the above copyright 9987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * notice, this list of conditions and the following disclaimer. 10987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * * Redistributions in binary form must reproduce the above copyright 11987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * notice, this list of conditions and the following disclaimer in 12987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * the documentation and/or other materials provided with the 13987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * distribution. 14987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * * Neither the name of Google, Inc. nor the names of its contributors 15987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * may be used to endorse or promote products derived from this 16987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * software without specific prior written permission. 17987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * 18987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * SUCH DAMAGE. 30987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 31987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 32987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe#include <stdio.h> 33987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe#include <stdlib.h> 34987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe#include <unistd.h> 35987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 36987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe#define MAX_BUF_SIZE 64 37987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 38987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestruct freq_info { 39987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe unsigned freq; 40987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe long unsigned time; 41987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe}; 42987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 43987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestruct cpu_info { 44987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe long unsigned utime, ntime, stime, itime, iowtime, irqtime, sirqtime; 45987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe struct freq_info *freqs; 46987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int freq_count; 47987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe}; 48987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 49987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe#define die(...) { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } 50987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 51987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic struct cpu_info old_total_cpu, new_total_cpu, *old_cpus, *new_cpus; 52987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int cpu_count, delay, iterations; 53987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic char minimal, aggregate_freq_stats; 54987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 55987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int get_cpu_count(); 56987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int get_cpu_count_from_file(char *filename); 57987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic long unsigned get_cpu_total_time(struct cpu_info *cpu); 58987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int get_freq_scales_count(int cpu); 59987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void print_stats(); 60987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void print_cpu_stats(char *label, struct cpu_info *new_cpu, struct cpu_info *old_cpu, 61987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char print_freq); 62987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void print_freq_stats(struct cpu_info *new_cpu, struct cpu_info *old_cpu); 63987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void read_stats(); 64987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void read_freq_stats(int cpu); 65987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic char should_aggregate_freq_stats(); 66987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic char should_print_freq_stats(); 67987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void usage(char *cmd); 68987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 69987f27fbd27fc8a88018882f4071c46b6de4195cEric Roweint main(int argc, char *argv[]) { 70987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe struct cpu_info *tmp_cpus, tmp_total_cpu; 71987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i, freq_count; 72987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 73987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe delay = 3; 74987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe iterations = -1; 75987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe minimal = 0; 76987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe aggregate_freq_stats = 0; 77987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 78987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < argc; i++) { 79987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!strcmp(argv[i], "-n")) { 80987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (i + 1 >= argc) { 81987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fprintf(stderr, "Option -n expects an argument.\n"); 82987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe usage(argv[0]); 83987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe exit(EXIT_FAILURE); 84987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 85987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe iterations = atoi(argv[++i]); 86987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe continue; 87987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 88987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!strcmp(argv[i], "-d")) { 89987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (i + 1 >= argc) { 90987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fprintf(stderr, "Option -d expects an argument.\n"); 91987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe usage(argv[0]); 92987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe exit(EXIT_FAILURE); 93987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 94987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe delay = atoi(argv[++i]); 95987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe continue; 96987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 97987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!strcmp(argv[i], "-m")) { 98987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe minimal = 1; 99987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 100987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!strcmp(argv[i], "-h")) { 101987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe usage(argv[0]); 102987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe exit(EXIT_SUCCESS); 103987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 104987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 105987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 106987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe cpu_count = get_cpu_count(); 107987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 108987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_cpus = malloc(sizeof(struct cpu_info) * cpu_count); 109987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!old_cpus) die("Could not allocate struct cpu_info\n"); 110987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpus = malloc(sizeof(struct cpu_info) * cpu_count); 111987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!new_cpus) die("Could not allocate struct cpu_info\n"); 112987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 113987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < cpu_count; i++) { 114987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_cpus[i].freq_count = new_cpus[i].freq_count = get_freq_scales_count(i); 115987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpus[i].freqs = malloc(sizeof(struct freq_info) * new_cpus[i].freq_count); 116987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!new_cpus[i].freqs) die("Could not allocate struct freq_info\n"); 117987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_cpus[i].freqs = malloc(sizeof(struct freq_info) * old_cpus[i].freq_count); 118987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!old_cpus[i].freqs) die("Could not allocate struct freq_info\n"); 119987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 120987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 121987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe // Read stats without aggregating freq stats in the total cpu 122987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe read_stats(); 123987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 124987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe aggregate_freq_stats = should_aggregate_freq_stats(); 125987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (aggregate_freq_stats) { 126987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_total_cpu.freq_count = new_total_cpu.freq_count = new_cpus[0].freq_count; 127987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_total_cpu.freqs = malloc(sizeof(struct freq_info) * new_total_cpu.freq_count); 128987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!new_total_cpu.freqs) die("Could not allocate struct freq_info\n"); 129987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_total_cpu.freqs = malloc(sizeof(struct freq_info) * old_total_cpu.freq_count); 130987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!old_total_cpu.freqs) die("Could not allocate struct freq_info\n"); 131987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 132987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe // Read stats again with aggregating freq stats in the total cpu 133987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe read_stats(); 134987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 135987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 136987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe while ((iterations == -1) || (iterations-- > 0)) { 137987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe // Swap new and old cpu buffers; 138987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe tmp_total_cpu = old_total_cpu; 139987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_total_cpu = new_total_cpu; 140987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_total_cpu = tmp_total_cpu; 141987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 142987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe tmp_cpus = old_cpus; 143987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe old_cpus = new_cpus; 144987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpus = tmp_cpus; 145987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 146987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe sleep(delay); 147987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe read_stats(); 148987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe print_stats(); 149987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 150987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 151987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe // Clean up 152987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (aggregate_freq_stats) { 153987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe free(new_total_cpu.freqs); 154987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe free(old_total_cpu.freqs); 155987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 156987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < cpu_count; i++) { 157987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe free(new_cpus[i].freqs); 158987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe free(old_cpus[i].freqs); 159987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 160987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe free(new_cpus); 161987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe free(old_cpus); 162987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 163987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 0; 164987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 165987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 166987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 167987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Get the number of CPUs of the system. 168987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * 169987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Uses the two files /sys/devices/system/cpu/present and 170987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * /sys/devices/system/cpu/online to determine the number of CPUs. Expects the 171987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * format of both files to be either 0 or 0-N where N+1 is the number of CPUs. 172987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * 173987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Exits if the present CPUs is not equal to the online CPUs 174987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 175987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int get_cpu_count() { 176987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int cpu_count = get_cpu_count_from_file("/sys/devices/system/cpu/present"); 177987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (cpu_count != get_cpu_count_from_file("/sys/devices/system/cpu/online")) { 178987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe die("present cpus != online cpus\n"); 179987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 180987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return cpu_count; 181987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 182987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 183987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 184987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Get the number of CPUs from a given filename. 185987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 186987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int get_cpu_count_from_file(char *filename) { 187987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe FILE *file; 188987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char line[MAX_BUF_SIZE]; 189987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int cpu_count; 190987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 191987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe file = fopen(filename, "r"); 192987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!file) die("Could not open %s\n", filename); 193987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!fgets(line, MAX_BUF_SIZE, file)) die("Could not get %s contents\n", filename); 194987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fclose(file); 195987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 196987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (strcmp(line, "0\n") == 0) { 197987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 1; 198987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 199987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 200987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (1 == sscanf(line, "0-%d\n", &cpu_count)) { 201987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return cpu_count + 1; 202987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 203987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 204987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe die("Unexpected input in file %s (%s).\n", filename, line); 205987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return -1; 206987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 207987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 208987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 209987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Get the number of frequency states a given CPU can be scaled to. 210987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 211987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic int get_freq_scales_count(int cpu) { 212987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe FILE *file; 213987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char filename[MAX_BUF_SIZE]; 214987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe long unsigned freq; 215987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int count = 0; 216987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 217987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu); 218987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe file = fopen(filename, "r"); 219987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!file) die("Could not open %s\n", filename); 220987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe do { 221987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe freq = 0; 222987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fscanf(file, "%lu %*d\n", &freq); 223987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (freq) count++; 224987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } while(freq); 225987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fclose(file); 226987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 227987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return count; 228987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 229987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 230987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 231987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Read the CPU and frequency stats for all cpus. 232987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 233987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void read_stats() { 234987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe FILE *file; 235987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char scanline[MAX_BUF_SIZE]; 236987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i; 237987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 238987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe file = fopen("/proc/stat", "r"); 239987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!file) die("Could not open /proc/stat.\n"); 240987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fscanf(file, "cpu %lu %lu %lu %lu %lu %lu %lu %*d %*d %*d\n", 241987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe &new_total_cpu.utime, &new_total_cpu.ntime, &new_total_cpu.stime, &new_total_cpu.itime, 242987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe &new_total_cpu.iowtime, &new_total_cpu.irqtime, &new_total_cpu.sirqtime); 243987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (aggregate_freq_stats) { 244987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < new_total_cpu.freq_count; i++) { 245987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_total_cpu.freqs[i].time = 0; 246987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 247987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 248987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 249987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < cpu_count; i++) { 250987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe sprintf(scanline, "cpu%d %%lu %%lu %%lu %%lu %%lu %%lu %%lu %%*d %%*d %%*d\n", i); 251987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fscanf(file, scanline, &new_cpus[i].utime, &new_cpus[i].ntime, &new_cpus[i].stime, 252987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe &new_cpus[i].itime, &new_cpus[i].iowtime, &new_cpus[i].irqtime, 253987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe &new_cpus[i].sirqtime); 254987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe read_freq_stats(i); 255987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 256987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fclose(file); 257987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 258987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 259987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 260987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Read the frequency stats for a given cpu. 261987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 262987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void read_freq_stats(int cpu) { 263987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe FILE *file; 264987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char filename[MAX_BUF_SIZE]; 265987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i; 266987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 267987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu); 268987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe file = fopen(filename, "r"); 269987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!file) die("Could not open %s\n", filename); 270987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < new_cpus[cpu].freq_count; i++) { 271987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fscanf(file, "%u %lu\n", &new_cpus[cpu].freqs[i].freq, 272987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe &new_cpus[cpu].freqs[i].time); 273987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (aggregate_freq_stats) { 274987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_total_cpu.freqs[i].freq = new_cpus[cpu].freqs[i].freq; 275987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_total_cpu.freqs[i].time += new_cpus[cpu].freqs[i].time; 276987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 277987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 278987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fclose(file); 279987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 280987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 281987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 282987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Get the sum of the cpu time from all categories. 283987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 284987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic long unsigned get_cpu_total_time(struct cpu_info *cpu) { 285987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return (cpu->utime + cpu->ntime + cpu->stime + cpu->itime + cpu->iowtime + cpu->irqtime + 286987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe cpu->sirqtime); 287987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 288987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 289987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 290987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Print the stats for all CPUs. 291987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 292987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void print_stats() { 293987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char label[8]; 294987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i, j; 295987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char print_freq; 296987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 297987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe print_freq = should_print_freq_stats(); 298987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 299987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe print_cpu_stats("Total", &new_total_cpu, &old_total_cpu, 1); 300987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < cpu_count; i++) { 301987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe sprintf(label, "cpu%d", i); 302987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe print_cpu_stats(label, &new_cpus[i], &old_cpus[i], print_freq); 303987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 304987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf("\n"); 305987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 306987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 307987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 308987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Print the stats for a single CPU. 309987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 310987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void print_cpu_stats(char *label, struct cpu_info *new_cpu, struct cpu_info *old_cpu, 311987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe char print_freq) { 312987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe long int total_delta_time; 313987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 314987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!minimal) { 315987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe total_delta_time = get_cpu_total_time(new_cpu) - get_cpu_total_time(old_cpu); 316987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf("%s: User %ld + Nice %ld + Sys %ld + Idle %ld + IOW %ld + IRQ %ld + SIRQ %ld = " 317987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe "%ld\n", label, 318987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->utime - old_cpu->utime, 319987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->ntime - old_cpu->ntime, 320987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->stime - old_cpu->stime, 321987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->itime - old_cpu->itime, 322987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->iowtime - old_cpu->iowtime, 323987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->irqtime - old_cpu->irqtime, 324987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->sirqtime - old_cpu->sirqtime, 325987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe total_delta_time); 326987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (print_freq) { 327987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe print_freq_stats(new_cpu, old_cpu); 328987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 329987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } else { 330987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf("%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld", label, 331987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->utime - old_cpu->utime, 332987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->ntime - old_cpu->ntime, 333987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->stime - old_cpu->stime, 334987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->itime - old_cpu->itime, 335987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->iowtime - old_cpu->iowtime, 336987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->irqtime - old_cpu->irqtime, 337987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->sirqtime - old_cpu->sirqtime); 338987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe print_freq_stats(new_cpu, old_cpu); 339987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf("\n"); 340987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 341987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 342987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 343987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 344987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Print the CPU stats for a single CPU. 345987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 346987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void print_freq_stats(struct cpu_info *new_cpu, struct cpu_info *old_cpu) { 347987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe long int delta_time, total_delta_time; 348987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i; 349987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 350987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (new_cpu->freq_count > 0) { 351987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (!minimal) { 352987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe total_delta_time = 0; 353987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf(" "); 354987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < new_cpu->freq_count; i++) { 355987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe delta_time = new_cpu->freqs[i].time - old_cpu->freqs[i].time; 356987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe total_delta_time += delta_time; 357987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf("%ukHz %ld", new_cpu->freqs[i].freq, delta_time); 358987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (i + 1 != new_cpu->freq_count) { 359987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf(" + \n "); 360987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } else { 361987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf(" = "); 362987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 363987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 364987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf("%ld\n", total_delta_time); 365987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } else { 366987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 0; i < new_cpu->freq_count; i++) { 367987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe printf(",%u,%ld", new_cpu->freqs[i].freq, 368987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpu->freqs[i].time - old_cpu->freqs[i].time); 369987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 370987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 371987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 372987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 373987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 374987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 375987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Determine if frequency stats should be printed. 376987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * 377987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * If the frequency stats are different between CPUs, the stats should be 378987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * printed for each CPU, else only the aggregate frequency stats should be 379987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * printed. 380987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 381987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic char should_print_freq_stats() { 382987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i, j; 383987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 384987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 1; i < cpu_count; i++) { 385987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (j = 0; j < new_cpus[i].freq_count; j++) { 386987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (new_cpus[i].freqs[j].time - old_cpus[i].freqs[j].time != 387987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe new_cpus[0].freqs[j].time - old_cpus[0].freqs[j].time) { 388987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 1; 389987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 390987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 391987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 392987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 0; 393987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 394987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 395987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 396987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Determine if the frequency stats should be aggregated. 397987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * 398987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Only aggregate the frequency stats in the total cpu stats if the frequencies 399987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * reported by all CPUs are identical. Must be called after read_stats() has 400987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * been called once. 401987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 402987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic char should_aggregate_freq_stats() { 403987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe int i, j; 404987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 405987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (i = 1; i < cpu_count; i++) { 406987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (new_cpus[i].freq_count != new_cpus[0].freq_count) { 407987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 0; 408987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 409987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe for (j = 0; j < new_cpus[i].freq_count; j++) { 410987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe if (new_cpus[i].freqs[j].freq != new_cpus[0].freqs[j].freq) { 411987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 0; 412987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 413987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 414987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe } 415987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 416987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe return 1; 417987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 418987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe 419987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe/* 420987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe * Print the usage message. 421987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe */ 422987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowestatic void usage(char *cmd) { 423987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe fprintf(stderr, "Usage %s [ -n iterations ] [ -d delay ] [ -c cpu ] [ -m ] [ -h ]\n" 424987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe " -n num Updates to show before exiting.\n" 425987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe " -d num Seconds to wait between updates.\n" 426987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe " -m Display minimal output.\n" 427987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe " -h Display this help screen.\n", 428987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe cmd); 429987f27fbd27fc8a88018882f4071c46b6de4195cEric Rowe} 430