123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /*
- ** Copyright 2010 The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
- /* Opens /proc/sched_stat and diff's the counters.
- Currently support version 15, modify parse() to support other
- versions
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <sys/uio.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <fcntl.h>
- #define MAX_CPU 2
- struct cpu_stat {
- /* sched_yield() stats */
- unsigned int yld_count; /* sched_yield() called */
- /* schedule() stats */
- unsigned int sched_switch; /* switched to expired queue and reused it */
- unsigned int sched_count; /* schedule() called */
- unsigned int sched_goidle; /* schedule() left the cpu idle */
- /* try_to_wake_up() stats */
- unsigned int ttwu_count; /* try_to_wake_up() called */
- /* try_to_wake_up() called and found the process being awakened last ran on
- * the waking cpu */
- unsigned int ttwu_local;
- /* latency stats */
- unsigned long long cpu_time; /* time spent running by tasks (ms) */
- unsigned long long run_delay; /* time spent waiting to run by tasks (ms) */
- unsigned long pcount; /* number of tasks (not necessarily unique) given */
- };
- struct cpu_stat cpu_prev[MAX_CPU];
- struct cpu_stat cpu_delta[MAX_CPU];
- struct cpu_stat tmp;
- static const char *next_line(const char *b) {
- while (1) {
- switch (*b) {
- case '\n':
- return b + 1;
- case '\0':
- return NULL;
- }
- b++;
- }
- }
- static int print() {
- int i;
- printf("CPU yield() schedule() switch idle ttwu() local cpu_time wait_time timeslices\n");
- for (i=0; i<MAX_CPU; i++) {
- printf(" %2d %7u %10u %6u %4u %8u %5u %9llu %9llu %10lu\n",
- i,
- cpu_delta[i].yld_count,
- cpu_delta[i].sched_count, cpu_delta[i].sched_switch, cpu_delta[i].sched_goidle,
- cpu_delta[i].ttwu_count, cpu_delta[i].ttwu_local,
- cpu_delta[i].cpu_time / 1000000, cpu_delta[i].run_delay / 1000000, cpu_delta[i].pcount);
- }
- return 0;
- }
- static int parse_cpu_v15(const char *b) {
- int cpu;
- if (sscanf(b, "cpu%d %u %u %u %u %u %u %llu %llu %lu\n",
- &cpu, &tmp.yld_count,
- &tmp.sched_switch, &tmp.sched_count, &tmp.sched_goidle,
- &tmp.ttwu_count, &tmp.ttwu_local,
- &tmp.cpu_time, &tmp.run_delay, &tmp.pcount) != 10) {
- printf("Could not parse %s\n", b);
- return -1;
- }
- cpu_delta[cpu].yld_count = tmp.yld_count - cpu_prev[cpu].yld_count;
- cpu_delta[cpu].sched_switch = tmp.sched_switch - cpu_prev[cpu].sched_switch;
- cpu_delta[cpu].sched_count = tmp.sched_count - cpu_prev[cpu].sched_count;
- cpu_delta[cpu].sched_goidle = tmp.sched_goidle - cpu_prev[cpu].sched_goidle;
- cpu_delta[cpu].ttwu_count = tmp.ttwu_count - cpu_prev[cpu].ttwu_count;
- cpu_delta[cpu].ttwu_local = tmp.ttwu_local - cpu_prev[cpu].ttwu_local;
- cpu_delta[cpu].cpu_time = tmp.cpu_time - cpu_prev[cpu].cpu_time;
- cpu_delta[cpu].run_delay = tmp.run_delay - cpu_prev[cpu].run_delay;
- cpu_delta[cpu].pcount = tmp.pcount - cpu_prev[cpu].pcount;
- cpu_prev[cpu] = tmp;
- return 0;
- }
- static int parse(const char *b) {
- unsigned int version;
- unsigned long long ts;
- if (sscanf(b, "version %u\n", &version) != 1) {
- printf("Could not parse version\n");
- return -1;
- }
- switch (version) {
- case 15:
- b = next_line(b);
- if (!b || sscanf(b, "timestamp %llu\n", &ts) != 1) {
- printf("Could not parse timestamp\n");
- return -1;
- }
- while (1) {
- b = next_line(b);
- if (!b) break;
- if (b[0] == 'c') {
- if (parse_cpu_v15(b)) return -1;
- }
- }
- break;
- default:
- printf("Can not handle version %u\n", version);
- return -1;
- }
- return 0;
- }
- int main(int argc, char **argv) {
- int i;
- int fd;
- char buf[4096];
- while (1) {
- fd = open("/proc/schedstat", O_RDONLY);
- if (fd < 0) return -1;
- i = read(fd, buf, sizeof(buf) - 1);
- close(fd);
- buf[i] = '\0';
- if (parse(buf)) return -1;
- print();
- sleep(1);
- }
- return 0;
- }
|