1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/* 2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License. 6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at 7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and 14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License. 15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */ 16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <ctype.h> 18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <dirent.h> 19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h> 20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <signal.h> 21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdio.h> 22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h> 23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h> 24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_LINE 512 26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_FILENAME 64 27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectconst char *EXPECTED_VERSION = "Latency Top version : v0.1\n"; 29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectconst char *SYSCTL_FILE = "/proc/sys/kernel/latencytop"; 30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectconst char *GLOBAL_STATS_FILE = "/proc/latency_stats"; 31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectconst char *THREAD_STATS_FILE_FORMAT = "/proc/%d/task/%d/latency"; 32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct latency_entry { 34e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *next; 35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long count; 36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long max; 37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long total; 38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char reason[MAX_LINE]; 39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}; 40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic inline void check_latencytop() { } 42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_global_stats(struct latency_entry *list, int erase); 44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_process_stats(struct latency_entry *list, int erase, int pid); 45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_thread_stats(struct latency_entry *list, int erase, int pid, int tid, int fatal); 46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *alloc_latency_entry(void); 48e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void free_latency_entry(struct latency_entry *e); 49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void set_latencytop(int on); 51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_latency_file(FILE *f, struct latency_entry *list); 52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void erase_latency_file(FILE *f); 53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *find_latency_entry(struct latency_entry *e, char *reason); 55e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void print_latency_entries(struct latency_entry *head); 56e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 57e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void signal_handler(int sig); 58e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void disable_latencytop(void); 59e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 60e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(const long long a, const long long b); 61e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int lat_cmp(const void *a, const void *b); 62e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 63e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void clear_screen(void); 64e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(const char *cmd); 65e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 66e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct latency_entry *free_entries; 67e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 68e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[]) { 69e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e; 70e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int delay, iterations; 71e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int pid, tid; 72e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int count, erase; 73e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int i; 74e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 75e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project delay = 1; 76e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project iterations = 0; 77e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid = tid = 0; 78e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 79e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 1; i < argc; i++) { 80e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-d")) { 81e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (i >= argc - 1) { 82e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Option -d expects an argument.\n"); 83e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 84e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 85e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project delay = atoi(argv[++i]); 86e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project continue; 87e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 88e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-n")) { 89e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (i >= argc - 1) { 90e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Option -n expects an argument.\n"); 91e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 92e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 93e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project iterations = atoi(argv[++i]); 94e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project continue; 95e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 96e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-h")) { 97e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project usage(argv[0]); 98e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_SUCCESS); 99e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 100e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-p")) { 101e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (i >= argc - 1) { 102e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Option -p expects an argument.\n"); 103e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 104e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 105e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pid = atoi(argv[++i]); 106e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project continue; 107e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 108e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(argv[i], "-t")) { 109e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (i >= argc - 1) { 110e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Option -t expects an argument.\n"); 111e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 112e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 113e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project tid = atoi(argv[++i]); 114e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project continue; 115e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 116e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Invalid argument \"%s\".\n", argv[i]); 117e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project usage(argv[0]); 118e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 119e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 120e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 121e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (tid && !pid) { 122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "If you provide a thread ID with -t, you must provide a process ID with -p.\n"); 123e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 124e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 125e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project check_latencytop(); 127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 128e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free_entries = NULL; 129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project signal(SIGINT, &signal_handler); 131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project signal(SIGTERM, &signal_handler); 132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 133e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project atexit(&disable_latencytop); 134e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 135e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project set_latencytop(1); 136e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 137e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project count = 0; 138e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project erase = 1; 139e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 140e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project while ((iterations == 0) || (count++ < iterations)) { 141e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 142e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project sleep(delay); 143e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 144e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = NULL; 145e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (pid) { 146e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (tid) { 147e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = read_thread_stats(e, erase, pid, tid, 1); 148e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 149e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = read_process_stats(e, erase, pid); 150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = read_global_stats(e, erase); 153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project erase = 0; 155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project clear_screen(); 157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (pid) { 158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (tid) { 159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("Latencies for thread %d in process %d:\n", tid, pid); 160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("Latencies for process %d:\n", pid); 162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("Latencies across all processes:\n"); 165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project print_latency_entries(e); 167e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 168e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 169e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project set_latencytop(0); 170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 171e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 172e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 174e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_global_stats(struct latency_entry *list, int erase) { 175e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project FILE *f; 176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e; 177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (erase) { 179e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(GLOBAL_STATS_FILE, "w"); 180e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!f) { 181e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not open global latency stats file: %s\n", strerror(errno)); 182e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 183e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 184e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(f, "erase\n"); 185e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fclose(f); 186e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 187e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 188e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(GLOBAL_STATS_FILE, "r"); 189e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!f) { 190e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not open global latency stats file: %s\n", strerror(errno)); 191e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 192e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 193e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 194e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = read_latency_file(f, list); 195e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 196e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fclose(f); 197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return e; 199e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 200e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 201e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_process_stats(struct latency_entry *list, int erase, int pid) { 202e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char dirname[MAX_FILENAME]; 203e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project DIR *dir; 204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct dirent *ent; 205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e; 206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int tid; 207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project sprintf(dirname, "/proc/%d/task", pid); 209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project dir = opendir(dirname); 210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!dir) { 211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not open task dir for process %d.\n", pid); 212e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Perhaps the process has terminated?\n"); 213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 214e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 215e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 216e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = list; 217e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project while ((ent = readdir(dir))) { 218e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!isdigit(ent->d_name[0])) 219e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project continue; 220e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 221e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project tid = atoi(ent->d_name); 222e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 223e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = read_thread_stats(e, erase, pid, tid, 0); 224e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 225e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 226e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project closedir(dir); 227e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 228e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return e; 229e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 230e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 231e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_thread_stats(struct latency_entry *list, int erase, int pid, int tid, int fatal) { 232e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char filename[MAX_FILENAME]; 233e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project FILE *f; 234e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e; 235e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 236e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project sprintf(filename, THREAD_STATS_FILE_FORMAT, pid, tid); 237e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 238e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (erase) { 239e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(filename, "w"); 240e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!f) { 241e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (fatal) { 242e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno)); 243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Perhaps the process or thread has terminated?\n"); 244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return list; 247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(f, "erase\n"); 250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fclose(f); 251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(GLOBAL_STATS_FILE, "r"); 254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!f) { 255e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (fatal) { 256e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno)); 257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Perhaps the process or thread has terminated?\n"); 258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 260e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return list; 261e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 263e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 264e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = read_latency_file(f, list); 265e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 266e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fclose(f); 267e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 268e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return e; 269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 271e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *alloc_latency_entry(void) { 272e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e; 273e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 274e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (free_entries) { 275e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = free_entries; 276e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free_entries = free_entries->next; 277e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 278e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = calloc(1, sizeof(struct latency_entry)); 279e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!e) { 280e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not allocate latency entry: %s\n", strerror(errno)); 281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 282e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 284e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 285e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return e; 286e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 287e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 288e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void free_latency_entry(struct latency_entry *e) { 289e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->next = free_entries; 290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free_entries = e; 291e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 292e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 293e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *find_latency_entry(struct latency_entry *head, char *reason) { 294e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e; 295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 296e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = head; 297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 298e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project while (e) { 299e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!strcmp(e->reason, reason)) 300e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return e; 301e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = e->next; 302e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 303e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 304e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return NULL; 305e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 306e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 307e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void set_latencytop(int on) { 308e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project FILE *f; 309e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 310e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project f = fopen(SYSCTL_FILE, "w"); 311e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!f) { 312e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not open %s: %s\n", SYSCTL_FILE, strerror(errno)); 313e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 315e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 316e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(f, "%d\n", on); 317e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 318e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fclose(f); 319e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 320e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 321e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void erase_latency_file(FILE *f) { 322e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(f, "erase\n"); 323e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 324e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 325e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic struct latency_entry *read_latency_file(FILE *f, struct latency_entry *list) { 326e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e, *head; 327e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char line[MAX_LINE]; 328e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long count, max, total; 329e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project char reason[MAX_LINE]; 330e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 331e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project head = list; 332e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 333e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!fgets(line, MAX_LINE, f)) { 334e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Could not read latency file version: %s\n", strerror(errno)); 335e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 336e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 337e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 338e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (strcmp(line, EXPECTED_VERSION) != 0) { 339e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Expected version: %s\n", EXPECTED_VERSION); 340e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "But got version: %s", line); 341e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 342e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 343e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 344e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project while (fgets(line, MAX_LINE, f)) { 345e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project sscanf(line, "%ld %ld %ld %s", &count, &total, &max, reason); 346e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (max > 0 || total > 0) { 347e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = find_latency_entry(head, reason); 348e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (e) { 349e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->count += count; 350e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (max > e->max) 351e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->max = max; 352e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->total += total; 353e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } else { 354e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = alloc_latency_entry(); 355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->count = count; 356e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->max = max; 357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->total = total; 358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project strcpy(e->reason, reason); 359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->next = head; 360e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project head = e; 361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 363e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 365e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return head; 366e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 367e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 368e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void print_latency_entries(struct latency_entry *head) { 369e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project struct latency_entry *e, **array; 370e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project unsigned long average; 371e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project int i, count; 372e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 373e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = head; 374e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project count = 0; 375e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project while (e) { 376e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project count++; 377e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = e->next; 378e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 379e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 380e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = head; 381e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project array = calloc(count, sizeof(struct latency_entry *)); 382e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (!array) { 383e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Error allocating array: %s\n", strerror(errno)); 384e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_FAILURE); 385e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 386e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < count; i++) { 387e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project array[i] = e; 388e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = e->next; 389e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 390e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 391e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project qsort(array, count, sizeof(struct latency_entry *), &lat_cmp); 392e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 393e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%10s %10s %7s %s\n", "Maximum", "Average", "Count", "Reason"); 394e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project for (i = 0; i < count; i++) { 395e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e = array[i]; 396e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project average = e->total / e->count; 397e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("%4lu.%02lu ms %4lu.%02lu ms %7ld %s\n", 398e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->max / 1000, (e->max % 1000) / 10, 399e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project average / 1000, (average % 1000) / 10, 400e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->count, 401e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project e->reason); 402e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project } 403e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 404e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project free(array); 405e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 406e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 407e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void signal_handler(int sig) { 408e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project exit(EXIT_SUCCESS); 409e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 410e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 411e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void disable_latencytop(void) { 412e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project set_latencytop(0); 413e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 414e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 415e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void clear_screen(void) { 416e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project printf("\n\n"); 417e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 418e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 419e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(const char *cmd) { 420e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project fprintf(stderr, "Usage: %s [ -d delay ] [ -n iterations ] [ -p pid [ -t tid ] ] [ -h ]\n" 421e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -d delay Time to sleep between updates.\n" 422e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -n iterations Number of updates to show (0 = infinite).\n" 423e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -p pid Process to monitor (default is all).\n" 424e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -t tid Thread (within specified process) to monitor (default is all).\n" 425e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project " -h Display this help screen.\n", 426e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project cmd); 427e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 428e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 429e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(const long long a, const long long b) { 430e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (a < b) return -1; 431e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project if (a > b) return 1; 432e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return 0; 433e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 434e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 435e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int lat_cmp(const void *a, const void *b) { 436e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project const struct latency_entry *pa, *pb; 437e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 438e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pa = (*((struct latency_entry **)a)); 439e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project pb = (*((struct latency_entry **)b)); 440e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 441e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project return numcmp(pb->max, pa->max); 442e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 443