sane_schedstat.c revision 6ca26ef8a78cc46dd8c779dcd7c611a247dd22c7
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