sane_schedstat.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. ** Copyright 2010 The Android Open Source Project
  3. **
  4. ** Licensed under the Apache License, Version 2.0 (the "License");
  5. ** you may not use this file except in compliance with the License.
  6. ** You may obtain a copy of the License at
  7. **
  8. ** http://www.apache.org/licenses/LICENSE-2.0
  9. **
  10. ** Unless required by applicable law or agreed to in writing, software
  11. ** distributed under the License is distributed on an "AS IS" BASIS,
  12. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ** See the License for the specific language governing permissions and
  14. ** limitations under the License.
  15. */
  16. /* Opens /proc/sched_stat and diff's the counters.
  17. Currently support version 15, modify parse() to support other
  18. versions
  19. */
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <sys/uio.h>
  24. #include <unistd.h>
  25. #include <sys/time.h>
  26. #include <fcntl.h>
  27. #define MAX_CPU 2
  28. struct cpu_stat {
  29. /* sched_yield() stats */
  30. unsigned int yld_count; /* sched_yield() called */
  31. /* schedule() stats */
  32. unsigned int sched_switch; /* switched to expired queue and reused it */
  33. unsigned int sched_count; /* schedule() called */
  34. unsigned int sched_goidle; /* schedule() left the cpu idle */
  35. /* try_to_wake_up() stats */
  36. unsigned int ttwu_count; /* try_to_wake_up() called */
  37. /* try_to_wake_up() called and found the process being awakened last ran on
  38. * the waking cpu */
  39. unsigned int ttwu_local;
  40. /* latency stats */
  41. unsigned long long cpu_time; /* time spent running by tasks (ms) */
  42. unsigned long long run_delay; /* time spent waiting to run by tasks (ms) */
  43. unsigned long pcount; /* number of tasks (not necessarily unique) given */
  44. };
  45. struct cpu_stat cpu_prev[MAX_CPU];
  46. struct cpu_stat cpu_delta[MAX_CPU];
  47. struct cpu_stat tmp;
  48. static const char *next_line(const char *b) {
  49. while (1) {
  50. switch (*b) {
  51. case '\n':
  52. return b + 1;
  53. case '\0':
  54. return NULL;
  55. }
  56. b++;
  57. }
  58. }
  59. static int print() {
  60. int i;
  61. printf("CPU yield() schedule() switch idle ttwu() local cpu_time wait_time timeslices\n");
  62. for (i=0; i<MAX_CPU; i++) {
  63. printf(" %2d %7u %10u %6u %4u %8u %5u %9llu %9llu %10lu\n",
  64. i,
  65. cpu_delta[i].yld_count,
  66. cpu_delta[i].sched_count, cpu_delta[i].sched_switch, cpu_delta[i].sched_goidle,
  67. cpu_delta[i].ttwu_count, cpu_delta[i].ttwu_local,
  68. cpu_delta[i].cpu_time / 1000000, cpu_delta[i].run_delay / 1000000, cpu_delta[i].pcount);
  69. }
  70. return 0;
  71. }
  72. static int parse_cpu_v15(const char *b) {
  73. int cpu;
  74. if (sscanf(b, "cpu%d %u %u %u %u %u %u %llu %llu %lu\n",
  75. &cpu, &tmp.yld_count,
  76. &tmp.sched_switch, &tmp.sched_count, &tmp.sched_goidle,
  77. &tmp.ttwu_count, &tmp.ttwu_local,
  78. &tmp.cpu_time, &tmp.run_delay, &tmp.pcount) != 10) {
  79. printf("Could not parse %s\n", b);
  80. return -1;
  81. }
  82. cpu_delta[cpu].yld_count = tmp.yld_count - cpu_prev[cpu].yld_count;
  83. cpu_delta[cpu].sched_switch = tmp.sched_switch - cpu_prev[cpu].sched_switch;
  84. cpu_delta[cpu].sched_count = tmp.sched_count - cpu_prev[cpu].sched_count;
  85. cpu_delta[cpu].sched_goidle = tmp.sched_goidle - cpu_prev[cpu].sched_goidle;
  86. cpu_delta[cpu].ttwu_count = tmp.ttwu_count - cpu_prev[cpu].ttwu_count;
  87. cpu_delta[cpu].ttwu_local = tmp.ttwu_local - cpu_prev[cpu].ttwu_local;
  88. cpu_delta[cpu].cpu_time = tmp.cpu_time - cpu_prev[cpu].cpu_time;
  89. cpu_delta[cpu].run_delay = tmp.run_delay - cpu_prev[cpu].run_delay;
  90. cpu_delta[cpu].pcount = tmp.pcount - cpu_prev[cpu].pcount;
  91. cpu_prev[cpu] = tmp;
  92. return 0;
  93. }
  94. static int parse(const char *b) {
  95. unsigned int version;
  96. unsigned long long ts;
  97. if (sscanf(b, "version %u\n", &version) != 1) {
  98. printf("Could not parse version\n");
  99. return -1;
  100. }
  101. switch (version) {
  102. case 15:
  103. b = next_line(b);
  104. if (!b || sscanf(b, "timestamp %llu\n", &ts) != 1) {
  105. printf("Could not parse timestamp\n");
  106. return -1;
  107. }
  108. while (1) {
  109. b = next_line(b);
  110. if (!b) break;
  111. if (b[0] == 'c') {
  112. if (parse_cpu_v15(b)) return -1;
  113. }
  114. }
  115. break;
  116. default:
  117. printf("Can not handle version %u\n", version);
  118. return -1;
  119. }
  120. return 0;
  121. }
  122. int main(int argc, char **argv) {
  123. int i;
  124. int fd;
  125. char buf[4096];
  126. while (1) {
  127. fd = open("/proc/schedstat", O_RDONLY);
  128. if (fd < 0) return -1;
  129. i = read(fd, buf, sizeof(buf) - 1);
  130. close(fd);
  131. buf[i] = '\0';
  132. if (parse(buf)) return -1;
  133. print();
  134. sleep(1);
  135. }
  136. return 0;
  137. }