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