16ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly/* 26ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** Copyright 2010 The Android Open Source Project 36ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** 46ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** Licensed under the Apache License, Version 2.0 (the "License"); 56ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** you may not use this file except in compliance with the License. 66ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** You may obtain a copy of the License at 76ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** 86ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** http://www.apache.org/licenses/LICENSE-2.0 96ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** 106ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** Unless required by applicable law or agreed to in writing, software 116ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** distributed under the License is distributed on an "AS IS" BASIS, 126ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** See the License for the specific language governing permissions and 146ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly** limitations under the License. 156ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly*/ 166ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 176ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 186ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly/* Opens /proc/sched_stat and diff's the counters. 196ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly Currently support version 15, modify parse() to support other 206ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly versions 216ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly*/ 226ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 236ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <stdlib.h> 246ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <stdio.h> 256ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <errno.h> 266ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <sys/uio.h> 276ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <unistd.h> 286ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <sys/time.h> 296ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#include <fcntl.h> 306ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 316ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly#define MAX_CPU 2 326ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 336ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystruct cpu_stat { 346ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly /* sched_yield() stats */ 356ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int yld_count; /* sched_yield() called */ 366ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 376ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly /* schedule() stats */ 386ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int sched_switch; /* switched to expired queue and reused it */ 396ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int sched_count; /* schedule() called */ 406ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int sched_goidle; /* schedule() left the cpu idle */ 416ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 426ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly /* try_to_wake_up() stats */ 436ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int ttwu_count; /* try_to_wake_up() called */ 446ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly /* try_to_wake_up() called and found the process being awakened last ran on 456ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly * the waking cpu */ 466ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int ttwu_local; 476ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 486ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly /* latency stats */ 496ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned long long cpu_time; /* time spent running by tasks (ms) */ 506ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned long long run_delay; /* time spent waiting to run by tasks (ms) */ 516ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned long pcount; /* number of tasks (not necessarily unique) given */ 526ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly}; 536ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 546ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystruct cpu_stat cpu_prev[MAX_CPU]; 556ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystruct cpu_stat cpu_delta[MAX_CPU]; 566ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystruct cpu_stat tmp; 576ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 586ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystatic const char *next_line(const char *b) { 596ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly while (1) { 606ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly switch (*b) { 616ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly case '\n': 626ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return b + 1; 636ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly case '\0': 646ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return NULL; 656ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 666ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly b++; 676ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 686ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly} 696ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystatic int print() { 706ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly int i; 716ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 726ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly printf("CPU yield() schedule() switch idle ttwu() local cpu_time wait_time timeslices\n"); 736ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly for (i=0; i<MAX_CPU; i++) { 746ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly printf(" %2d %7u %10u %6u %4u %8u %5u %9llu %9llu %10lu\n", 756ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly i, 766ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[i].yld_count, 776ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[i].sched_count, cpu_delta[i].sched_switch, cpu_delta[i].sched_goidle, 786ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[i].ttwu_count, cpu_delta[i].ttwu_local, 796ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[i].cpu_time / 1000000, cpu_delta[i].run_delay / 1000000, cpu_delta[i].pcount); 806ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 816ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return 0; 826ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly} 836ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 846ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystatic int parse_cpu_v15(const char *b) { 856ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly int cpu; 866ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 876ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (sscanf(b, "cpu%d %u %u %u %u %u %u %llu %llu %lu\n", 886ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly &cpu, &tmp.yld_count, 896ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly &tmp.sched_switch, &tmp.sched_count, &tmp.sched_goidle, 906ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly &tmp.ttwu_count, &tmp.ttwu_local, 916ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly &tmp.cpu_time, &tmp.run_delay, &tmp.pcount) != 10) { 926ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly printf("Could not parse %s\n", b); 936ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return -1; 946ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 956ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 966ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].yld_count = tmp.yld_count - cpu_prev[cpu].yld_count; 976ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].sched_switch = tmp.sched_switch - cpu_prev[cpu].sched_switch; 986ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].sched_count = tmp.sched_count - cpu_prev[cpu].sched_count; 996ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].sched_goidle = tmp.sched_goidle - cpu_prev[cpu].sched_goidle; 1006ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].ttwu_count = tmp.ttwu_count - cpu_prev[cpu].ttwu_count; 1016ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].ttwu_local = tmp.ttwu_local - cpu_prev[cpu].ttwu_local; 1026ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].cpu_time = tmp.cpu_time - cpu_prev[cpu].cpu_time; 1036ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].run_delay = tmp.run_delay - cpu_prev[cpu].run_delay; 1046ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_delta[cpu].pcount = tmp.pcount - cpu_prev[cpu].pcount; 1056ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 1066ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly cpu_prev[cpu] = tmp; 1076ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return 0; 1086ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly} 1096ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 1106ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 1116ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellystatic int parse(const char *b) { 1126ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned int version; 1136ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly unsigned long long ts; 1146ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 1156ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (sscanf(b, "version %u\n", &version) != 1) { 1166ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly printf("Could not parse version\n"); 1176ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return -1; 1186ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 1196ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly switch (version) { 1206ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly case 15: 1216ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly b = next_line(b); 1226ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (!b || sscanf(b, "timestamp %llu\n", &ts) != 1) { 1236ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly printf("Could not parse timestamp\n"); 1246ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return -1; 1256ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 1266ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly while (1) { 1276ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly b = next_line(b); 1286ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (!b) break; 1296ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (b[0] == 'c') { 1306ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (parse_cpu_v15(b)) return -1; 1316ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 1326ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 1336ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly break; 1346ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly default: 1356ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly printf("Can not handle version %u\n", version); 1366ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return -1; 1376ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 1386ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return 0; 1396ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly} 1406ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 1416ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pellyint main(int argc, char **argv) { 1426ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly int i; 1436ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly int fd; 1446ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly char buf[4096]; 1456ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly 1466ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly while (1) { 1476ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly fd = open("/proc/schedstat", O_RDONLY); 1486ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (fd < 0) return -1; 1496ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly i = read(fd, buf, sizeof(buf) - 1); 1506ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly close(fd); 1516ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly buf[i] = '\0'; 1526ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly if (parse(buf)) return -1; 1536ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly print(); 1546ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly sleep(1); 1556ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly } 1566ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly return 0; 1576ca26ef8a78cc46dd8c779dcd7c611a247dd22c7Nick Pelly} 158