1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
5b93e5812faffd3b6c5fb349072413aace31918d8Olivier Bailly#include <unistd.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
7b93e5812faffd3b6c5fb349072413aace31918d8Olivier Bailly#include <stdint.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <signal.h>
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pwd.h>
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct thread_info {
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pid;
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int tid;
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char name[64];
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint64_t exec_time;
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint64_t delay_time;
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t run_count;
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct thread_table {
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t allocated;
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t active;
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct thread_info *data;
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectenum {
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FLAG_BATCH = 1U << 0,
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FLAG_HIDE_IDLE = 1U << 1,
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FLAG_SHOW_THREADS = 1U << 2,
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FLAG_USE_ALTERNATE_SCREEN = 1U << 3,
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int time_dp = 9;
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int time_div = 1;
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define NS_TO_S_D(ns) \
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    (uint32_t)((ns) / 1000000000), time_dp, ((uint32_t)((ns) % 1000000000) / time_div)
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct thread_table processes;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct thread_table last_processes;
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct thread_table threads;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct thread_table last_threads;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void grow_table(struct thread_table *table)
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t size = table->allocated;
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct thread_info *new_table;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (size < 128)
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size = 128;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size *= 2;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    new_table = realloc(table->data, size * sizeof(*table->data));
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (new_table == NULL) {
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "out of memory\n");
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    table->data = new_table;
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    table->allocated = size;
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic struct thread_info *get_item(struct thread_table *table)
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (table->active >= table->allocated)
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        grow_table(table);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return table->data + table->active;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void commit_item(struct thread_table *table)
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    table->active++;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int read_line(char *line, size_t line_size)
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(line, O_RDONLY);
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd == 0)
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = read(fd, line, line_size - 1);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (len <= 0)
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    line[len] = '\0';
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void add_thread(int pid, int tid, struct thread_info *proc_info)
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char line[1024];
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *name, *name_end;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t name_len;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct thread_info *info;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(tid == 0)
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        info = get_item(&processes);
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        info = get_item(&threads);
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info->pid = pid;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info->tid = tid;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(tid)
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(line, "/proc/%d/task/%d/schedstat", pid, tid);
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(line, "/proc/%d/schedstat", pid);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (read_line(line, sizeof(line)))
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(sscanf(line, "%llu %llu %u", &info->exec_time, &info->delay_time, &info->run_count) != 3)
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (proc_info) {
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc_info->exec_time += info->exec_time;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc_info->delay_time += info->delay_time;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc_info->run_count += info->run_count;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = NULL;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!tid) {
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(line, "/proc/%d/cmdline", pid);
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (read_line(line, sizeof(line)) == 0 && line[0]) {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            name = line;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            name_len = strlen(name);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!name) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tid)
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sprintf(line, "/proc/%d/task/%d/stat", pid, tid);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sprintf(line, "/proc/%d/stat", pid);
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (read_line(line, sizeof(line)))
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name = strchr(line, '(');
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (name == NULL)
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name_end = strchr(name, ')');
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (name_end == NULL)
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name++;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name_len = name_end - name;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (name_len >= sizeof(info->name))
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name_len = sizeof(info->name) - 1;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(info->name, name, name_len);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info->name[name_len] = '\0';
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(tid == 0)
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        commit_item(&processes);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        commit_item(&threads);
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void add_threads(int pid, struct thread_info *proc_info)
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char path[1024];
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sprintf(path, "/proc/%d/task", pid);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d = opendir(path);
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(d == 0) return;
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while((de = readdir(d)) != 0){
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(isdigit(de->d_name[0])){
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int tid = atoi(de->d_name);
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            add_thread(pid, tid, proc_info);
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(d);
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void print_threads(int pid, uint32_t flags)
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t i, j;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < last_threads.active; i++) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int epid = last_threads.data[i].pid;
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int tid = last_threads.data[i].tid;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (epid != pid)
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (j = 0; j < threads.active; j++)
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tid == threads.data[j].tid)
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (j == threads.active)
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printf(" %5u died\n", tid);
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if (!(flags & FLAG_HIDE_IDLE) || threads.data[j].run_count - last_threads.data[i].run_count)
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printf(" %5u %2u.%0*u %2u.%0*u %5u %5u.%0*u %5u.%0*u %7u  %s\n", tid,
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NS_TO_S_D(threads.data[j].exec_time - last_threads.data[i].exec_time),
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NS_TO_S_D(threads.data[j].delay_time - last_threads.data[i].delay_time),
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                threads.data[j].run_count - last_threads.data[i].run_count,
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NS_TO_S_D(threads.data[j].exec_time), NS_TO_S_D(threads.data[j].delay_time),
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                threads.data[j].run_count, threads.data[j].name);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void update_table(DIR *d, uint32_t flags)
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t i, j;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    rewinddir(d);
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while((de = readdir(d)) != 0){
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(isdigit(de->d_name[0])){
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int pid = atoi(de->d_name);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct thread_info *proc_info;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            add_thread(pid, 0, NULL);
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc_info = &processes.data[processes.active - 1];
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc_info->exec_time = 0;
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc_info->delay_time = 0;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc_info->run_count = 0;
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            add_threads(pid, proc_info);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!(flags & FLAG_BATCH))
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("\e[H\e[0J");
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("Processes: %d, Threads %d\n", processes.active, threads.active);
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch (time_dp) {
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 3:
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("   TID --- SINCE LAST ---- ---------- TOTAL ----------\n");
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("  PID  EXEC_T  DELAY SCHED EXEC_TIME DELAY_TIM   SCHED NAME\n");
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 6:
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("   TID ------ SINCE LAST -------    ------------ TOTAL -----------\n");
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("  PID  EXEC_TIME DELAY_TIM SCHED    EXEC_TIME   DELAY_TIME   SCHED NAME\n");
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default:
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("   TID    -------- SINCE LAST --------       ------------- TOTAL -------------\n");
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("  PID     EXEC_TIME   DELAY_TIME SCHED       EXEC_TIME      DELAY_TIME   SCHED NAME\n");
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < last_processes.active; i++) {
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int pid = last_processes.data[i].pid;
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int tid = last_processes.data[i].tid;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (j = 0; j < processes.active; j++)
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (pid == processes.data[j].pid)
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (j == processes.active)
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printf("%5u died\n", pid);
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if (!(flags & FLAG_HIDE_IDLE) || processes.data[j].run_count - last_processes.data[i].run_count) {
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printf("%5u  %2u.%0*u %2u.%0*u %5u %5u.%0*u %5u.%0*u %7u %s\n", pid,
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NS_TO_S_D(processes.data[j].exec_time - last_processes.data[i].exec_time),
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NS_TO_S_D(processes.data[j].delay_time - last_processes.data[i].delay_time),
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                processes.data[j].run_count - last_processes.data[i].run_count,
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NS_TO_S_D(processes.data[j].exec_time), NS_TO_S_D(processes.data[j].delay_time),
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                processes.data[j].run_count, processes.data[j].name);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (flags & FLAG_SHOW_THREADS)
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                print_threads(pid, flags);
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct thread_table tmp;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp = last_processes;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        last_processes = processes;
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        processes = tmp;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        processes.active = 0;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp = last_threads;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        last_threads = threads;
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        threads = tmp;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        threads.active = 0;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectsig_abort(int signum)
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("\e[?47l");
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(0);
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint schedtop_main(int argc, char **argv)
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int c;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *namefilter = 0;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pidfilter = 0;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t flags = 0;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int delay = 3000000;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    float delay_f;
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(1) {
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c = getopt(argc, argv, "d:ibtamun");
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (c == EOF)
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch (c) {
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'd':
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            delay_f = atof(optarg);
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            delay = delay_f * 1000000;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'b':
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            flags |= FLAG_BATCH;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'i':
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            flags |= FLAG_HIDE_IDLE;
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 't':
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            flags |= FLAG_SHOW_THREADS;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'a':
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            flags |= FLAG_USE_ALTERNATE_SCREEN;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'm':
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            time_dp = 3;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            time_div = 1000000;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'u':
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            time_dp = 6;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            time_div = 1000;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'n':
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            time_dp = 9;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            time_div = 1;
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d = opendir("/proc");
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(d == 0) return -1;
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!(flags & FLAG_BATCH)) {
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(flags & FLAG_USE_ALTERNATE_SCREEN) {
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            signal(SIGINT, sig_abort);
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            signal(SIGPIPE, sig_abort);
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            signal(SIGTERM, sig_abort);
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printf("\e7\e[?47h");
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("\e[2J");
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (1) {
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_table(d, flags);
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usleep(delay);
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(d);
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
337